最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入淺析Netty 在 Dubbo 中是如何應(yīng)用的

 更新時間:2020年05月07日 11:19:05   作者:Java技術(shù)棧  
國內(nèi)知名框架 Dubbo 底層使用的是 Netty 作為網(wǎng)絡(luò)通信,那么內(nèi)部到底是如何使用的呢?今天通過本文給大家詳細(xì)講解,對Netty 在 Dubbo中應(yīng)用相關(guān)知識感興趣的朋友跟隨小編一起看看吧

眾所周知,國內(nèi)知名框架 Dubbo 底層使用的是 Netty 作為網(wǎng)絡(luò)通信,那么內(nèi)部到底是如何使用的呢?今天我們就來一探究竟。

1. dubbo 的 Consumer 消費者如何使用 Netty

注意:此次代碼使用了從 github 上 clone 的 dubbo 源碼中的 dubbo-demo 例子。

代碼如下:

System.setProperty("java.net.preferIPv4Stack", "true");
 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-consumer.xml"});
 context.start();
 // @1
 DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
 int a = 0;
 while (true) {
  try {
   Thread.sleep(1000);
   System.err.println( ++ a + " ");

   String hello = demoService.sayHello("world"); // call remote method
   System.out.println(hello); // get result

  } catch (Throwable throwable) {
   throwable.printStackTrace();
  }
 }

當(dāng)代碼執(zhí)行到 @1 的時候,會調(diào)用 Spring 容器的 getBean 方法,而 dubbo 擴展了 FactoryBean,所以,會調(diào)用 getObject 方法,該方法會創(chuàng)建代理對象。

這個過程中會調(diào)用 DubboProtocol 實例的 getClients(URL url) 方法,當(dāng)這個給定的 URL 的 client 沒有初始化則創(chuàng)建,然后放入緩存,代碼如下:

這個 initClient 方法就是創(chuàng)建 Netty 的 client 的。

最終調(diào)用的就是抽象父類 AbstractClient 的構(gòu)造方法,構(gòu)造方法中包含了創(chuàng)建 Socket 客戶端,連接客戶端等行為。

public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
 doOpen();
 connect();
}

doOpent 方法用來創(chuàng)建 Netty 的 bootstrap :

protected void doOpen() throws Throwable {
 NettyHelper.setNettyLoggerFactory();
 bootstrap = new ClientBootstrap(channelFactory);
 bootstrap.setOption("keepAlive", true);
 bootstrap.setOption("tcpNoDelay", true);
 bootstrap.setOption("connectTimeoutMillis", getTimeout());
 final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
 bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
  public ChannelPipeline getPipeline() {
   NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyClient.this);
   ChannelPipeline pipeline = Channels.pipeline();
   pipeline.addLast("decoder", adapter.getDecoder());
   pipeline.addLast("encoder", adapter.getEncoder());
   pipeline.addLast("handler", nettyHandler);
   return pipeline;
  }
 });
}

connect 方法用來連接提供者:

protected void doConnect() throws Throwable {
 long start = System.currentTimeMillis();
 ChannelFuture future = bootstrap.connect(getConnectAddress());
 boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
 if (ret && future.isSuccess()) {
  Channel newChannel = future.getChannel();
  newChannel.setInterestOps(Channel.OP_READ_WRITE);
 }
}

上面的代碼中,調(diào)用了 bootstrap 的 connect 方法,熟悉的 Netty 連接操作。當(dāng)然這里使用的是  jboss 的 netty3,稍微有點區(qū)別。點擊這篇:教你用 Netty 實現(xiàn)一個簡單的 RPC。當(dāng)連接成功后,注冊寫事件,準(zhǔn)備開始向提供者傳遞數(shù)據(jù)。

當(dāng) main 方法中調(diào)用 demoService.sayHello(“world”) 的時候,最終會調(diào)用 HeaderExchangeChannel 的 request 方法,通過 channel 進(jìn)行請求。

public ResponseFuture request(Object request, int timeout) throws RemotingException {
 Request req = new Request();
 req.setVersion("2.0.0");
 req.setTwoWay(true);
 req.setData(request);
 DefaultFuture future = new DefaultFuture(channel, req, timeout);
 channel.send(req);
 return future;
}

send 方法中最后調(diào)用 jboss  Netty 中繼承了  NioSocketChannel 的 NioClientSocketChannel 的 write 方法。完成了一次數(shù)據(jù)的傳輸。

2. dubbo 的 Provider 提供者如何使用 Netty

Provider demo 代碼:

System.setProperty("java.net.preferIPv4Stack", "true");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"});
context.start();
System.in.read(); // press any key to exit

Provider 作為被訪問方,肯定是一個 Server 模式的 Socket。如何啟動的呢?

當(dāng) Spring 容器啟動的時候,會調(diào)用一些擴展類的初始化方法,比如繼承了 InitializingBean,ApplicationContextAware,ApplicationListener 。

而 dubbo 創(chuàng)建了 ServiceBean 繼承了一個監(jiān)聽器。Spring 會調(diào)用他的 onApplicationEvent 方法,該類有一個 export 方法,用于打開 ServerSocket 。

然后執(zhí)行了 DubboProtocol 的 createServer 方法,然后創(chuàng)建了一個NettyServer 對象。NettyServer 對象的 構(gòu)造方法同樣是  doOpen 方法和。

代碼如下:

protected void doOpen() throws Throwable {
 NettyHelper.setNettyLoggerFactory();
 ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
 ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
 ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, getUrl().getPositiveParameter(Constants.IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS));
 bootstrap = new ServerBootstrap(channelFactory);

 final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
 channels = nettyHandler.getChannels();
 bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
  public ChannelPipeline getPipeline() {
   NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
   ChannelPipeline pipeline = Channels.pipeline();
   pipeline.addLast("decoder", adapter.getDecoder());
   pipeline.addLast("encoder", adapter.getEncoder());
   pipeline.addLast("handler", nettyHandler);
   return pipeline;
  }
 });
 channel = bootstrap.bind(getBindAddress());
}

該方法中,看到了熟悉的 boss 線程,worker 線程,和 ServerBootstrap,在添加了編解碼 handler  之后,添加一個 NettyHandler,最后調(diào)用 bind 方法,完成綁定端口的工作。和我們使用 Netty 是一摸一樣。

3. 總結(jié)

可以看到,dubbo 使用 Netty 還是挺簡單的,消費者使用 NettyClient,提供者使用 NettyServer,Provider  啟動的時候,會開啟端口監(jiān)聽,使用我們平時啟動 Netty 一樣的方式。

而 Client 在 Spring getBean 的時候,會創(chuàng)建 Client,當(dāng)調(diào)用遠(yuǎn)程方法的時候,將數(shù)據(jù)通過 dubbo 協(xié)議編碼發(fā)送到 NettyServer,然后 NettServer 收到數(shù)據(jù)后解碼,并調(diào)用本地方法,并返回數(shù)據(jù),完成一次完美的 RPC 調(diào)用。

到此這篇關(guān)于深入淺析Netty 在 Dubbo 中是如何應(yīng)用的的文章就介紹到這了,更多相關(guān)Netty 在 Dubbo中應(yīng)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot啟動java.nio.charset.MalformedInputException: Input length = 1報錯的解決方案

    SpringBoot啟動java.nio.charset.MalformedInputException: I

    本文主要介紹了SpringBoot啟動java.nio.charset.MalformedInputException: Input length = 1報錯的解決方案
    2023-07-07
  • java中pdf轉(zhuǎn)圖片的實現(xiàn)方法

    java中pdf轉(zhuǎn)圖片的實現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava中pdf轉(zhuǎn)圖片的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • java 中sleep() 和 wait() 的對比

    java 中sleep() 和 wait() 的對比

    這篇文章主要介紹了java 中sleep() 和 wait() 的對比的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • SpringBoot+slf4j線程池全鏈路調(diào)用日志跟蹤問題及解決思路(二)

    SpringBoot+slf4j線程池全鏈路調(diào)用日志跟蹤問題及解決思路(二)

    本文主要給大家介紹如何實現(xiàn)子線程中的traceId日志跟蹤,本文通過封裝Callable為例給大家介紹的非常詳細(xì),需要的朋友一起看看吧
    2021-05-05
  • Java中List對象集合按對象中某字段進(jìn)行排序舉例

    Java中List對象集合按對象中某字段進(jìn)行排序舉例

    這篇文章主要給大家介紹了關(guān)于Java中List對象集合按對象中某字段進(jìn)行排序的相關(guān)資料,我們在日常開發(fā)中也經(jīng)常會用到排序算法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Java并發(fā)控制機制詳解

    Java并發(fā)控制機制詳解

    這篇文章主要為大家詳細(xì)介紹了Java并發(fā)控制機制,什么是Java并發(fā)控制機制,Java并發(fā)控制機制的作用,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Spring?Boot?底層原理基礎(chǔ)深度解析

    Spring?Boot?底層原理基礎(chǔ)深度解析

    這篇文章主要介紹了Spring?Boot?底層原理基礎(chǔ),包括底層注解@Configuration,底層注解@Import及底層注解@Conditional的相關(guān)知識,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • java實現(xiàn)Excel轉(zhuǎn)換為圖片

    java實現(xiàn)Excel轉(zhuǎn)換為圖片

    在實際開發(fā)過程中,經(jīng)常會有這樣的需求,需要將Excel表格或特定區(qū)域轉(zhuǎn)換為圖片,所以小編今天就來為大家介紹一下如何使用Java將Excel轉(zhuǎn)化為圖片吧
    2023-10-10
  • springboot:接收date類型的參數(shù)方式

    springboot:接收date類型的參數(shù)方式

    這篇文章主要介紹了springboot:接收date類型的參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • SpringBoot如何自動生成API文檔詳解

    SpringBoot如何自動生成API文檔詳解

    網(wǎng)絡(luò)程序正朝著移動設(shè)備的方向發(fā)展,前后端分離、APP,最好的交互交互方式莫過于通過API接口實現(xiàn),這篇文章主要給大家介紹了關(guān)于SpringBoot如何自動生成API文檔的相關(guān)資料,需要的朋友可以參考下
    2021-07-07

最新評論

洪雅县| 富源县| 四子王旗| 鲁山县| 紫金县| 辽源市| 石狮市| 偃师市| 宁蒗| 礼泉县| 浦东新区| 龙江县| 扬中市| 东阳市| 舒兰市| 绿春县| 南皮县| 凤冈县| 寿光市| 德格县| 齐齐哈尔市| 菏泽市| 卓资县| 祁阳县| 开封市| 余姚市| 罗甸县| 临泽县| 荔浦县| 满城县| 云阳县| 济源市| 商南县| 浪卡子县| 内乡县| 唐河县| 永州市| 大渡口区| 广平县| 清河县| 和政县|