rabbitmq学习7:ConntectionFactory与Conntection的认知

 

  从前面几小节的学习,我们可能知道在发送和接收消息重要的类ConnectionFactory, Connection,Channel和 QueueingConsumer。

  ConntectionFactory类是方便创建与AMQP代理相关联的Connection;下面来看看ConntectionFactory是如何创建一个Contention.

  首先通过new ConnectionFactory()创建一个ConnectionFactory;并设置此连接工厂的主机设置为localhost。通过ConnectionFactory的newConnection()方法 创建一个Connection; newConnection方法通过得到当前连接的地址及端口号来获得一个Address,通过createFrameHandler的方法 来得到FrameHandler;再通过new AMQConnection(this, frameHandler)来得到Connection并启动。如代码清单7-1所示。

    代码清单7-1 创建Connection的源码(ConnectionFactory.java中)

 

   1. protected FrameHandler createFrameHandler(Address addr)  
   2.         throws IOException {  
   3.   
   4.         String hostName = addr.getHost();  
   5.         int portNumber = portOrDefault(addr.getPort());//得到端口号  
   6.         Socket socket = factory.createSocket();  
   7.         configureSocket(socket);//这里Socket通过TCP无迟延的协议  
   8.         socket.connect(new InetSocketAddress(hostName, portNumber), connectionTimeout);  
   9.         return createFrameHandler(socket);  
  10.     }  
  11.   
  12.     protected FrameHandler createFrameHandler(Socket sock)  
  13.         throws IOException  
  14.     {  
  15.         return new SocketFrameHandler(sock);  
  16.     }  
  17.   
  18.     /** 
  19.      *  Provides a hook to insert custom configuration of the sockets 
  20.      *  used to connect to an AMQP server before they connect. 
  21.      * 
  22.      *  The default behaviour of this method is to disable Nagle's 
  23.      *  algorithm to get more consistently low latency.  However it 
  24.      *  may be overridden freely and there is no requirement to retain 
  25.      *  this behaviour. 
  26.      * 
  27.      *  @param socket The socket that is to be used for the Connection 
  28.      */  
  29.     protected void configureSocket(Socket socket) throws IOException{  
  30.         // disable Nagle's algorithm, for more consistently low latency  
  31.         socket.setTcpNoDelay(true);  
  32.     }  
  33.   
  34.     /** 
  35.      * Create a new broker connection 
  36.      * @param addrs an array of known broker addresses (hostname/port pairs) to try in order 
  37.      * @return an interface to the connection 
  38.      * @throws IOException if it encounters a problem 
  39.      */  
  40.     public Connection newConnection(Address[] addrs)  
  41.         throws IOException  
  42.     {  
  43.         IOException lastException = null;  
  44.         for (Address addr : addrs) {  
  45.             try {  
  46.                 FrameHandler frameHandler = createFrameHandler(addr);  
  47.                 AMQConnection conn = new AMQConnection(this,  
  48.                                                        frameHandler);  
  49.                 conn.start();  
  50.                 return conn;  
  51.             } catch (IOException e) {  
  52.                 lastException = e;  
  53.             }  
  54.         }  
  55.   
  56.         if (lastException == null) {  
  57.             throw new IOException("failed to connect");  
  58.         } else {  
  59.             throw lastException;  
  60.         }  
  61.     }  
  62.   
  63.     /** 
  64.      * Create a new broker connection 
  65.      * @return an interface to the connection 
  66.      * @throws IOException if it encounters a problem 
  67.      */  
  68.     public Connection newConnection() throws IOException {  
  69.         return newConnection(new Address[] {  
  70.                                  new Address(getHost(), getPort())});  
  71.     }  

 

代码清单7-2 连接启动

 

/**
     * 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 heartbeat
     * and frame max values after tuning has taken place.
     * @throws java.io.IOException if an error is encountered; IOException
     * subtypes {@link ProtocolVersionMismatchException} and
     * {@link PossibleAuthenticationFailureException} will be thrown in the
     * corresponding circumstances.
     */
    public void start()
        throws IOException
    {
        // 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);
        // The following two lines are akin to AMQChannel's
        // transmit() method for this pseudo-RPC.
        _frameHandler.setTimeout(HANDSHAKE_TIMEOUT);
        _frameHandler.sendHeader();

        // start the main loop going
        Thread ml = new MainLoop();
        ml.setName("AMQP Connection " + getHostAddress() + ":" + getPort());
        ml.start();

        AMQP.Connection.Start connStart = null;
        try {
            connStart =
                (AMQP.Connection.Start) connStartBlocker.getReply().getMethod();

            _serverProperties = connStart.getServerProperties();

            Version serverVersion =
                new Version(connStart.getVersionMajor(),
                            connStart.getVersionMinor());

            if (!Version.checkVersion(clientVersion, serverVersion)) {
                _frameHandler.close(); //this will cause mainLoop to terminate
                throw new ProtocolVersionMismatchException(clientVersion,
                                                           serverVersion);
            }
        } catch (ShutdownSignalException sse) {
            throw AMQChannel.wrap(sse);
        }

        String[] mechanisms = connStart.getMechanisms().toString().split(" ");
        SaslMechanism sm = _factory.getSaslConfig().getSaslMechanism(mechanisms);
        if (sm == null) {
            throw new IOException("No compatible authentication mechanism found - " +
                    "server offered [" + connStart.getMechanisms() + "]");
        }

        LongString challenge = null;
        LongString response = sm.handleChallenge(null, _factory);

        AMQP.Connection.Tune connTune = null;
        do {
            Method method = (challenge == null)
                ? new AMQImpl.Connection.StartOk(_clientProperties,
                                                 sm.getName(),
                                                 response, "en_US")
                : new AMQImpl.Connection.SecureOk(response);

            try {
                Method serverResponse = _channel0.rpc(method).getMethod();
                if (serverResponse instanceof AMQP.Connection.Tune) {
                    connTune = (AMQP.Connection.Tune) serverResponse;
                } else {
                    challenge = ((AMQP.Connection.Secure) serverResponse).getChallenge();
                    response = sm.handleChallenge(challenge, _factory);
                }
            } catch (ShutdownSignalException e) {
                throw new PossibleAuthenticationFailureException(e);
            }
        } while (connTune == null);

        int channelMax =
            negotiatedMaxValue(_factory.getRequestedChannelMax(),
                               connTune.getChannelMax());
        _channelManager = new ChannelManager(channelMax);

        int frameMax =
            negotiatedMaxValue(_factory.getRequestedFrameMax(),
                               connTune.getFrameMax());
        setFrameMax(frameMax);

        int heartbeat =
            negotiatedMaxValue(_factory.getRequestedHeartbeat(),
                               connTune.getHeartbeat());
        setHeartbeat(heartbeat);

        _channel0.transmit(new AMQImpl.Connection.TuneOk(channelMax,
                                                         frameMax,
                                                         heartbeat));
        // 0.9.1: insist [on not being redirected] is deprecated, but
        // still in generated code; just pass a dummy value here
        _channel0.exnWrappingRpc(new AMQImpl.Connection.Open(_virtualHost,
                                                            "",
                                                            false)).getMethod();
        return;
    }
 

 

你可能感兴趣的:(rabbitmq学习7:ConntectionFactory与Conntection的认知)