之前的文章,介绍了NameServer的启动流程,本篇分析下涉及到的几个Netty的处理器。
一. NettyEncoder
NettyEncoder继承自MessageToByteEncoder。
MessageToByteEncoder是Netty提供的基类,用于将返回的对象,转为字节流的处理器
public class NettyEncoder extends MessageToByteEncoder<RemotingCommand> {
public void encode(ChannelHandlerContext ctx, RemotingCommand remotingCommand, ByteBuf out) {
// 将数据头写出
ByteBuffer header = remotingCommand.encodeHeader();
out.writeBytes(header);
// 将数据体写出
byte[] body = remotingCommand.getBody();
if (body != null) {
out.writeBytes(body);
}
}
}
主要看下encodeHeader方法,
public ByteBuffer encodeHeader(final int bodyLength) {
// header长度
int length = 4;
// header data 长度
byte[] headerData;
// 默认将当前对象,采用FastJSON转为字节数组
headerData = this.headerEncode();
length += headerData.length;
// body 的长度
length += bodyLength;
ByteBuffer result = ByteBuffer.allocate(4 + length - bodyLength);
// length
result.putInt(length);
// 这里对应ByteBuffer.allocate中的4,markProtocolType方法返回长度4个字节的数组
// 低24存放headerData的长度,高位存放序列化方式
result.put(markProtocolType(headerData.length, serializeTypeCurrentRPC));
// header data
result.put(headerData);
result.flip();
return result;
}
最终序列化值得数据格式:
二. NettyDecoder
NettyDecoder 用于将字节流反序列化为自定义的对象。
注意默认构造里面的参数
- 第一个0表示数据流长度偏移量,第二个4表示数据流长度,含义是数据流从0开始读取4个字节获取整个完整流要读取的长度。对应上文中设置
result.putInt(length)
的操作。 - 第三个0表示读取数据流,是否继续偏移一定长度读取,这边不偏移读取
- 第四个4表示忽略多少开始长度读取流数据。这里跳过4个字节,实际上吧length数据过滤。
public class NettyDecoder extends LengthFieldBasedFrameDecoder {
private static final int FRAME_MAX_LENGTH =
Integer.parseInt(System.getProperty("com.rocketmq.remoting.frameMaxLength", "16777216"));
public NettyDecoder() {
super(FRAME_MAX_LENGTH, 0, 4, 0, 4);
}
@Override
public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
ByteBuf frame = null;
frame = (ByteBuf) super.decode(ctx, in);
if (null == frame) {
return null;
}
ByteBuffer byteBuffer = frame.nioBuffer();
return RemotingCommand.decode(byteBuffer);
}
}
按照构造中的定义,调用完super.decode(ctx, in)方法之后的,数据格式如下:
public static RemotingCommand decode(final ByteBuffer byteBuffer) throws RemotingCommandException {
// 总的数据长度
int length = byteBuffer.limit();
// 获取到byte[]的数据
int oriHeaderLen = byteBuffer.getInt();
// 获取headerdata长度
int headerLength = getHeaderLength(oriHeaderLen);
byte[] headerData = new byte[headerLength];
byteBuffer.get(headerData);
RemotingCommand cmd = headerDecode(headerData, getProtocolType(oriHeaderLen));
// 总长度-byte[]-header长度
int bodyLength = length - 4 - headerLength;
byte[] bodyData = null;
if (bodyLength > 0) {
bodyData = new byte[bodyLength];
byteBuffer.get(bodyData);
}
cmd.body = bodyData;
return cmd;
}
三. NettyServerHandler
NettyServerHandler 是最后一步,将对应请求分配到实际业务去处理。
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;
}
}
}
- 处理请求数据
public void processRequestCommand(final ChannelHandlerContext ctx, final RemotingCommand cmd) {
// 根据具体的请求code,查询对应的处理策略,不存在使用默认策略(DefaultRequestProcessor)
final Pair<NettyRequestProcessor, ExecutorService> matched = this.processorTable.get(cmd.getCode());
final Pair<NettyRequestProcessor, ExecutorService> pair = null == matched ? this.defaultRequestProcessor : matched;
// 请求序号
final int opaque = cmd.getOpaque();
Runnable run = new Runnable() {
@Override
public void run() {
String remoteAddr = RemotingHelper.parseChannelRemoteAddr(ctx.channel());
// 类似切面的调用前处理
doBeforeRpcHooks(remoteAddr, cmd);
final RemotingResponseCallback callback = new RemotingResponseCallback() {
@Override
public void callback(RemotingCommand response) {
// 类似切面的调用后处理
doAfterRpcHooks(remoteAddr, cmd, response);
// 有返回的,把数据写回去
if (!cmd.isOnewayRPC()) {
if (response != null) {
response.setOpaque(opaque);
response.markResponseType();
ctx.writeAndFlush(response);
}
}
}
}
};
// 如果是异步处理的,在回调中调用结果
if (pair.getObject1() instanceof AsyncNettyRequestProcessor) {
AsyncNettyRequestProcessor processor = (AsyncNettyRequestProcessor)pair.getObject1();
processor.asyncProcessRequest(ctx, cmd, callback);
} else {
// 同步处理,直接等待处理结果
NettyRequestProcessor processor = pair.getObject1();
RemotingCommand response = processor.processRequest(ctx, cmd);
callback.callback(response);
}
}
};
// ....省略不重要的
// 提交任务执行
final RequestTask requestTask = new RequestTask(run, ctx.channel(), cmd);
pair.getObject2().submit(requestTask);
}
- 处理响应数据
public void processResponseCommand(ChannelHandlerContext ctx, RemotingCommand cmd) {
// 请求序号
final int opaque = cmd.getOpaque();
// 获取对应的返回结果
final ResponseFuture responseFuture = responseTable.get(opaque);
responseFuture.setResponseCommand(cmd);
responseTable.remove(opaque);
// 异步的回调获取结果
if (responseFuture.getInvokeCallback() != null) {
executeInvokeCallback(responseFuture);
} else {
// 同步直接设置结果
responseFuture.putResponse(cmd);
responseFuture.release();
}
}