共計 4177 個字符,預計需要花費 11 分鐘才能閱讀完成。
本篇內(nèi)容主要講解“Netty 在 Dubbo 中使用實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“Netty 在 Dubbo 中使用實例分析”吧!
當配置如下信息時
dubbo:application name= infuq-dubbo-provider / dubbo:registry protocol= zookeeper address= 127.0.0.1:2181 check= false / dubbo:protocol name= dubbo port= 20880 threads= 200 / dubbo:service ref= queryUserInfoFacade interface= com.infuq.facade.QueryUserInfoFacade version= 1.0.0 / bean id= queryUserInfoFacade >
Spring 在啟動的過程中, 通過 DubboNamespaceHandler 解析上面的標簽.
將每個標簽與之對應的 BeanDefinition 注冊到 BeanFactory 中.
Spring 再根據(jù) BeanDefinition 生成對應的 Bean 實例.
上面的 dubbo:service / 標簽最終會生成對應的 ServiceBean 實例.
// 源碼位置: com.alibaba.dubbo.config.spring.ServiceBeanpublic class ServiceBean T extends ServiceConfig T implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener ContextRefreshedEvent , BeanNameAware, ApplicationEventPublisherAware { }
ServiceBean 實現(xiàn)了 ApplicationListener ContextRefreshedEvent 接口.
在 Spring 創(chuàng)建完所有的 Bean 之后, 最后會發(fā)布一個 ContextRefreshedEvent 事件.
因此 ServiceBean 的 onApplicationEvent() 方法會被執(zhí)行.
public void onApplicationEvent(ContextRefreshedEvent event) { if (isDelay() !isExported() !isUnexported()) { if (logger.isInfoEnabled()) { logger.info( The service ready on spring started. service: + getInterface()); } // 暴露服務 export(); }}
接下來就進入到了服務暴露的過程.
服務暴露會完成兩件事情. 第一件事情是通過 Netty 開啟服務, 監(jiān)聽端口.
第二件事情是將服務注冊到注冊中心.
跟進 export() 方法, 最后會來到 DubboProtocol 類.
大體看下它是如何開啟服務, 監(jiān)聽端口? 留意下, 有個屬性 requestHandler.
public class DubboProtocol extends AbstractProtocol { private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {... };
private ExchangeServer createServer(URL url) { // 綁定 server = Exchangers.bind(url, requestHandler); }
}
跟進 bind() 方法, 最后會來到 NettyServer 的 doOpen() 方法.
留意下, 有個屬性 nettyServerHandler.
// 源碼位置: com.alibaba.dubbo.remoting.transport.netty4.NettyServerprotected void doOpen() throws Throwable { bootstrap = new ServerBootstrap();
bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory( NettyServerBoss , true)); workerGroup = new NioEventLoopGroup(getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS), new DefaultThreadFactory(NettyServerWorker , true));
// 重要的 Handler final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this); channels = nettyServerHandler.getChannels();
bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE) .childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE) .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) .childHandler(new ChannelInitializer NioSocketChannel () { @Override protected void initChannel(NioSocketChannel ch) throws Exception { NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this); ch.pipeline() .addLast( decoder , adapter.getDecoder()) .addLast(encoder , adapter.getEncoder()) .addLast(handler , nettyServerHandler);// 處理請求和響應的 Handler } }); // bind ChannelFuture channelFuture = bootstrap.bind(getBindAddress()); channelFuture.syncUninterruptibly(); channel = channelFuture.channel();
}
從 DubboProtocol 類的 requestHandler 屬性到 NettyServer 的 nettyServerHandler 屬性.
這一路會經(jīng)歷很多 Handler, 經(jīng)過層層封裝, 最后才封裝成 NettyServerHandler.
它會經(jīng)歷如下 Handler
NettyServerHandler
- NettyServer
- MultiMessageHandler
- HeartbeatHandler
- AllChannelHandler
- DecodeHandler
- HeaderExchangeHandler
- ExchangeHandler
當客戶端連接服務端, 或者發(fā)送數(shù)據(jù)到服務端的時候,
首先會由 NettyServerHandler 處理請求, 然后依次將請求傳遞下去, 最后到 ExchangeHandler.
那么這些 Handler 是否都由同一個線程執(zhí)行的嗎? 并不是
如上圖, 在 AllChannelHandler 中有個 executor 屬性, 它是一個線程池.
NettyServerHandler
- NettyServer
- MultiMessageHandler
- HeartbeatHandler
- AllChannelHandler
以上這幾個 Handler 是由同一個線程執(zhí)行的, 是由 Netty 的 IO 線程執(zhí)行的, 名稱類似 NettyServerWorker-5-7
- DecodeHandler
- HeaderExchangeHandler
- ExchangeHandler
以上這幾個 Handler 是由另一類線程執(zhí)行的, 是由 AllChannelHandler 中的線程池執(zhí)行的, 名稱類似 DubboServerHandler-2.0.1.15:20880-thread-57
也就是說, Netty 的 IO 線程在接收到請求后, 先依次執(zhí)行
NettyServerHandler - NettyServer -
MultiMessageHandler - HeartbeatHandler
- AllChannelHandler 這五個 Handler.
之后會由 AllChannelHandler 中的線程池執(zhí)行后面的 DecodeHandler
- HeaderExchangeHandler - ExchangeHandler 這三個 Handler.
dubbo:protocol name= dubbo port= 20880 threads= 200 threadpool= fixed /
使用 threads=200, threadpool=fixed 就是在配置圖中紅色區(qū)域的線程池. 線程池也是調(diào)優(yōu)的一個地方.
到此,相信大家對“Netty 在 Dubbo 中使用實例分析”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!