1 SOFA RPC源码解析
1.1 Rest服务
1.1.1 服务端响应
在前文介绍SOFA RPC Rest服务发布过程的文章中,我们知道对于rest类型绑定,SOFA采用com.alipay.sofa.rpc.server.rest.SofaNettyJaxrsServer作为服务器。SofaNettyJaxrsServer采用Netty4作为网络通讯层。
看一下SofaNettyJaxrsServer启动方法:
1. public void start() {
2. eventLoopGroup = newNioEventLoopGroup(ioWorkerCount, new NamedThreadFactory("SOFA-REST-IO-"+ port, daemon));
3. eventExecutor = newNioEventLoopGroup(executorThreadCount, newNamedThreadFactory("SOFA-REST-BIZ-" + port, daemon));
4. bootstrap.group(eventLoopGroup)
5. .channel(NioServerSocketChannel.class)
6. .childHandler(createChannelInitializer())
7. .option(ChannelOption.SO_BACKLOG,backlog)
8. .childOption(ChannelOption.SO_KEEPALIVE,keepAlive); // CHANGE:
9.
10. ……略
11.
12. bootstrap.bind(socketAddress).syncUninterruptibly();
13. }
在Server配置过程中,调用createChannelInitializer方法:
1. privateChannelInitializer<SocketChannel> createChannelInitializer() {
2. final RequestDispatcher dispatcher =createRequestDispatcher();
3. if (sslContext == null) {
4. return newChannelInitializer<SocketChannel>() {
5. @Override
6. public voidinitChannel(SocketChannel ch) throws Exception {
7. setupHandlers(ch, dispatcher, HTTP);
8. }
9. };
10. } else {
11. final SSLEngine engine =sslContext.createSSLEngine();
12. engine.setUseClientMode(false);
13. return newChannelInitializer<SocketChannel>() {
14. @Override
15. public voidinitChannel(SocketChannel ch) throws Exception {
16. ch.pipeline().addFirst(newSslHandler(engine));
17. setupHandlers(ch, dispatcher, HTTPS);
18. }
19. };
20. }
21. }
无论是HTTP连接,或HTTPS连接,都会调用setupHandlers方法设置各种Netty4的ChannelInboundHandler和ChannelOutboundHandler处理器:
1. private void setupHandlers(SocketChannelch, RequestDispatcher dispatcher,
2. RestEasyHttpRequestDecoder.Protocolprotocol) {
3. ChannelPipeline channelPipeline =ch.pipeline();
4. channelPipeline.addLast(channelHandlers.toArray(newChannelHandler[channelHandlers.size()]));
5. channelPipeline.addLast(newHttpRequestDecoder());
6. channelPipeline.addLast(newHttpObjectAggregator(maxRequestSize));
7. channelPipeline.addLast(newHttpResponseEncoder());
8. channelPipeline.addLast(httpChannelHandlers.toArray(newChannelHandler[httpChannelHandlers.size()]));
9. channelPipeline.addLast(newRestEasyHttpRequestDecoder(dispatcher.getDispatcher(), root, protocol));
10. channelPipeline.addLast(newRestEasyHttpResponseEncoder());
11. channelPipeline.addLast(eventExecutor,new SofaRestRequestHandler(dispatcher)); // CHANGE: 用sofa的处理类
12. }
由于SofaNettyJaxrsServer参考JBoss Resteasy的NettyJaxrsServer实现,除了根据SOFABoot框架自身需求增加一些自定义功能外,其它还是采用JBossResteasy的处理逻辑。所以,根据Resteasy需求,设置Netty4的上行处理器和下行处理器。
其中,上行处理器主要包括自定义非HTTP类型ChannelInboundHandler、Http请求解码器HttpRequestDecoder、Http对象聚合器HttpObjectAggregator、自定义HTTP类型ChannelInboundHandler、restful风格Http请求解码器RestEasyHttpRequestDecoder、SOFA框架restful风格Http请求处理器SofaRestRequestHandler;
下行处理器包括自定义非HTTP类型ChannelOutboundHandler、Http响应编码器、自定义HTTP类型ChannelOutboundHandler、restful风格Http响应编码器RestEasyHttpResponseEncoder;
我们主要关注SOFA框架restful风格Http请求处理器,对于其他处理器,在这里不详细描述。
从上述代码中,我们可以看出,SOFA框架的业务处理是在一个单独的线程组中执行,而非在Worker线程组(此处Boss和Worker采用同一个线程组),这样可以避免耗时较长的业务处理长时间占用IO线程,导致当大量并发请求到来时,无线程处理的问题。
以下是SofaRestRequestHandler类的主要方法: