大家好,上一次分析了注册流程 这次就开始分析下接收处理过程。贴图

rocketmq broker 第三章接收处理1_第1张图片

1,this.defaultEventExecutorGroup = new DefaultEventExecutorGroup(//
            nettyServerConfig.getServerWorkerThreads(), //
            new ThreadFactory() {

                private AtomicInteger threadIndex = new AtomicInteger(0);


                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r, "NettyServerWorkerThread_" + this.threadIndex.incrementAndGet());
                }
            });
   默认事件线程组

   1.1,ServerBootstrap childHandler = //
                this.serverBootstrap.group(this.eventLoopGroupBoss, this.eventLoopGroupWorker)
                    .channel(NioServerSocketChannel.class)
                    //使用NIO selector

                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //输入连接指示(对连接的请求)的最大队列长度被设置为 backlog 参数。如果队列满时收到连接指示,则拒绝该连接

                    .option(ChannelOption.SO_REUSEADDR, true)
                    //设置了SO_REUSADDR的应用可以避免TCP 的 TIME_WAIT 状态 时间过长无法复用端口

                    .option(ChannelOption.SO_KEEPALIVE, false)
                    //设置心跳参数 FALSE为不启用参数                   

                    .childOption(ChannelOption.TCP_NODELAY, true)
                    //开启TCP_NODELAY表示package被忽略size尽快地发送。

                    .option(ChannelOption.SO_SNDBUF, nettyServerConfig.getServerSocketSndBufSize())
                    //socket发送缓冲区大小

                    .option(ChannelOption.SO_RCVBUF, nettyServerConfig.getServerSocketRcvBufSize())
                    //socket接收缓冲区大小

                    .localAddress(new InetSocketAddress(this.nettyServerConfig.getListenPort()))

                    //localAddress方法用于绑定服务器地址和端口

                    .childHandler(new ChannelInitializer() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(
                                //
                                defaultEventExecutorGroup, //默认事件接收线程组

                                new NettyEncoder(), //netty编码器

                                new NettyDecoder(), //netty×××

                                new IdleStateHandler(0, 0, nettyServerConfig
                                    .getServerChannelMaxIdleTimeSeconds()),//

                                空闲链路状态处理

                                new NettyConnetManageHandler(), //自实现空闲链路处理

                                new NettyServerHandler());netty服务处理

                        }
                    });

   1.2,if (nettyServerConfig.isServerPooledByteBufAllocatorEnable()) {
            // 这个选项有可能会占用大量堆外内存,暂时不使用。
            childHandler.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
         }

         是否启用推外内存,默认不使用

   1.3,ChannelFuture sync = this.serverBootstrap.bind().sync();
        InetSocketAddress addr = (InetSocketAddress) sync.channel().localAddress();
        this.port = addr.getPort();

        绑定netty监听端口

       

        if (this.channelEventListener != null) {
            this.nettyEventExecuter.start();
        }

        启动netty事件处理线程

2,当有请求连接的时候,步骤如下

   2.1,public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
            final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel());
            log.info("NETTY SERVER PIPELINE: channelRegistered {}", remoteAddress);
            super.channelRegistered(ctx);
        }

        channel注册

   2.2,public void channelActive(ChannelHandlerContext ctx) throws Exception {
            final String remoteAddress = RemotingHelper.parseChannelRemoteAddr(ctx.channel());
            log.info("NETTY SERVER PIPELINE: channelActive, the channel[{}]", remoteAddress);
            super.channelActive(ctx);

            if (NettyRemotingServer.this.channelEventListener != null) {
                NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.CONNECT, remoteAddress
                    .toString(), ctx.channel()));
            }
        }

        channel激活后放入连接事件到NettyEventExecuter.LinkedBlockingQueue队列里,由NettyEventExecuter线程取队列数据(先进先出)

        NettyEvent event = this.eventQueue.poll(3000, TimeUnit.MILLISECONDS);

        switch (event.getType()) {
            case IDLE:当空闲链路达到serverChannelMaxIdleTimeSeconds(默认120秒)会触发这个事件处理.

        listener.onChannelIdle(event.getRemoteAddr(), event.getChannel());
                            break;


        this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
        this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
        this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);

        通知producer,consumer,filterServer移除channel



            case CLOSE:当channel关闭的时候会触发这个事件处理.

               listener.onChannelClose(event.getRemoteAddr(), event.getChannel());
                            break;

        this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
        this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
        this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);

        通知producer,consumer,filterServer移除channel


            case CONNECT:当有新连接的时候会触发这个事件处理.
               listener.onChannelConnect(event.getRemoteAddr(), event.getChannel());
                            break;


           case EXCEPTION:当channel发生异常的时候会发生这个事件处理.
               listener.onChannelException(event.getRemoteAddr(), event.getChannel());
                            break;


        this.brokerController.getProducerManager().doChannelCloseEvent(remoteAddr, channel);
        this.brokerController.getConsumerManager().doChannelCloseEvent(remoteAddr, channel);
        this.brokerController.getFilterServerManager().doChannelCloseEvent(remoteAddr, channel);

       通知producer,consumer,filterServer移除channel

   2.3,this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    ClientHousekeepingService.this.scanExceptionChannel();

      this.brokerController.getProducerManager().scanNotActiveChannel();
      this.brokerController.getConsumerManager().scanNotActiveChannel();
      this.brokerController.getFilterServerManager().scanNotActiveChannel();     

      通知producer,consumer,filterServer移除未活动,过期channel

          }
                catch (Exception e) {
                    log.error("", e);
                }
            }
        }, 1000 * 10, 1000 * 10, TimeUnit.MILLISECONDS);

3,NettyDecoder.decode 解码

       ByteBuf frame = null;
       try {
           frame = (ByteBuf) super.decode(ctx, in);
           if (null == frame) {
              return null;
        }
        ByteBuffer byteBuffer = frame.nioBuffer();
        return RemotingCommand.decode(byteBuffer);

        解码为remotingCommand对象,实现如下:


        int length = byteBuffer.limit();获取总length
        int headerLength = byteBuffer.getInt();

        byte[] headerData = new byte[headerLength];
        byteBuffer.get(headerData);获取header数据

        int bodyLength = length - 4 - headerLength;body总length
        byte[] bodyData = null;
        if (bodyLength > 0) {
            bodyData = new byte[bodyLength];
            byteBuffer.get(bodyData);获取body数据
        }

        RemotingCommand cmd = RemotingSerializable.decode(headerData, RemotingCommand.class);

        内部实现用fastJson序列化为RemotingCommand

        cmd.body = bodyData;
     
        return cmd;


4,NettyServerHandler.channelRead0 反序列化后处理过程

  final RemotingCommand cmd = msg;
        if (cmd != null) {
            switch (cmd.getType()) { 根据command type判断是请求
            case REQUEST_COMMAND:
                proce***equestCommand(ctx, cmd);
                break;
            case RESPONSE_COMMAND:
                proce***esponseCommand(ctx, cmd);
                break;
            default:
                break;
            }
   }