溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Netty在Dubbo中使用實(shí)例分析

發(fā)布時(shí)間:2021-12-15 14:48:48 來源:億速云 閱讀:161 作者:iii 欄目:云計(jì)算

本篇內(nèi)容主要講解“Netty在Dubbo中使用實(shí)例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Netty在Dubbo中使用實(shí)例分析”吧!

當(dāng)配置如下信息時(shí)

<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在啟動(dòng)的過程中,通過DubboNamespaceHandler解析上面的標(biāo)簽.

將每個(gè)標(biāo)簽與之對(duì)應(yīng)的BeanDefinition注冊(cè)到BeanFactory中.

Spring再根據(jù)BeanDefinition生成對(duì)應(yīng)的Bean實(shí)例.

上面的<dubbo:service />標(biāo)簽最終會(huì)生成對(duì)應(yīng)的ServiceBean實(shí)例.

// 源碼位置: com.alibaba.dubbo.config.spring.ServiceBeanpublic class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean,        ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware,        ApplicationEventPublisherAware {          }

ServiceBean實(shí)現(xiàn)了ApplicationListener<ContextRefreshedEvent>接口.

在Spring創(chuàng)建完所有的Bean之后,最后會(huì)發(fā)布一個(gè)ContextRefreshedEvent事件.

因此ServiceBean的onApplicationEvent()方法會(huì)被執(zhí)行.

public void onApplicationEvent(ContextRefreshedEvent event) {    if (isDelay() && !isExported() && !isUnexported()) {        if (logger.isInfoEnabled()) {            logger.info("The service ready on spring started. service: " + getInterface());        }        // 暴露服務(wù)        export();    }}

接下來就進(jìn)入到了服務(wù)暴露的過程.

服務(wù)暴露會(huì)完成兩件事情. 第一件事情是通過Netty開啟服務(wù),監(jiān)聽端口.

第二件事情是將服務(wù)注冊(cè)到注冊(cè)中心.

跟進(jìn)export()方法, 最后會(huì)來到DubboProtocol類.

大體看下它是如何開啟服務(wù),監(jiān)聽端口? 留意下,有個(gè)屬性requestHandler.

public class DubboProtocol extends AbstractProtocol {  private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() { ... };
  private ExchangeServer createServer(URL url) {    // 綁定    server = Exchangers.bind(url, requestHandler);  }
}

跟進(jìn)bind()方法,最后會(huì)來到NettyServer的doOpen()方法. 

留意下,有個(gè)屬性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);// 處理請(qǐng)求和響應(yīng)的Handler                }            });    // bind    ChannelFuture channelFuture = bootstrap.bind(getBindAddress());    channelFuture.syncUninterruptibly();    channel = channelFuture.channel();
}

從DubboProtocol類的requestHandler屬性到NettyServer的nettyServerHandler屬性. 

這一路會(huì)經(jīng)歷很多Handler,經(jīng)過層層封裝,最后才封裝成NettyServerHandler.

它會(huì)經(jīng)歷如下Handler

NettyServerHandler
-> NettyServer
-> MultiMessageHandler
-> HeartbeatHandler
-> AllChannelHandler
-> DecodeHandler
-> HeaderExchangeHandler
-> ExchangeHandler

Netty在Dubbo中使用實(shí)例分析

當(dāng)客戶端連接服務(wù)端,或者發(fā)送數(shù)據(jù)到服務(wù)端的時(shí)候, 

首先會(huì)由NettyServerHandler處理請(qǐng)求,然后依次將請(qǐng)求傳遞下去,最后到ExchangeHandler.

那么這些Handler是否都由同一個(gè)線程執(zhí)行的嗎? 并不是

Netty在Dubbo中使用實(shí)例分析

如上圖, 在AllChannelHandler中有個(gè)executor屬性,它是一個(gè)線程池.

NettyServerHandler
-> NettyServer
-> MultiMessageHandler
-> HeartbeatHandler
-> AllChannelHandler

以上這幾個(gè)Handler是由同一個(gè)線程執(zhí)行的, 是由Netty的IO線程執(zhí)行的, 名稱類似NettyServerWorker-5-7

-> DecodeHandler
-> HeaderExchangeHandler
-> ExchangeHandler

以上這幾個(gè)Handler是由另一類線程執(zhí)行的, 是由AllChannelHandler中的線程池執(zhí)行的, 名稱類似DubboServerHandler-2.0.1.15:20880-thread-57

也就是說, Netty的IO線程在接收到請(qǐng)求后, 先依次執(zhí)行

NettyServerHandler -> NettyServer ->

MultiMessageHandler -> HeartbeatHandler

-> AllChannelHandler 這五個(gè)Handler.

之后會(huì)由AllChannelHandler中的線程池執(zhí)行后面的DecodeHandler
-> HeaderExchangeHandler -> ExchangeHandler 這三個(gè)Handler.

Netty在Dubbo中使用實(shí)例分析

<dubbo:protocol name="dubbo" port="20880" threads="200" threadpool="fixed"  />

使用threads=200, threadpool=fixed 就是在配置圖中紅色區(qū)域的線程池. 線程池也是調(diào)優(yōu)的一個(gè)地方.

到此,相信大家對(duì)“Netty在Dubbo中使用實(shí)例分析”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI