RabbitMQ-客户端源码之AMQConnection

本文详细分析了RabbitMQ客户端AMQConnection的start()方法,讲解了如何启动连接,包括MainLoop线程的启动,AMQP协议的negoitation过程,以及对心跳线程、工作线程池的初始化。文中提到了Connection.Start, Connection.Tune等帧的处理,并解释了如何根据broker的回复设置参数。此外,还探讨了SimpleBlockingRpcContinuation在RPC调用中的作用,以及MainLoop线程如何处理通信帧。" 123181672,7974618,TCP三次握手与丢包处理,"['tcp/ip', '网络', '服务器']
摘要由CSDN通过智能技术生成

首先来看看start()方法的源码,这个方法有点长,这里拆开来一一分析,首先是注释:

/**
 * Start up the connection, including the MainLoop thread.
 * Sends the protocol
 * version negotiation header, and runs through
 * Connection.Start/.StartOk, Connection.Tune/.TuneOk, and then
 * calls Connection.Open and waits for the OpenOk. Sets heart-beat
 * and frame max values after tuning has taken place.
 * @throws IOException if an error is encountered
 * either before, or during, protocol negotiation;
 * sub-classes {@link ProtocolVersionMismatchException} and
 * {@link PossibleAuthenticationFailureException} will be thrown in the
 * corresponding circumstances. {@link AuthenticationFailureException}
 * will be thrown if the broker closes the connection with ACCESS_REFUSED.
 * If an exception is thrown, connection resources allocated can all be
 * garbage collected when the connection object is no longer referenced.
 */

首先来看看方法上的注释说了什么:

  • 方法的作用是启动连接(start up the connection), 包括启动MainLoop线程,这个MainLoop线程主要是和broker进行通信交互处理通信帧(Frame)的一个线程(非常的重要!!!)。
  • 这个方法会在建立连接的初始化阶段(negotiation)会进行Connection.Start/.StartOk, Connection.Tune/.TuneOk, 调用Connection.Open之后再等待Conenction.OpenOk(这里的都是指AMQP协议层面的),这个可以参考本文中第一张使用wireshark抓包的网络截图,一一对应的关系。
  • 通过broker回复的Connection.Tune帧(帧中包含Channel-Max, Frame-Max, Heartbeat三个参数)设置channelMax, frameMax以及Heartbeat的参数值。
  • 一些异常情况。

public void start()
        throws IOException, TimeoutException {
    initializeConsumerWorkService();
    initializeHeartbeatSender();
    this._running = true;
    // Make sure that the first thing we do is to send the header,
    // which should cause any socket errors to show up for us, rather
    // than risking them pop out in the MainLoop
    AMQChannel.SimpleBlockingRpcContinuation connStartBlocker =
        new AMQChannel.SimpleBlockingRpcContinuation();
    // We enqueue an RPC continuation here without sending an RPC
    // request, since the protocol specifies that after sending
    // the version negotiation header, the client (connection
    // initiator) is to wait for a connection.start method to
    // arrive.
    _channel0.enqueueRpc(connStartBlocker);

首先是初始化工作线程池(initializeConsumerWorkService)和初始化心跳线程(initializeHeartbeatSender)并设置运行状态为true(this._isrunning=true,这个值会在MainLoop线程中有用,控制MainLoop线程是否继续运行)。

“AMQChannel.SimpleBlockingRpcContinuation connStartBlocker = new AMQChannel.SimpleBlockingRpcContinuation();”这句代码,从命名上来说像是rpc, 其实这么理解也没错。RabbitMQ-Client这个版本(3.5.3)的客户端与broker端的通信是采用java原生socket.当然后面也改成了NIO,这个自然是后话。RabbitMQ-Client程序中会对各种帧进行处理,处理的方式也不是单一化的,这里举Connection.Start这个类型的报文做分析。当broker发送Connection.Start至client端,client收到之后进行处理(MainLoop线程中),然后将此报文存入SimpleBlockingRpcContinuation中,照着SimpleBlockingRpcContinuation深究下去,其就是一个容量为1的BlockingQueue,也就是当MainLoop主导的线程将收到的Connection.Start存入其中,然后AMQConnction类的start()线程在等待(start()方法下面的代码):

connStart = (AMQP.Connection.Start) connStartBlocker.get
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值