赞
踩
在前文介绍SOFA RPC Rest服务发布过程的文章中,我们知道对于rest类型绑定,SOFA采用com.alipay.sofa.rpc.server.rest.SofaNettyJaxrsServer作为服务器。SofaNettyJaxrsServer采用Netty4作为网络通讯层。
看一下SofaNettyJaxrsServer启动方法:
在Server配置过程中,调用createChannelInitializer方法:
无论是HTTP连接,或HTTPS连接,都会调用setupHandlers方法设置各种Netty4的ChannelInboundHandler和ChannelOutboundHandler处理器:
由于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类的主要方法:
当Netty4服务器接收到客户端Http请求,按照顺序依次调用其ChannelPipeline中配置的上行处理器处理Http请求。 此处,上行处理器的执行顺序为:自定义非HTTP类型ChannelInboundHandler、Http请求解码器HttpRequestDecoder、Http对象聚合器HttpObjectAggregator、自定义HTTP类型ChannelInboundHandler、restful风格Http请求解码器RestEasyHttpRequestDecoder、SOFA框架restful风格Http请求处理器SofaRestRequestHandler。
当请求到达最后一个处理SofaRestRequestHandler时,调用其channelRead0方法,处理Http请求:
1. 经过RestEasyHttpRequestDecoder解码器处理以后,Http请求已经被转换为JBoss RestEasy的NettyHttpRequest实例request;
2. 从NettyHttpRequest中获取NettyHttpResponse实例response;
3. 获取远程IP地址、兼容Nignx转发和VIP等、设置本地地址等;
4. 调用org.jboss.resteasy.plugins.server.netty.RequestDispatcher的service方法,分发Http请求;
5. RequestDispatcher的service方法中,调用com.alipay.sofa.rpc.server.rest.SofaSynchronousDispatcher的invoke方法:
调用getInvoker方法:
调用com.alipay.sofa.rpc.server.rest.SofaResourceMethodRegistry类getResourceInvoker方法,解析请求中的路径, 然后匹配到相应的invoker(此处为com.alipay.sofa.rpc.server.rest.SofaResourceMethodInvoker实例)来执行客户端请求。例如:该Http请求路径为:/webapi/rest/person/sayName/Mike,匹配到相应的invoker为SofaResourceMethodInvoker的一个实例;
获取Http请求对应的invoker以后,调用SofaSynchronousDispatcher的invoke(HttpRequestrequest, HttpResponse response, ResourceInvoker invoker)方法,处理请求:
此时,调用SofaResourceMethodInvoker的invoke方法,处理请求:
调用com.alipay.sofa.rpc.server.rest.SofaResourceFactory的createResource方法,获取响应Http请求的目标对象,此处为PersonServiceImpl的一个实例。
调用invoke方法:
调用invokeOnTarget方法:
调用org.jboss.resteasy.core.MethodInjectorImpl的invoke方法:
最后,通过Java反射机制,调用目标类上指定的方法,此处为PersonService的sayName方法。到此为止,请求处理完成,并返回处理结果。
再来看一下SofaRestRequestHandler的channelRead0方法:
当接收的处理结果response以后,调研NettyHttpResponse的finish方法,准备处理结果,并写入Channel。
调用org.jboss.resteasy.plugins.server.netty.ChunkOutputStream的flush方法准备处理结果,并写入Channel。
最后,调用Netty4的DefaultChannelHandlerContext类writeAndFlush方法,把处理结果写入Channel。
在把处理结果通过网络返回给客户端以前,需要经过已经配置的下行处理器进行编码处理。下行处理器的执行顺序与配置顺序相反,所以按照逆序依次执行restful风格Http响应编码器RestEasyHttpResponseEncoder、自定义HTTP类型ChannelOutboundHandler、Http响应编码器、自定义非HTTP类型ChannelOutboundHandler,最终把已经编码好的处理结果的比特流,通过网络返回给客户端。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。