ActiveMQ源码分析之Producer接收消息

ActiveMQ有三种消息发送方式,同步(syncSendPacket)、异步(asyncSendPacket)、单向(doOnewaySend)

同步:发送者发送消息给Broker,同步等待,当前线程会阻塞,直到Broker返回应答信息。

异步:发送者发送消息给Broker,消息发送线程不阻塞,继续执行下面的逻辑。由其他线程处理Broker返回的应答信息。

单向:发送者发送消息给Broker之后立即返回,不等待Broker端的应答响应,Broker端也不会有对应的响应信息。简单的说就是只管发送,不在乎是否有消息返回。

AMQ中Producer发送消息主要依靠ActiveMQConnection类,其中发送syncSendPacket方法主要发送同步请求,asyncSendPacket方法主要发送异步请求,下面就AMQ的同步请求和异步请求进行分析。

同步发送API核心入口:

public Response syncSendPacket(Command command, int timeout) throws JMSException

其中command是需要发送的请求内容,timeout是响应超时时间,不设置的话默认是0,该参数此时不起任何作用。

关于同步请求我们有三个地方需要注意 1、Broker同步响应  2、发送线程会阻塞  3、响应处理流程

public FutureResponse asyncRequest(Object o, ResponseCallback responseCallback) throws IOException {
        Command command = (Command) o;
        command.setCommandId(sequenceGenerator.getNextSequenceId());
        command.setResponseRequired(true);
        FutureResponse future = new FutureResponse(responseCallback, this);

其中command.setResponseRequired(true)表明Broker接收到请求之后要同步返回响应信息,是AMQ同步请求的标志。

public Object request(Object command) throws IOException {
        FutureResponse response = asyncRequest(command, null);
        return response.getResult();
}

而我们在发送请求之后会调用response.getResult()方法,该方法会调用阻塞队列responseSlot的take方法获取Broker返回的响应信息,如果这个时候还未收到应答信息则当前线程会处于一个阻塞状态,直到有消息返回为止。

接下来我们看下同步请求响应处理流程

ResponseCorrelator类的onCommand方法负责处理同步响应信息

public void onCommand(Object o) {
        Command command = null;
        if (o instanceof Command) {
            command = (Command)o;
        } else {
            throw new ClassCastException("Object cannot be converted to a Command,  Object: " + o);
        }
        if (command.isResponse()) {
            Response response = (Response)command;
            FutureResponse future = null;
            synchronized (requestMap) {
                future = requestMap.remove(Integer.valueOf(response.getCorrelationId()));
            }
            if (future != null) {
                future.set(response);

    。。。。。。。。省略

其中future.set(response)负责将应答信息设置到responseSlot队列中

public void set(Response result) {
        if (responseSlot.offer(result)) {
            if (responseCallback != null) {
                responseCallback.onCompletion(this);
            }
        }
 }

因为responseSlot是阻塞队列,因为队列中有数据进入,此时调用take方法阻塞的线程将会被唤醒,继续执行后面的逻辑。

异步发送核心API接口:

public void asyncSendPacket(Command command) throws JMSException
 public void oneway(Object o) throws IOException {
        Command command = (Command)o;
        command.setCommandId(sequenceGenerator.getNextSequenceId());
        command.setResponseRequired(false);
        next.oneway(command);
 }

其中command.setResponseRequired(false)是异步请求的标志,Broker收到请求之后,不会同步响应应答信息,Broker端具体实现后面详细分析。关于异步请求,我们重点关注响应处理流程

TcpTransport类的run方法负责Producer端所有的消息接收,原文描述为reads packets from a Socket。接下来消息会经过如下链式处理流程 AbstractInactivityMonitor------>MutexTransport------>ResponseCorrelator------>ActiveMQConnection

其中ResponseCorrelator类用于处理同步请求,所以接下来重点分析ActiveMQConnection类的处理流程

public void onCommand(final Object o) {
        final Command command = (Command)o;
        LOG.info("ActiveMQConnection onCommand: "  +  command);
        if (!closed.get() && command != null) {
            try {
                command.visit(new CommandVisitorAdapter() {
        


        。。。。。。省略

onCommand方法实际处理异步请求响应,此处command.visit(new CommandVisitorAdapter() {…})使用了适配器设计模式,关于MQ中的设计模式使用,后续会有一篇专题进行分析。处理的响应类型有processBrokerInfo ,processConnectionControl ,processWireFormat ,processMessageDispatch等。而其中processWireFormat 的作用就是把broker返回的protocolVersion 设置到客户端。其他响应类型处理流程也较简单,此处不再过多描述,关于processMessageDispatch处理流程会在消费者模块详细介绍。

最后是单向发送。AMQ中的单向发送最常见的应用场景就是心跳检测机制。AMQ的心跳检测机制依靠AbstractInactivityMonitor中的writeChecker和readChecker实现,其中writeChecker会调用doOnewaySend方法发送KeepAliveInfo信息到Broker端,用于保持跟Broker端的连接,而这个请求是不需要Broker端返回任何响应的,因此它是一个典型的单向发送。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值