activemq-broker接收消息


配置broker时,都会设置connector,connector内部会持有一个TransportServer,TransportServer相当于socketserver,transport相当于socket,connector启动(start)时会引发socketserver的启动(start),TcpTransportServer的主要职责就是accept(socketserver的主要职责就是accept)

 1 //org.apache.activemq.transport.tcp.TcpTransportServer的start
 2 protected void doStart() throws Exception {
 3   if (useQueueForAccept) {
 4     Runnable run = new Runnable() {
 5       @Override
 6       public void run() {
 7         try {
 8             //socketQueue是一个阻塞队列,不断的从socketQueue中获得socket,然后执行handleSocket方法
 9           while (!isStopped() && !isStopping()) {
10             Socket sock = socketQueue.poll(1, TimeUnit.SECONDS);
11             if (sock != null) {
12               try {
13                   //handleSocket最终会调用getAcceptListener().onAccept(configuredTransport)
14                 handleSocket(sock);
15               } catch (Throwable thrown) {
16                 if (!isStopping()) {
17                   onAcceptError(new Exception(thrown));
18                 } else if (!isStopped()) {
19                   LOG.warn("Unexpected error thrown during accept handling: ", thrown);
20                   onAcceptError(new Exception(thrown));
21                 }
22               }
23             }
24           }
25 
26         } catch (InterruptedException e) {
27           if (!isStopped() || !isStopping()) {
28             LOG.info("socketQueue interrupted - stopping");
29             onAcceptError(e);
30           }
31         }
32       }
33     };
34     socketHandlerThread = new Thread(null, run, "ActiveMQ Transport Server Thread Handler: " + toString(), getStackSize());
35     socketHandlerThread.setDaemon(true);
36     socketHandlerThread.setPriority(ThreadPriorities.BROKER_MANAGEMENT - 1);
37     //启动线程,该线程循环处理accept到的socket
38     socketHandlerThread.start();
39   }
40   //TcpTransportServer继承了TransportServerThreadSupport,其本身也持有持有一个线程,
41   //该线程用来执行的run逻辑,TcpTransportServer的run逻辑就是accept。
42   super.doStart();
43 }

 

TcpTransportServer启动后执行的run方法

 1 /**
 2 * 就是accept
 3 * pull Sockets from the ServerSocket
 4 */
 5 @Override
 6 public void run() {
 7   if (!isStopped() && !isStopping()) {
 8     final ServerSocket serverSocket = this.serverSocket;
 9     if (serverSocket == null) {
10       onAcceptError(new IOException("Server started without a valid ServerSocket"));
11     }
12         //channel不为null说明是nio
13     final ServerSocketChannel channel = serverSocket.getChannel();
14     if (channel != null) {
15         //nio
16       doRunWithServerSocketChannel(channel);
17     } else {
18         //以bio为例
19       doRunWithServerSocket(serverSocket);
20     }
21   }
22 }

TcpTransportServer的run方法就是accept

 1 private void doRunWithServerSocket(final ServerSocket serverSocket) {
 2   while (!isStopped()) {
 3       //accept
 4     Socket socket = serverSocket.accept();
 5     if (socket != null) {
 6       if (isStopped() || getAcceptListener() == null) {
 7         socket.close();
 8       } else {
 9           //默认useQueueForAccept为true,socketQueue中的Socket最终会由socketHandlerThread取出并执行handleSocket(socket),
10           //handleSocket最终会调用getAcceptListener().onAccept(configuredTransport)。
11         if (useQueueForAccept) {
12           socketQueue.put(socket);
13         } else {
14             //handleSocket最终会调用getAcceptListener().onAccept(configuredTransport)
15           handleSocket(socket);
16         }
17       }
18     }
19   }
20 }

 

在org.apache.activemq.broker.TransportConnector启动时,设置了AcceptListener(getServer().setAcceptListener)该AcceptListener的主要逻辑:

 1 brokerService.getTaskRunnerFactory().execute(new Runnable() {
 2   @Override
 3   public void run() {
 4     try {
 5       if (!brokerService.isStopping()) {
 6           //transport中含有Socket,transport代表client
 7         Connection connection = createConnection(transport);
 8         //connection.start会执行transport.start,TcpTransport继承了TransportServerThreadSupport,
 9         //start会开启该线程的执行逻辑,即TcpTransport的run方法,阻塞读取socket数据。
10         connection.start();
11       } else {
12         throw new BrokerStoppedException("Broker " + brokerService + " is being stopped");
13       }
14     } catch (Exception e) {
15       String remoteHost = transport.getRemoteAddress();
16       ServiceSupport.dispose(transport);
17       onAcceptError(e, remoteHost);
18     }
19   }
20 });

accept到的socket被包装为TcpTransport,并start该Transport,socket就可以开始读数据了

 1 //TcpTransport的run方法会调用doRun
 2 protected void doRun() throws IOException {
 3   try {
 4       //从Socket读数据
 5     Object command = readCommand();
 6     doConsume(command);//执行命令,比如如果该command是一个Message,则会将其放入对应的destination
 7   } catch (SocketTimeoutException e) {
 8   } catch (InterruptedIOException e) {
 9   }
10 }

 

小结:connector.start引发了TransportServer的start,TransportServer的start主要就是socketserver.accept(在独立线程中),accept到的socket可以放入队列异步处理,也可以同步处理(在accept所在线程中),二者的执行逻辑是一致的,都会将socket封装成transport,再将transport封装成connection后进行connection.start,这就开始阻塞读了(transport会持有一个独立线程,阻塞读就在该线程中)。

 

TcpTransport的读线程会阻塞在readCommand上,当client有数据传来时,readCommand会读取数据,并将其unmarshal为activemq的命令对象,然后再doConsume该对象。doConsume最终会调用broker(TransportConnection持有broker)的相关方法(比如,如果command是Message,就会调用broker.send(producerExchange, messageSend);),这就将Message交由broker处理了(接收client发来的命令并不属于broker的职责,broker真正要做的是将处理这些命令,比如将消息路由置对应的destination,而接收client命令的任务是由TransportServer完成的)。

 

posted @ 2017-09-03 23:22  holoyong  阅读(3199)  评论(0编辑  收藏  举报