日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Netty3之ServerBootstrap分析

發(fā)布時(shí)間:2024/9/21 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Netty3之ServerBootstrap分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??

概述

ServerBootstrap是Netty提供的一個(gè)服務(wù)端工具類(lèi),通過(guò)設(shè)置ChanneFactory,ChannelPipelineFactory,用戶(hù)可以很方便的啟動(dòng)一個(gè)服務(wù)端。

ServerBootstrap是做什么的

ServerBootstrap是一個(gè)幫助類(lèi),用來(lái)創(chuàng)建服務(wù)端的Channel以監(jiān)聽(tīng)來(lái)自客戶(hù)端的連接。

面向連接

ServerBootstrap只支持面向連接的傳輸,比如TCP/IP,如果是沒(méi)有連接的傳輸,比如UDP/IP這樣,就需要使用ConnectionlessBootstrap。

Parent and Child Channel

ServerBootstrap通過(guò)bind()方法使用屬性ChannelFactory來(lái)創(chuàng)建服務(wù)端的Channel,以監(jiān)聽(tīng)并且accept客戶(hù)端的連接。服務(wù)端的Channel被稱(chēng)為parent Channel,來(lái)自客戶(hù)端的連接被稱(chēng)為child Channel。

配置Channel

使用Options來(lái)設(shè)置parent and child Channel的可選參數(shù),其中child Channel需要使用child.前綴。

ServerBootstrap b = ...;// Options for a parent channel b.setOption("localAddress", new InetSocketAddress(8080)); b.setOption("reuseAddress", true);// Options for its children b.setOption("child.tcpNoDelay", true); b.setOption("child.receiveBufferSize", 1048576);

設(shè)置Channel Pipeline

Netty使用ChannelPipeline來(lái)處理和流轉(zhuǎn)IO事件。parent Channel的Pipeline是由ServerBootstrap內(nèi)部創(chuàng)建的,并且加入Binder的內(nèi)部類(lèi)作為ChannelHandler。我們可以設(shè)置ServerBootstrap的屬性parentHandler,一旦設(shè)置之后parentHandler就會(huì)被追加到parent Pipeline中用來(lái)我們自定義的ChannelHandler。

child Pipeline有兩種方式可以設(shè)置,一種方式是通過(guò)setPipelineFactory(ChannelPipelineFactory)設(shè)置,每個(gè)child Channel都會(huì)通過(guò)ChannelPipelineFactory創(chuàng)建新的ChannelPipeline,是推薦的方式。另一種方式通過(guò)setPipeline(ChannelPipeline)設(shè)置,這個(gè)方法內(nèi)部會(huì)創(chuàng)建ChannelPipelineFactory,復(fù)用設(shè)置的ChannelPipeline的內(nèi)部ChannelHandler。

不同配置,不同Channel

ServerBootstrap本身并不是占用資源,而是交給ChannelFactory來(lái)處理,官網(wǎng)文檔說(shuō)可以使用同一個(gè)ChannelFactory來(lái)創(chuàng)建多個(gè)ServerBootstrap,每個(gè)ServerBootstrap都可以使用不同的配置,從而創(chuàng)建不同的Channel(沒(méi)見(jiàn)過(guò)這種需要。)

ServerBootstrap創(chuàng)建和啟動(dòng)過(guò)程

Netty為我們提供ServerBootstrap作為工具來(lái)方便的啟動(dòng)服務(wù)端,使用起來(lái)也很簡(jiǎn)單,一般分為這幾步:

  • 創(chuàng)建ChannelFactory
  • 創(chuàng)建ChannelPipelineFactory
  • 創(chuàng)建ServerBootstrap實(shí)例、設(shè)置ChannelFactory和ChannelPipelineFactory
  • 調(diào)用bind方法

1、創(chuàng)建ChannelFactory

這個(gè)ChannelFactory在啟動(dòng)時(shí)候會(huì)創(chuàng)建parent Channel也就是服務(wù)的Channel以監(jiān)聽(tīng)來(lái)自客戶(hù)端的連接。

ChannelFactory是用來(lái)創(chuàng)建parent Channel

2、創(chuàng)建ChannelPipelineFactory

在accept Channel之后會(huì)使用這個(gè)ChannelPipelineFactory創(chuàng)建ChannelPipeline用來(lái)處理IO事件。常見(jiàn)的使用方法是使用Channels.pipeline()創(chuàng)建一個(gè)DefaultChannelPipeline,我們往里添加自定義的ChannelHandler即可。

ChannelPipelineFactory是用來(lái)服務(wù)child Channel

3、設(shè)置ChannelFactory和ChannelPipelineFactory

創(chuàng)建ServerBootstrap實(shí)例,設(shè)置ChannelFactory和ChannelPipelineFactory屬性。

4、調(diào)用bind()方法啟動(dòng),綁定在指定端口。

官網(wǎng)示例(也是常用使用方式,Dubbo就是這樣的,設(shè)計(jì)的簡(jiǎn)約而不簡(jiǎn)單)

// Configure the server. ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),Executors.newCachedThreadPool()));// Set up the pipeline factory. bootstrap.setPipelineFactory(new ChannelPipelineFactory() {public ChannelPipeline getPipeline() throws Exception {return Channels.pipeline(new EchoServerHandler());} });// Bind and start to accept incoming connections. bootstrap.bind(new InetSocketAddress(port));

bind()綁定過(guò)程

ServerBootstrap通過(guò)調(diào)用bind()方法來(lái)啟動(dòng)服務(wù)端。綁定方法很簡(jiǎn)單,首先創(chuàng)建parent的ChannelPipeline,然后使用ChannelFactory創(chuàng)建Channel,結(jié)束。

public Channel bind(final SocketAddress localAddress) {ChannelFuture future = bindAsync(localAddress);// Wait for the future.future.awaitUninterruptibly();if (!future.isSuccess()) {future.getChannel().close().awaitUninterruptibly();throw new ChannelException("Failed to bind to: " + localAddress, future.getCause());}return future.getChannel(); }public ChannelFuture bindAsync(final SocketAddress localAddress) {if (localAddress == null) {throw new NullPointerException("localAddress");}// 設(shè)置bossPipelineBinder binder = new Binder(localAddress);ChannelHandler parentHandler = getParentHandler();ChannelPipeline bossPipeline = pipeline();bossPipeline.addLast("binder", binder);if (parentHandler != null) {bossPipeline.addLast("userHandler", parentHandler);}// 創(chuàng)建parent ChannelChannel channel = getFactory().newChannel(bossPipeline);final ChannelFuture bfuture = new DefaultChannelFuture(channel, false);binder.bindFuture.addListener(new ChannelFutureListener() {public void operationComplete(ChannelFuture future) throws Exception {if (future.isSuccess()) {bfuture.setSuccess();} else {// Call close on bind failurebfuture.getChannel().close();bfuture.setFailure(future.getCause());}}});return bfuture; }

分析方法過(guò)程:

  • 創(chuàng)建parent ChannelPipeline,添加Binder、外部設(shè)置的parentChannelHandler,這個(gè)Pipeline是給parent Channel服務(wù)的
  • 使用ChannelFactory創(chuàng)建Channel,是parent Channel
  • Binder類(lèi)是ServerBootstrap內(nèi)部類(lèi),是一個(gè)UpstreamHandler,處理三個(gè)事件:channelOpen、childChannelOpen、exceptionCaught。

    NioServerSocketChannelFactory創(chuàng)建NioServerSocketChannel,在NioServerSocketChannel的構(gòu)造函數(shù)中會(huì)觸發(fā)一個(gè)ChannelOpen的事件傳入Pipeline中,這個(gè)Pipeline就是在ServerBootstrap的bind()方法里創(chuàng)建的parent Pipeline。而ChannelOpen是一個(gè)UpstreamEvent,因此Binder類(lèi)就會(huì)執(zhí)行相應(yīng)的邏輯。

    關(guān)鍵代碼

    // NioServerSocketChannel的構(gòu)造函數(shù)中執(zhí)行 socket = ServerSocketChannel.open(); socket.configureBlocking(false); fireChannelOpen(this); // Binder類(lèi)的channelOpen方法,最后執(zhí)行channel的bind方法 evt.getChannel().bind(localAddress).addListener(new ChannelFutureListener() {public void operationComplete(ChannelFuture future) throws Exception {if (future.isSuccess()) {bindFuture.setSuccess();} else {bindFuture.setFailure(future.getCause());}} });// NioServerSocketChannel的bind方法 channel.getPipeline().sendDownstream(new DownstreamChannelStateEvent(channel, future, ChannelState.BOUND, localAddress));// NioServerSocketPipelineSink,調(diào)用NioServerBoss的bind方法 case BOUND:if (value != null) {((NioServerBoss) channel.boss).bind(channel, future, (SocketAddress) value);} else {((NioServerBoss) channel.boss).close(channel, future);}break;// NioServerBoss中創(chuàng)建RegisterTask void bind(final NioServerSocketChannel channel, final ChannelFuture future,final SocketAddress localAddress) {registerTask(new RegisterTask(channel, future, localAddress)); }// RegisterTask中執(zhí)行nio的bind和注冊(cè)到Selector,屬性的nio知識(shí)點(diǎn) channel.socket.socket().bind(localAddress, channel.getConfig().getBacklog()); bound = true;future.setSuccess(); fireChannelBound(channel, channel.getLocalAddress()); channel.socket.register(selector, SelectionKey.OP_ACCEPT, channel);

    流程分析:

  • NioServerSocketChannel構(gòu)造方法創(chuàng)建Java nio的ServerSocketChannel;
  • NioServerSocketChannel構(gòu)造方法中觸發(fā)OPEN的UpstreamEvent;
  • Binder類(lèi)中channelOpen()方法中調(diào)用Channel的bind()方法;
  • NioServerSocketChannel的bind()方法觸發(fā)一個(gè)BOUND的DownstreamEvent;
  • NioServerSocketPipelineSink,調(diào)用NioServerBoss的bind()方法;
  • NioServerBoss中創(chuàng)建RegisterTask,RegisterTask是一個(gè)Runnable對(duì)象,run()方法中執(zhí)行NIO的相關(guān)操作,真正處理IO的地方
  • ServerSocketChannel的bind方法,ServerSocketChannel注冊(cè)到Selector,事件是OP_ACCEPT
  • 總體的看來(lái),ServerBootstrap內(nèi)部將任務(wù)交給了Binder和ChannelFactory,進(jìn)一步說(shuō)其實(shí)是Channel來(lái)處理。通過(guò)一系列的事件觸發(fā),最終調(diào)用JDK NIO的ServerSocketChannel完成啟動(dòng)并注冊(cè)監(jiān)聽(tīng)。

    ServerBootstrap沒(méi)做什么,都是ServerChannelFactory在處理,想要理清楚Netty的服務(wù)端,就得剖析NioServerSocketChannelFactory。

    思考一下

    為什么不直接在ServerBootstrap的bind方法里直接執(zhí)行Channel的bind方法呢?我覺(jué)得是想把復(fù)雜的邏輯剝離出來(lái)到Binder這個(gè)內(nèi)部類(lèi)里。may be

    相關(guān)閱讀

    NioServerSocketChannelFactory分析

    轉(zhuǎn)載于:https://my.oschina.net/cregu/blog/2874332

    總結(jié)

    以上是生活随笔為你收集整理的Netty3之ServerBootstrap分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。