• RocketMQ(三) RemotingServer服务端启动 源码分析


    RocketMQ(三) - RemotingServer服务端启动 源码分析

    接着 《 RocketMQ(一) - NameServer 启动源码分析 》 文章最后留下的 RemotingServer网络层服务端启动 来进行分析。

    继承体系

    为了 更好的从 宏观上 分析RocketMQ 的 网络层对象,我们要将 服务端 与 客户端一起来分析继承体系。

    服务端 NettyRemotingServer

    客户端 NettyRemotingClient

    由上面 客户端 与 服务端 类继承图 可以知道:

    共同点: 继承了 NettyRemotingAbstract抽象类 , 实现了 RemotingService接口

    不同点: 实现了 RemotingServerRemotingClient接口

    该小结我们着重介绍 RemotingService接口 ,RemotingServer接口 下的方法作用。

    到了之后讲解 有关 客户端的代码时,其中有些相同点就不会再继续赘述了。

    RemotingService

    public interface RemotingService {
        
        // 服务启动
        void start();
    
        // 服务关闭
        void shutdown();
    
        // 注册 RPCHook  钩子
        void registerRPCHook(RPCHook rpcHook);
    }
    

    RemotingServer

    public interface RemotingServer extends RemotingService {
    
        /**
         *  注册处理器
         * @param requestCode   请求码
         * @param processor     处理器
         * @param executor      线程池
         *    这三者是绑定关系:
         *       根据请求的code  找到处理对应请求的处理器与线程池 并完成业务处理。
         */
        void registerProcessor(final int requestCode, final NettyRequestProcessor processor,
            final ExecutorService executor);
    
    
        /**
         *  注册缺省处理器
         * @param processor  缺省处理器
         * @param executor   线程池
         */
        void registerDefaultProcessor(final NettyRequestProcessor processor, final ExecutorService executor);
    
        // 获取服务端口
        int localListenPort();
    
    
        /**
         *  根据 请求码 获取 处理器和线程池
         * @param requestCode  请求码
         * @return
         */
        Pair<NettyRequestProcessor, ExecutorService> getProcessorPair(final int requestCode);
    
        /**
         *  同步调用
         * @param channel   通信通道
         * @param request   业务请求对象
         * @param timeoutMillis   超时时间
         * @return  响应结果封装
         */
        RemotingCommand invokeSync(final Channel channel, final RemotingCommand request,
            final long timeoutMillis) throws InterruptedException, RemotingSendRequestException,
            RemotingTimeoutException;
    
        /**
         *  异步调用
         * @param channel  通信通道
         * @param request  业务请求对象
         * @param timeoutMillis  超时时间
         * @param invokeCallback  响应结果回调对象
         */
        void invokeAsync(final Channel channel, final RemotingCommand request, final long timeoutMillis,
            final InvokeCallback invokeCallback) throws InterruptedException,
            RemotingTooMuchRequestException, RemotingTimeoutException, RemotingSendRequestException;
    
    
        /**
         *  单向调用 (不关注返回结果)
         * @param channel   通信通道
         * @param request   业务请求对象
         * @param timeoutMillis  超时时间
         */
        void invokeOneway(final Channel channel, final RemotingCommand request, final long timeoutMillis)
            throws InterruptedException, RemotingTooMuchRequestException, RemotingTimeoutException,
            RemotingSendRequestException;
    }
    

    以上的接口方法大致就分为两部分:

    1. 注册请求协议处理器 ( requestCode , proccessor, executor )
    2. 请求调用方法:
      1. 同步请求调用
      2. 异步请求调用
      3. 单向请求调用

    上面分析了 接口中的方法, 而抽象类NettyRemotingAbstract 将在后面分析 NettyRemotingServer的时候带着去讲解。

    老套路,下面来看下 NettyRemotingServer 的 属性和构造方法。

    属性和构造器

    public class NettyRemotingServer extends NettyRemotingAbstract implements RemotingServer {
        private static final InternalLogger log = InternalLoggerFactory.getLogger(RemotingHelper.ROCKETMQ_REMOTING);
    
      	// Netty服务端启动器
        private final ServerBootstrap serverBootstrap;
      	
        // worker组
        private final EventLoopGroup eventLoopGroupSelector;
      
        // boss组 
        private final EventLoopGroup eventLoopGroupBoss;
    
        // Netty服务端配置信息类
        private final NettyServerConfig nettyServerConfig;
    
     	// 公共线程池   (在注册协议处理器的时候,若未给处理器指定线程池,那么就是用该公共线程池)
        private final ExecutorService publicExecutor;
    
    	
        //  Netty Channel 特殊状态监听器
        private final ChannelEventListener  channelEventListener;
    
      	// 定时器  (功能: 扫描 responseTable表,将过期的responseFuture移除)
        private final Timer timer = new Timer("ServerHouseKeepingService", true);
    
        // 用于在pipeline指定handler中 执行任务的线程池
        private DefaultEventExecutorGroup defaultEventExecutorGroup;
    
     	// 服务端绑定的端口
        private int port = 0;
    
        private static final String HANDSHAKE_HANDLER_NAME = "handshakeHandler";
        private static final String TLS_HANDLER_NAME = "sslHandler";
        private static final String FILE_REGION_ENCODER_NAME = "fileRegionEncoder";
    
      	
        // 用于处理 SSL 握手连接的处理器
        private HandshakeHandler handshakeHandler;
        
        // 协议编码 处理器
        private NettyEncoder encoder;
        
        // 连接管理 处理器
        private NettyConnectManageHandler connectionManageHandler;
        
        // 核心业务 处理器
        private NettyServerHandler serverHandler;
    
    
    	// 参数1: nettyServerConfig  Netty服务端配置信息
        // 参数2: channelEventListener  channel特殊状态监听器
        public NettyRemotingServer(final NettyServerConfig nettyServerConfig,
            final ChannelEventListener channelEventListener) {
    		
            // 调用父类  就是通过 Semaphore 设置请求并发限制
            // 1. 设置 单行请求的并发限制
            // 2. 设置 异步请求的并发限制
            super(nettyServerConfig.getServerOnewaySemaphoreValue(), nettyServerConfig.getServerAsyncSemaphoreValue());
    
    		
            
            this.serverBootstrap = new ServerBootstrap();
            this.nettyServerConfig = nettyServerConfig;
            this.channelEventListener = channelEventListener;
    
    
           
            // 创建公共线程池 publicExecutor   线程数量为:4
            int publicThreadNums = nettyServerConfig.getServerCallbackExecutorThreads();
            if (publicThreadNums <= 0) {
                publicThreadNums = 4;
            }
            this.publicExecutor = Executors.newFixedThreadPool(publicThreadNums, new ThreadFactory() {
                private AtomicInteger threadIndex = new AtomicInteger(0);
    
                @Override
                public Thread newThread(Runnable r) {
                    return new Thread(r, "NettyServerPublicExecutor_" + this.threadIndex.incrementAndGet());
                }
            });
    
        
            
            // 下面就是根据操作系统平台来选择创建 bossGroup 和 workGroup的逻辑
            if (useEpoll()) {
                this.eventLoopGroupBoss = new EpollEventLoopGroup(1, new ThreadFactory() {
                    private AtomicInteger threadIndex = new AtomicInteger(0);
    
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, String.format("NettyEPOLLBoss_%d", this.threadIndex.incrementAndGet()));
                    }
                });
    
                this.eventLoopGroupSelector = new EpollEventLoopGroup(nettyServerConfig.getServerSelectorThreads(), new ThreadFactory() {
                    private AtomicInteger threadIndex = new AtomicInteger(0);
                    private int threadTotal = nettyServerConfig.getServerSelectorThreads();
    
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, String.format("NettyServerEPOLLSelector_%d_%d", threadTotal, this.threadIndex.incrementAndGet()));
                    }
                });
            } else {
                this.eventLoopGroupBoss = new NioEventLoopGroup(1, new ThreadFactory() {
                    private AtomicInteger threadIndex = new AtomicInteger(0);
    
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, String.format("NettyNIOBoss_%d", this.threadIndex.incrementAndGet()));
                    }
                });
    
                this.eventLoopGroupSelector = new NioEventLoopGroup(nettyServerConfig.getServerSelectorThreads(), new ThreadFactory() {
                    private AtomicInteger threadIndex = new AtomicInteger(0);
                    private int threadTotal = nettyServerConfig.getServerSelectorThreads();
    
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, String.format("NettyServerNIOSelector_%d_%d", threadTotal, this.threadIndex.incrementAndGet()));
                    }
                });
            }
    		
            
            // 加载SSL连接的相关方法 (不在本篇的分析范围内)
            loadSslContext();
        }
    }
    

    上述代码中,构造方法 实际上就是为 一些属性变量附上了值:

    1. 父类的属性 semaphoreOneway , **semaphoreAsync ** 用来控制请求并发量的
    2. serverBootstrap Netty服务器启动器
    3. nettyServerConfig Netty服务器配置信息
    4. channelEventListener Netty Channel状态监听器
    5. eventLoopGroupSelector worker组
    6. eventLoopGroupBoss boss组

    在看一下父类 **NettyRemotingAbstract ** 中的 属性

    public abstract class NettyRemotingAbstract {
    
    
    	// 控制 单向请求的 并发量
        protected final Semaphore semaphoreOneway;
    
        // 控制 异步请求的 并发量
        protected final Semaphore semaphoreAsync;
    
    	// 响应对象映射表  (key: opaque  value:responseFuture)
        protected final ConcurrentMap<Integer /* opaque */, ResponseFuture> responseTable =
            new ConcurrentHashMap<Integer, ResponseFuture>(256);
    
    	// 请求处理器映射表 (key: requestCode  value:(processor,executor)  )
        protected final HashMap<Integer/* request code */, Pair<NettyRequestProcessor, ExecutorService>> processorTable =
            new HashMap<Integer, Pair<NettyRequestProcessor, ExecutorService>>(64);
    
    	// Netty事件监听线程池
        protected final NettyEventExecutor nettyEventExecutor = new NettyEventExecutor();
    
    	
        // 默认的请求处理器对  包含(processor,executor) 
        protected Pair<NettyRequestProcessor, ExecutorService> defaultRequestProcessor;
    	
        // SSL相关
        protected volatile SslContext sslContext;
    
    	
        // 扩展钩子
        protected List<RPCHook> rpcHooks = new ArrayList<RPCHook>();
    }
    

    在父类中 存储的 是相对 更加业务层的 对象,其中有两个尤为重要:

    1. responseTable 响应对象映射表
    2. processorTable 请求处理器映射表

    服务器启动

    之前讲解的 NameServer启动的文章中,最终留下了就是本篇 网络层服务启动的入口, NettyRemotingServer # start

        // 启动Netty 服务器
        @Override
        public void start() {
            
            // Netty pipeline中的指定 handler 采用该线程池执行
            this.defaultEventExecutorGroup = new DefaultEventExecutorGroup(
                nettyServerConfig.getServerWorkerThreads(),
                new ThreadFactory() {
    
                    private AtomicInteger threadIndex = new AtomicInteger(0);
    
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, "NettyServerCodecThread_" + this.threadIndex.incrementAndGet());
                    }
                });
    
            // 初始化 处理器 handler
            // 1. handshakeHandler  SSL连接
            // 2. encoder  编码器
            // 3. connectionManageHandler 连接管理器处理器
            // 4. serverHandler 核心业务处理器
            prepareSharableHandlers();
    		
            // 下面就是 Netty 创建服务端启动器的固定流程 
            
            ServerBootstrap childHandler =
                    // 配置服务端 启动对象
                    // 配置工作组 boss 和 worker 组
                this.serverBootstrap.group(this.eventLoopGroupBoss, this.eventLoopGroupSelector)
                        // 设置服务端ServerSocketChannel 类型
                    .channel(useEpoll() ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
                        // 设置服务端ch选项
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .option(ChannelOption.SO_REUSEADDR, true)
                    .option(ChannelOption.SO_KEEPALIVE, false)
                        // 设置客户端ch选项
                    .childOption(ChannelOption.TCP_NODELAY, true)
                        // 设置 接收缓冲区 和 发送缓冲区的 大小
                    .childOption(ChannelOption.SO_SNDBUF, nettyServerConfig.getServerSocketSndBufSize())
                    .childOption(ChannelOption.SO_RCVBUF, nettyServerConfig.getServerSocketRcvBufSize())
    
                        // 设置服务器端口
                    .localAddress(new InetSocketAddress(this.nettyServerConfig.getListenPort()))
    
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
              // 初始化 客户端ch pipeline 的逻辑, 同时指定了线程池为 defaultEventExecutorGroup
                            ch.pipeline()
                                .addLast(defaultEventExecutorGroup, HANDSHAKE_HANDLER_NAME, handshakeHandler)
                                .addLast(defaultEventExecutorGroup,
                                    encoder,
                                    new NettyDecoder(),
                                    new IdleStateHandler(0, 0, nettyServerConfig.getServerChannelMaxIdleTimeSeconds()),
                                    connectionManageHandler,
                                    serverHandler
                                );
                        }
                    });
    
    		
            if (nettyServerConfig.isServerPooledByteBufAllocatorEnable()) {
                // 客户端开启 内存池,使用的内存池 是 PooledByteBufAllocator.DEFAULT
                childHandler.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
            }
    
            try {
                //  服务器 绑定端口
                ChannelFuture sync = this.serverBootstrap.bind().sync();
                InetSocketAddress addr = (InetSocketAddress) sync.channel().localAddress();
                this.port = addr.getPort();
            } catch (InterruptedException e1) {
                throw new RuntimeException("this.serverBootstrap.bind().sync() InterruptedException", e1);
            }
    
            // 条件成立: channel状态监听器不为空, 则创建 网络异常事件执行器
            if (this.channelEventListener != null) {
                this.nettyEventExecutor.start();
            }
    
            // 提交定时任务,每一秒 执行一次
            // 扫描 responseTable 表, 将过期的 responseFuture 移除
            this.timer.scheduleAtFixedRate(new TimerTask() {
    
                @Override
                public void run() {
                    try {
                        NettyRemotingServer.this.scanResponseTable();
                    } catch (Throwable e) {
                        log.error("scanResponseTable exception", e);
                    }
                }
            }, 1000 * 3, 1000);
        }
    

    上述代码 基本上就是 模板Netty创建服务端的代码,主要做了如下几件事:

    1. 启动Netty服务器
    2. 开启 channel状态监听线程
    3. 开启 扫描 responseFuture 的定时任务

    总结

    RocketMQ 的 NameServer 服务端启动, 所做的事情,全都总结为下图:

  • 相关阅读:
    21班考试总结
    性别
    2019.08.20上课笔记2
    2019.08.20上课笔记3
    2019.08.20上课笔记1
    单词2
    数据类和运算符
    2019.08.14单词1
    2019.08.14上课笔记1
    request.get... getHeader 能取得的信息 参数
  • 原文地址:https://www.cnblogs.com/s686zhou/p/15924230.html
Copyright © 2020-2023  润新知