教你正確地利用Netty建立連線池
一、問題描述
Netty是最近非常流行的高效能非同步通訊框架,相對於Java原生的NIO介面,Netty封裝後的非同步通訊機制要簡單很多。
但是小K最近發現並不是所有開發人員在使用的過程中都瞭解其內部實現機制,而是照著葫蘆畫瓢。
網上簡單搜尋下,在客戶端使用Netty建立連線池的文章也是比較少。今天小K給大家簡單介紹下使用Netty建立連線池的方法。
首先我們來看下Netty官方給出的客戶端sample例項:
//建立一個EventLoopGroup,可以簡單認為是Netty框架下的執行緒池,預設最大執行緒數量是處理器數量的2倍 EventLoopGroup group = new NioEventLoopGroup(); try { //Netty建立連線的輔助類 Bootstrap b = new Bootstrap(); //配置屬性,向pipeline新增handler b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); } //p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast(new EchoClientHandler()); } }); //啟動建立連線 ChannelFuture f = b.connect(HOST, PORT).sync(); //block直到連線被關閉 f.channel().closeFuture().sync();
很簡單?沒錯,確實如此。那麼現在問題來了,如果你現在需要連線100個伺服器,你會怎麼做呢?
下面這樣處理怎麼樣呢?我們在外層加了一個for迴圈
for(Host host : hosts){ //建立一個EventLoopGroup,可以簡單認為是Netty框架下的執行緒池,預設執行緒數量是處理器數量的2倍 EventLoopGroup group = new NioEventLoopGroup(); try { //Netty建立連線的輔助類 Bootstrap b = new Bootstrap(); //配置屬性,向pipeline新增handler b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); } //p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast(new EchoClientHandler()); } }); //啟動建立連線 ChannelFuture f = b.connect(HOST, PORT).sync(); //block直到連線被關閉 f.channel().closeFuture().sync(); }
問題很明顯,如果每一個channel都對應一個NIOEventLoopGroup,那麼我們實際上構建了一個connection:thread = 1:1的模型,隨著連線數不斷地擴大,執行緒膨脹的問題就會突顯出來。
二、問題解決
那麼如何避免執行緒膨脹的問題呢?很簡單,我們只要稍微修改下上面的程式碼就可以了。
NioEventLoopGroup group = new NioEventLoopGroup(); Bootstrap b = new Bootstrap(); try { b.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); if (sslCtx != null) { p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); } //p.addLast(new LoggingHandler(LogLevel.INFO)); p.addLast(new EchoClientHandler()); } }); for(Host HOST : Hosts){ ChannelFuture f = b.connect(HOST, PORT).sync(); }
在上面的程式碼中,我們使用同一個Bootstrap建立了多個連線,從而使連線共享了一個NioEventLoopGroup,避免了執行緒膨脹的問題。
問題就這樣解決了嗎?NO,還遠遠沒有結束哦,那麼問題又來了。
1、如果希望每個連線能夠使用不同的Handler怎麼辦?
2、每個連線如何能夠再次複用,避免重複建立channel?
為了能夠建立非同步操作的連線池我們需要實現如下的模型。
為了能夠方便地建立一個非同步操作的連線池,我們會使用到FixedChannelPool(不瞭解的同學麻煩Google一下吧,(⌒_⌒))
其虛擬碼如下(具體的程式碼實現結構還是留給讀者自己思考吧):
Bootstrap b = new Bootstrap().channel(NioSocketChannel.class).group( new NioEventLoopGroup()); //自定義的channelpoolhandler ChannelPoolHandler handler = new ChannelPoolHandler(); //建立一個FixedChannelPool FixedChannelPool pool = new FixedChannelPool(bootstrap, handler); //從channelpool中獲取連線或者建立新的連線,並新增listener pool.acquire.addlistener();
三、總結
通常情況下,我們並不需要使用Netty建立連線池,common pool可以滿足我們的需求,但是有些業務場景(例如:返回結果時間不確定)需要使用這種非同步的連線池,在正確的業務場景下選擇正確的解決方案才是王道哦。
相關文章
- python資料庫連線池的正確用法Python資料庫
- ElasticSearch連線池建立Elasticsearch
- netty實戰-netty client連線池設計Nettyclient
- 【JDBC】使用OracleDataSource建立連線池用於連線OracleJDBCOracle
- Jdbc 封裝, 利用反射, 加入連線池JDBC封裝反射
- 利用weblogic的POOL(連線池)連線資料庫 (轉)Web資料庫
- 教你正確認識WIFI無線聯網技術WiFi
- Weblogic Server連線池建立會話慢WebServer會話
- 在Weblogic9.2.3中建立連線池Web
- 連線池
- Go連線池Go
- HTTP連線池HTTP
- django連線池Django
- Swift 里正確地 addTarget(_:action:for:)Swift
- 如何正確管理HBase的連線,從原理到實戰
- MongoDB Driver:使用正確的姿勢連線分片叢集MongoDB
- 如何正確的建立網站網站
- Http持久連線與HttpClient連線池HTTPclient
- 連線池和連線數詳解
- Go實戰準備工作---建立資料庫連線池Go資料庫
- 自定義連線池
- golang tcp連線池GolangTCP
- Oracle 連線池配置Oracle
- oracle occi 連線池Oracle
- Resin 配置連線池
- [尋]連線池例子
- proxool連線池 配置
- 連線池 druidUI
- 利用Oracle自帶的連線池類的一例 (轉)Oracle
- 如何正確設定資料庫連線池的大小?我的天,原來之前都設定錯了!資料庫
- Java 如何正確地輸出日誌Java
- 讀《原則》(一):“正確地失敗”
- 如何正確地寫出單例模式單例模式
- Android-如何正確地使用HandlerAndroid
- java連線池解決連線中斷Java
- proxool連線池如何使用SSL方式連線?
- 路由器和貓怎麼連線?路由器和貓的正確連線方法教程路由器
- 分散式 | 資料庫連線如何正確處理 TCP 連線三次握手失敗分散式資料庫TCP