您好,登錄后才能下訂單哦!
本篇內容主要講解“Netty在Dubbo中使用實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“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" class="com.infuq.facade.impl.QueryUserInfoFacadeImpl" />
Spring在啟動的過程中,通過DubboNamespaceHandler解析上面的標簽.
將每個標簽與之對應的BeanDefinition注冊到BeanFactory中.
Spring再根據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實現了ApplicationListener<ContextRefreshedEvent>接口.
在Spring創建完所有的Bean之后,最后會發布一個ContextRefreshedEvent事件.
因此ServiceBean的onApplicationEvent()方法會被執行.
public void onApplicationEvent(ContextRefreshedEvent event) { if (isDelay() && !isExported() && !isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + getInterface()); } // 暴露服務 export(); }}
接下來就進入到了服務暴露的過程.
服務暴露會完成兩件事情. 第一件事情是通過Netty開啟服務,監聽端口.
第二件事情是將服務注冊到注冊中心.
跟進export()方法, 最后會來到DubboProtocol類.
大體看下它是如何開啟服務,監聽端口? 留意下,有個屬性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.NettyServer
protected 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屬性.
這一路會經歷很多Handler,經過層層封裝,最后才封裝成NettyServerHandler.
它會經歷如下Handler
NettyServerHandler
-> NettyServer
-> MultiMessageHandler
-> HeartbeatHandler
-> AllChannelHandler
-> DecodeHandler
-> HeaderExchangeHandler
-> ExchangeHandler
當客戶端連接服務端,或者發送數據到服務端的時候,
首先會由NettyServerHandler處理請求,然后依次將請求傳遞下去,最后到ExchangeHandler.
那么這些Handler是否都由同一個線程執行的嗎? 并不是
如上圖, 在AllChannelHandler中有個executor屬性,它是一個線程池.
NettyServerHandler
-> NettyServer
-> MultiMessageHandler
-> HeartbeatHandler
-> AllChannelHandler
以上這幾個Handler是由同一個線程執行的, 是由Netty的IO線程執行的, 名稱類似NettyServerWorker-5-7
-> DecodeHandler
-> HeaderExchangeHandler
-> ExchangeHandler
以上這幾個Handler是由另一類線程執行的, 是由AllChannelHandler中的線程池執行的, 名稱類似DubboServerHandler-2.0.1.15:20880-thread-57
也就是說, Netty的IO線程在接收到請求后, 先依次執行
NettyServerHandler -> NettyServer ->
MultiMessageHandler -> HeartbeatHandler
-> AllChannelHandler 這五個Handler.
之后會由AllChannelHandler中的線程池執行后面的DecodeHandler
-> HeaderExchangeHandler -> ExchangeHandler 這三個Handler.
<dubbo:protocol name="dubbo" port="20880" threads="200" threadpool="fixed" />
使用threads=200, threadpool=fixed 就是在配置圖中紅色區域的線程池. 線程池也是調優的一個地方.
到此,相信大家對“Netty在Dubbo中使用實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。