接收流程概览
- 先通过dubboCodec将数据缓冲区反序列化request对象
- DubboCountCodec支持多request对象的处理
- 通过NettyServerHandler处理核心逻辑
- NettyServerHandler通过NettyChannel获取映射的NettyServer
- NettyServer通过received链处理请求事件
- 发送Response对象时,直调netty的NioSocketChannel
|NettyServer| MultiMessageHandler |HeatBeatHandler|AllChannelHandler|DecodeHandler|HeaderExchangeHandler|ExchangeHandlerAdapter|
|–|--|–|--|–|--|–|--|
| handler链处理引擎入口 | 多消息递归处理 |心跳消息处理|dubbo业务线程池策略|一般不起作用,将invocation和result的编解码从netty 编解码线程池延迟到dubbo线程池|负责请求响应关系处理|查找接口完成接口调用|
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/fa81ec10ea425bb95543feb27cd17465.png)
编解码源码分析
InternalDecoder.decode - 接收消息入口
- 缓冲区可读则不断解码
- 将缓存区和NettyServer传给dubboCountCodec
- 解码结果输出到out,传递给nettyServerHandler
protected void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> out) throws Exception {
ChannelBuffer message = new NettyBackedChannelBuffer(input);
获取nettyServer对象
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
try {
do {
int saveReaderIndex = message.readerIndex();
dubboCountCodec解码
Object msg = codec.decode(channel, message);
if (msg == Codec2.DecodeResult.NEED_MORE_INPUT) {
message.readerIndex(saveReaderIndex);
break;
} else {
if (saveReaderIndex == message.readerIndex()) {
throw new IOException("Decode without read data.");
}
输出到nettyServerHandler [out有值 则会触发输出到nettyServerHandler,netty知识不做介绍]
if (msg != null) {
out.add(msg);
}
}
} while (message.readable());
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
}
}
}
DubboCountCodec.decode
- 支持多消息处理
- 调用dubbocodec完成消息反序列化
public Object decode(Channel channel, ChannelBuffer buffer) throws IOException {
int save = buffer.readerIndex();
支持多消息解码
MultiMessage result = MultiMessage.create();
解码核心:dubbocodec完成解析 【父类解析request dubbocodec解析invocation】
do {
Object obj = codec.decode(channel, buffer);
if (Codec2.DecodeResult.NEED_MORE_INPUT == obj) {
buffer.readerIndex(save);
break;
} else {
result.addMessage(obj);
logMessageLength(obj, buffer.readerIndex() - save);
save = buffer.readerIndex();
}
} while (true);
if (result.isEmpty()) {
return Codec2.DecodeResult.NEED_MORE_INPUT;
}
一个消息则直接去Request
if (result.size() == 1) {
return result.get(0);
}
多消息也支持
return result;
}
ExchangeCodec.decode完成消息体反序列化
- ExchangeCodec作为父类处理Telnet协议和dubbo协议
- dubboCodec.decodeBody获取序列化方式解析生成request和invocation
- decodeBody部分不做讲解 参见扩展点一 dubbo协议报文
protected Object decode(Channel channel, ChannelBuffer buffer, int readable, byte[] header) throws IOException {
这里代码全部删除 处理Telnet协议
try {
根据dubbo协议报文解析request和invocation
return decodeBody(channel, is, header);
} finally {
if (is.available() > 0) {
try {
if (logger.isWarnEnabled()) {
logger.warn("Skip input stream " + is.available());
}
StreamUtils.skipUnusedStream(is);
} catch (IOException e) {
logger.warn(e.getMessage(), e);
}
}
}
}
handler源码分析
nettyServerHandler.channelRead入口分析
- 通过映射机制获取handler->NettyServer
- 调用NettyServer.received
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
通过映射机制获取NettyServer
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
try {
调用NettyServer.received
handler.received(channel, msg);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
}
}
MultiMessageHandler.received 多消息处理
- MultiMessageHandler.received 由NettyServer.received
调用
-功能拆分消息,触发下一个Handler调用
public void received(Channel channel, Object message) throws RemotingException {
拆分消息调用心跳HeatBeatHandler.received
if (message instanceof MultiMessage) {
MultiMessage list = (MultiMessage) message;
for (Object obj : list) {
handler.received(channel, obj);
}
} else {
handler.received(channel, message);
}
}
HeatBeatHandler.received心跳消息处理
- 心跳消息则终止下掉
- 非心跳消息调用(默认)AllChannelHandler
public void received(Channel channel, Object message) throws RemotingException {
setReadTimestamp(channel);
是心跳消息则终止链路调用
if (isHeartbeatRequest(message)) {
Request req = (Request) message;
如果是心跳是双向消息则进行回写 同时保障读写通道的顺畅
if (req.isTwoWay()) {
回写心跳响应
Response res = new Response(req.getId(), req.getVersion());
res.setEvent(Response.HEARTBEAT_EVENT);
channel.send(res);
...... 删除日志
}
return;
}
如果是心跳响应则直接终止 心跳由消费者发起,提供者接收
if (isHeartbeatResponse(message)) {
...... 删除日志
return;
}
调用AllChannelHandler 负责线程池隔离io线程池
handler.received(channel, message);
}
AllChannelHandler.received线程池策略-固定200线程同步池
- 异步调用剩余的handler链路
- 线程池默认200线程,
- 完成netty线程与dubbo线程业务隔离
public void received(Channel channel, Object message) throws RemotingException {
默认Fixed线程池
ExecutorService executor = getExecutorService();
try {
ChannelEventRunnable负责下一个DecodeHandler调用
executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
} catch (Throwable t) {
if(message instanceof Request && t instanceof RejectedExecutionException){
Request request = (Request)message;
线程池出问题则响应消费者相关错误
if(request.isTwoWay()){
String msg = "Server side(" + url.getIp() + "," + url.getPort() + ") threadpool is exhausted ,detail msg:" + t.getMessage();
Response response = new Response(request.getId(), request.getVersion());
response.setStatus(Response.SERVER_THREADPOOL_EXHAUSTED_ERROR);
response.setErrorMessage(msg);
channel.send(response);
return;
}
}
throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
}
}
线程池内核参数
@Override
public Executor getExecutor(URL url) {
String name = url.getParameter(THREAD_NAME_KEY, DEFAULT_THREAD_NAME);
默认200
int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS);
默认0
int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
默认SynchronousQueue AbortPolicyWithReport
return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
queues == 0 ? new SynchronousQueue<Runnable>() :
(queues < 0 ? new LinkedBlockingQueue<Runnable>()
: new LinkedBlockingQueue<Runnable>(queues)),
new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
}
DecodeHandler.received
- 如果dubbocodec没有解析Request.mData或者Response.mResult
- 则完成解析,一般默认dubboCodec已经完成解析
- 作用: 进一步轻量化netty线程工作量
- 解码内容不做展示,参见扩展点一 dubbo协议报文
public void received(Channel channel, Object message) throws RemotingException {
if (message instanceof Decodeable) {
decode(message);
}
解析invocation对象 默认序列化是Hessian2
if (message instanceof Request) {
decode(((Request) message).getData());
}
解析result对象 默认序列化是Hessian2
if (message instanceof Response) {
decode(((Response) message).getResult());
}
handler.received(channel, message);
}
HeaderExchangeHandler.received一核心:生成Response,发送Response
public void received(Channel channel, Object message) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
final ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
...... 删除资源处理代码
if (message instanceof Request) {
Request request = (Request) message;
...... 删除心跳代码 oneway代码
处理请求
handleRequest(exchangeChannel, request);
} else if (message instanceof Response) {
处理响应,参见消费者接受响应
作用,取消消费者业务线程阻塞,消费者获取rpc请求的Response结果
handleResponse(channel, (Response) message);
}
...... 删除Telnet协议处理和兜底逻辑
}
handleRequest处理请求
- 调用dubboProtocol.requestHandler完成请求处理[调用dubboInvoker]
- Response.id = req.getId,用于request-Response映射
- 输出到消费者Response信息
void handleRequest(final ExchangeChannel channel, Request req) throws RemotingException {
Response res = new Response(req.getId(), req.getVersion());
...... 删除破损请求
Object msg = req.getData();
...... 删除其他代码
调用dubboProtocol.requestHandler完成请求处理
CompletionStage<Object> future = handler.reply(channel, msg);
future.whenComplete((appResult, t) -> {
if (t == null) {
res.setStatus(Response.OK);
res.setResult(appResult);
} else {
res.setStatus(Response.SERVICE_ERROR);
res.setErrorMessage(StringUtils.toString(t));
}
请求处理完毕发送消息
channel.send(res);
});
}
DubboProtocol.requestHandler.reply()完成接口调用
- 完成 dubboInvoker的查找
- 通过wrapper机制调用目标对象
public CompletableFuture<Object> reply(ExchangeChannel channel, Object message) throws RemotingException {
...... 删除其他代码
Invocation inv = (Invocation) message;
通过DubboProtocol协议的exporterMap 获取dubboInvoker
Invoker<?> invoker = getInvoker(channel, inv);
RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
dubboInvoker借助Wrapper完成无反射的业务接口方法调用
Result result = invoker.invoke(inv);
return result.completionFuture().thenApply(Function.identity());
}
通过暴露的Invoker集合查找Invoker
- 查找规则: 接口名 + port + 版本号 + 分组
Invoker<?> getInvoker(Channel channel, Invocation inv) throws RemotingException {
接口名 + port + 版本号 + 分组
String serviceKey = serviceKey(port, path, inv.getAttachments().get(VERSION_KEY), inv.getAttachments().get(GROUP_KEY));
去暴露的Invoker集合查找
DubboExporter<?> exporter = (DubboExporter<?>) exporterMap.get(serviceKey);
return exporter.getInvoker();
}
invoker.invoke完成业务接口调用
- 完成filter链路的处理
- 支持wapper动态代理类模式避免反射提高性能
AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
}
HeaderExchangeChannel.send(res)-发送响应
- HeaderExchangeChannel的channel属性为nettyChannel
public void send(Object message, boolean sent) throws RemotingException {
if (closed) {
throw new RemotingException(this.getLocalAddress(), null, "Failed to send message " + message + ", cause: The channel " + this + " is closed!");
}
if (message instanceof Request
|| message instanceof Response
|| message instanceof String) {
请求 响应 和telnet
channel.send(message, sent);
}
...... 删除其他场景
}
NettyChannel.send
- NettyChannel的channel为NioSocketChannel
- netty的channel直接调用三层handler模型,其中nettyServerHandler无实质工作
- 通过dubboCodec完成编码后输出给消费者
public void send(Object message, boolean sent) throws RemotingException {
nettyServerHandler基本不起作用,调用编码器完成编码 输出到网卡[flush=true]
ChannelFuture future = channel.writeAndFlush(message);
}
总结
- 通过codec完成request的解码和Response的编码
- 通过request,id = response,id 完成请求响应映射
- 通过handler链明确各handler职责
- handler作用于接收消息
- codec作用于收发消息
- 编解码默认的序列化工具为hessian2
- 默认的线程池为200大小的固定池