源码分析RocketMQ之Broker-消息接收
1、Broker 的启动会调用BrokerStartup.start(),方法里调用NettyRemotingServer.start,进行netty的启动
通过netty进行消息接收和处理。
2、netty启动初始化,在执行业务逻辑前要进行SSL验证、编解码、空闲检查、网络连接管理
//在真正执行业务逻辑之前需要进行 SSL 验证、编解码、空闲检查、网络连接管理
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());
}
});
prepareSharableHandlers();
ServerBootstrap childHandler =
//8个线程的事件处理组
this.serverBootstrap.group(this.eventLoopGroupBoss, this.eventLoopGroupSelector)
.channel(useEpoll() ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 1024)//连接队列大小
.option(ChannelOption.SO_REUSEADDR, true)//为了快速启动
.option(ChannelOption.SO_KEEPALIVE, false)
.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()
.addLast(defaultEventExecutorGroup, HANDSHAKE_HANDLER_NAME, handshakeHandler)
.addLast(defaultEventExecutorGroup,
encoder,
new NettyDecoder(),
new IdleStateHandler(0, 0, nettyServerConfig.getServerChannelMaxIdleTimeSeconds()),
connectionManageHandler,//连接管理
serverHandler//真正干活的是这个线程池,有连接来的时候boss处理,channel有事件发生的时候 selecter将事件读出来,然后交给EventExecutor来处理
);
}
});
3、NettyServerHandler:业务消息执行处理器
1、processMessageReceived:通过RemotingCommand type确定是处理request请求或者response请求
2、requst请求, 从processorTable中根据code码取出对应的处理器,线程池 processorTable 在registerProcessor注册的事件管理映射对象processTable对应事件的事件处
3、如果处理器不为空,创建一个Runnable 消息处理线程
1、事前钩子处理
2、创建消息响应回调函数,非oneway消息通过channel writeAndFlush(response) 响应消息处理
3、判断获取的处理器异步与同步。如果是同步处理器阻塞等待结果,如果是异步处理器,设置回调响应
4、SendMessageProcessor:消息发送请求处理器
1、asyncProcessRequest 方法都是返回 CompletableFuture<RemotingCommand> 同步通过调用CompletableFuture.get方法同步等待
2、先从request中解析出SendMessageRequestHeader
3、通过buildMsgContext构建 SendMessageContext 发送消息上下文
4、执行前置钩子处理
5、asyncSendMessage 执行接收消息处理
1、获取remotingCommand response, 用于返回处理结果,读取SendMessageResponseHeader responseHeader,获取body消息内容
2、创建MessageExtBrokerInner(要存入commitLog的数据封装),设置相关信息requestId , message body, request queue和topic等
3、调用MessageStore存储MessageExtBrokerInner
4、根据MessageStore返回的结果, 给出响应
4、将线程管道,cmd命令包装为RequestTask
5、通过之前获取到的线程池submit RequestTask
6、如果RejectedExecutionException异常,非oneway消息时包装response,通过netty writeAndFlush
4、负责处理ChannelEventListener 启动
5、NettyRemotingServer.this.scanResponseTable(); 任务来扫描responseTable,这个就是异步调用的时候,然后会扫描这个responseTable找出过期的