public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
Integer queueNumber = (Integer)arg;
return mqs.get(queueNumber);
}
}, 2);
System.err.println(sr);
### Netty底层框架解析
![在这里插入图片描述](https://img-blog.csdnimg.cn/8d0bc573baeb4e66bab9d6560ec66c3a.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/024407c5d88542c69825cf518921c128.png)
`NettyRemotingServer`实现Netty服务器端功能,接受数据包,在服务器端处理后发送给客户端。
`NettyRemotingClient`实现Netty客户端功能。
#### NettyRemotingServer
##### start() 方法
start方法主要启动Netty服务器,并在绑定端口后阻塞主线程。这里主要看看Netty服务器端装配了哪些ChannelHandler:
ServerBootstrap childHandler =
this.serverBootstrap.group(this.eventLoopGroupBoss, this.eventLoopGroupSelector)
.channel(useEpoll() ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, nettyServerConfig.getServerSocketBacklog())
.option(ChannelOption.SO_REUSEADDR, true)
.option(ChannelOption.SO_KEEPALIVE, false)
.childOption(ChannelOption.TCP_NODELAY, true)
.localAddress(new InetSocketAddress(this.nettyServerConfig.getListenPort()))
.childHandler(new ChannelInitializer() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
// SocketChannel添加ChannelHandler
.addLast(defaultEventExecutorGroup, HANDSHAKE_HANDLER_NAME, handshakeHandler)
.addLast(defaultEventExecutorGroup,
encoder,
new NettyDecoder(),
new IdleStateHandler(0, 0, nettyServerConfig.getServerChannelMaxIdleTimeSeconds()),
connectionManageHandler,
serverHandler
);
}
});
HandshakeHandler:检测传输的包体是否使用TLS协议(传输层安全性协议,Transport Layer Security)传输 ,如果包体使用TSL协议,将会在Pipeline中加入处理TSL协议握手的Handler。
ctx.pipeline()
.addAfter(defaultEventExecutorGroup, HANDSHAKE_HANDLER_NAME, TLS_HANDLER_NAME, sslContext.newHandler(ctx.channel().alloc()))
.addAfter(defaultEventExecutorGroup, TLS_HANDLER_NAME, FILE_REGION_ENCODER_NAME, new FileRegionEncoder());
![在这里插入图片描述](https://img-blog.csdnimg.cn/4ce14ef0b24c4925a71f41967858d137.png)
![image.png](https://img-blog.csdnimg.cn/img_convert/ea866cd7215184336abbff3998033021.png#clientId=u4938fe88-11c1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=163&id=ue65c776d&margin=%5BobjectObject%5D&name=image.png&originHeight=183&originWidth=719&originalType=binary&ratio=1&rotation=0&showTitle=false&size=18931&status=done&style=none&taskId=uc0a1ea51-845b-4cba-bb97-dacc77bc00f&title=&width=639.1111111111111)
`NettyEncoder/NettyDecoder`:RocketMQ自定义的编解码Handler,其中编码器将RemotingCommand(RocketMQ的服务器端和客户端交互的数据结构)序列化,其中序列化的方式有json或者二进制,具体编解码方式这里不讨论了。而解码器NettyDecoder继承LengthFieldBasedFrameDecoder,基于长度编解码方式,将二进制反序列化为RemotingCommand。
`IdleStateHandler`:Netty包中定义的心跳检测包。读写超时时间由NettyServerConfig.serverChannelMaxIdleTimeSeconds变量控制,默认时间120s。
`NettyConnectManageHandler`:Channel连接的管理handler,当发生channel连接的激活、失效、超时和异常时,NettyRemotingServer会生成一个Netty事件,管理连接的组件相应的会处理事件。
NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.CONNECT, remoteAddress, ctx.channel()));
NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.CLOSE, remoteAddress, ctx.channel()));
NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.IDLE, remoteAddress, ctx.channel()));
NettyRemotingServer.this.putNettyEvent(new NettyEvent(NettyEventType.EXCEPTION, remoteAddress, ctx.channel()));
`NettyServerHandler`:处理RemotingCommand消息,并且返回相应的处理结果。具体实现如下:
class NettyServerHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, RemotingCommand msg) throws Exception {
processMessageReceived(ctx, msg);
}
}
而processMessageReceived()方法在NettyRemotingServer的父类NettyRemotingAbstract中实现:
public void processMessageReceived(ChannelHandlerContext ctx, RemotingCommand msg) throws Exception {
final RemotingCommand cmd = msg;
if (cmd != null) {
switch (cmd.getType()) {
case REQUEST_COMMAND:
processRequestCommand(ctx, cmd);
break;
case RESPONSE_COMMAND:
processResponseCommand(ctx, cmd);
break;
default:
break;
}
}
}
在看processRequestCommand和processResponseCommand这两个方法之前,先了解一下RemotingCommand这个对象:
public class RemotingCommand {
private static SerializeType serializeTypeConfigInThisServer = SerializeType.JSON;
static {
// 获取配置的序列化方式
final String protocol = System.getProperty(SERIALIZE_TYPE_PROPERTY, System.getenv(SERIALIZE_TYPE_ENV));
if (!isBlank(protocol)) {
try {
serializeTypeConfigInThisServer = SerializeType.valueOf(protocol);
} catch (IllegalArgumentException e) {
throw new RuntimeException(“parser specified protocol error. protocol=” + protocol, e);
}
}
}
private int code; // 请求类型
private LanguageCode language = LanguageCode.JAVA;
private int version = 0; // RocketMQ版本编号
private int opaque = requestId.getAndIncrement(); // 请求序号
private int flag = 0; // 标记请求是普通请求,还是无回应的请求
private String remark; // 失败提示
private HashMap<String, String> extFields; // 参数字段的数值
private transient CommandCustomHeader customHeader; // 参数的类型
private SerializeType serializeTypeCurrentRPC = serializeTypeConfigInThisServer;
private transient byte[] body; // 解码时缓存的字节流
}
#### NettyRemotingClient
NettyRemotingClient的start()方法与NettyRemotingServer类似,在添加ChannelHandler处理包的handler是NettyClientHandler,其功能与NettyServerHandler一样。
public RemotingCommand invokeSync(String addr, final RemotingCommand request, long timeoutMillis)
throws InterruptedException, RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException {
long beginStartTime = System.currentTimeMillis();
final Channel channel = this.getAndCreateChannel(addr);
if (channel != null && channel.isActive()) {
try {
doBeforeRpcHooks(addr, request);
long costTime = System.currentTimeMillis() - beginStartTime;
if (timeoutMillis < costTime) {
throw new RemotingTimeoutException(“invokeSync call timeout”);
}
RemotingCommand response = this.invokeSyncImpl(channel, request, timeoutMillis - costTime);
doAfterRpcHooks(RemotingHelper.parseChannelRemoteAddr(channel), request, response);
return response;
} catch (Exception e) {
// …
总结
面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。
我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。
面试题及解析总结
大厂面试场景
知识点总结
有哪些,所以刷题是面试前期准备过程中非常重要的一点。
面试题及解析总结
[外链图片转存中…(img-oetymk6O-1714559821384)]
大厂面试场景
[外链图片转存中…(img-Ccv94orR-1714559821384)]
知识点总结
[外链图片转存中…(img-XEcUg4nn-1714559821385)]