摘要:是一個(gè)高性能事件驅(qū)動(dòng)的異步的非堵塞的框架,用于建立等底層的連接,基于可以建立高性能的服務(wù)器。在中提供了兩套,一套是針對(duì)標(biāo)準(zhǔn)輸入輸出,另一套就是網(wǎng)絡(luò)編程。和是標(biāo)準(zhǔn)中的核心對(duì)象是對(duì)原中流的模擬,任何來(lái)源和目的數(shù)據(jù)都必須通過(guò)一個(gè)對(duì)象。
Netty是一個(gè)高性能 事件驅(qū)動(dòng)的異步的非堵塞的IO(NIO)框架,用于建立TCP等底層的連接,基于Netty可以建立高性能的Http服務(wù)器。
1、首先來(lái)復(fù)習(xí)下非堵塞IO(NIO)
NIO這個(gè)庫(kù)是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但實(shí)現(xiàn)方式不同,NIO主要用到的是塊,所以NIO的效率要比IO高很多。
在Java API中提供了兩套NIO,一套是針對(duì)標(biāo)準(zhǔn)輸入輸出NIO,另一套就是網(wǎng)絡(luò)編程N(yùn)IO。
*Buffer和Channel是標(biāo)準(zhǔn)NIO中的核心對(duì)象*
Channel是對(duì)原IO中流的模擬,任何來(lái)源和目的數(shù)據(jù)都必須通過(guò)一個(gè)Channel對(duì)象。一個(gè)Buffer實(shí)質(zhì)上是一個(gè)容器對(duì)象,發(fā)給Channel的所有對(duì)象都必須先放到Buffer中;同樣的,從Channel中讀取的任何數(shù)據(jù)都要讀到Buffer中。
網(wǎng)絡(luò)編程N(yùn)IO中還有一個(gè)核心對(duì)象Selector,它可以注冊(cè)到很多個(gè)Channel上,監(jiān)聽(tīng)各個(gè)Channel上發(fā)生的事件,并且能夠根據(jù)事件情況決定Channel讀寫(xiě)。這樣,通過(guò)一個(gè)線程管理多個(gè)Channel,就可以處理大量網(wǎng)絡(luò)連接了。
Selector 就是注冊(cè)對(duì)各種 I/O 事件興趣的地方,而且當(dāng)那些事件發(fā)生時(shí),就是這個(gè)對(duì)象告訴你所發(fā)生的事件。
Selector selector = Selector.open(); //創(chuàng)建一個(gè)selector
為了能讓Channel和Selector配合使用,我們需要把Channel注冊(cè)到Selector上。通過(guò)調(diào)用channel.register()方法來(lái)實(shí)現(xiàn)注冊(cè):
channel.configureBlocking(false); //設(shè)置成異步IO
SelectionKey key =channel.register(selector,SelectionKey.OP_READ); //對(duì)所關(guān)心的事件進(jìn)行注冊(cè)(connet,accept,read,write)
SelectionKey 代表這個(gè)通道在此 Selector 上的這個(gè)注冊(cè)。
2、異步
CallBack:回調(diào)是異步處理經(jīng)常用到的編程模式,回調(diào)函數(shù)通常被綁定到一個(gè)方法上,并且在方法完成之后才執(zhí)行,這種處理方式在javascript當(dāng)中得到了充分的運(yùn)用。回調(diào)給我們帶來(lái)的難題是當(dāng)一個(gè)問(wèn)題處理過(guò)程中涉及很多回調(diào)時(shí),代碼是很難讀的。
Futures:Futures是一種抽象,它代表一個(gè)事情的執(zhí)行過(guò)程中的一些關(guān)鍵點(diǎn),我們通過(guò)Future就可以知道任務(wù)的執(zhí)行情況,比如當(dāng)任務(wù)沒(méi)完成時(shí)我們可以做一些其它事情。它給我們帶來(lái)的難題是我們需要去判斷future的值來(lái)確定任務(wù)的執(zhí)行狀態(tài)。
3、netty到底怎么工作的呢?
直接來(lái)看個(gè)最簡(jiǎn)單的實(shí)例
服務(wù)器端
public class EchoServer { private final static int port = 8007; public void start() throws InterruptedException{ ServerBootstrap bootstrap = new ServerBootstrap(); //引導(dǎo)輔助程序 EventLoopGroup group = new NioEventLoopGroup(); //通過(guò)nio的方式接受連接和處理連接 try { bootstrap.group(group) .channel(NioServerSocketChannel.class) //設(shè)置nio類(lèi)型的channel .localAddress(new InetSocketAddress(port)) //設(shè)置監(jiān)聽(tīng)端口 .childHandler(new ChannelInitializer() { //有連接到達(dá)時(shí)會(huì)創(chuàng)建一個(gè)channel // pipline 管理channel中的handler,在channel隊(duì)列中添加一個(gè)handler來(lái)處理業(yè)務(wù) @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("myHandler", new EchoServerHandler()); //ch.pipeline().addLast("idleStateHandler",new? IdleStateHandler(0, 0, 180)); } }); ChannelFuture future = bootstrap.bind().sync(); //配置完成,綁定server,并通過(guò)sync同步方法阻塞直到綁定成功 System.out.println(EchoServer.class.getName() + " started and listen on " + future.channel().localAddress()); future.channel().closeFuture().sync(); //應(yīng)用程序會(huì)一直等待,直到channel關(guān)閉 } catch (Exception e) { e.getMessage(); }finally { group.shutdownGracefully().sync(); } }
創(chuàng)建一個(gè)ServerBootstrap實(shí)例
創(chuàng)建一個(gè)EventLoopGroup來(lái)處理各種事件,如處理鏈接請(qǐng)求,發(fā)送接收數(shù)據(jù)等。
定義本地InetSocketAddress( port)好讓Server綁定
創(chuàng)建childHandler來(lái)處理每一個(gè)鏈接請(qǐng)求
所有準(zhǔn)備好之后調(diào)用ServerBootstrap.bind()方法綁定Server
handler 處理核心業(yè)務(wù)
@Sharable //注解@Sharable可以讓它在channels間共享?? public class EchoServerHandler extends ChannelInboundHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx,Object msg) throws Exception { ByteBuf buf = ctx.alloc().buffer(); buf.writeBytes("Hello World".getBytes()); ctx.write(buf); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
客戶端 連接
public class EchoClient { private final int port; private final String hostIp; public EchoClient(int port, String hostIp) { this.port = port; this.hostIp = hostIp; } public void start() throws InterruptedException { Bootstrap bootstrap = new Bootstrap(); EventLoopGroup group = new NioEventLoopGroup(); try { bootstrap.group(group).channel(NioSocketChannel.class) .remoteAddress(new InetSocketAddress(hostIp, port)) .handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoClientHandler()); } }); ChannelFuture future = bootstrap.connect().sync(); future.addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { System.out.println("client connected"); } else { System.out.println("server attemp failed"); future.cause().printStackTrace(); } } }); future.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { group.shutdownGracefully().sync(); } }
客戶端handler
@Sharable public class EchoClientHandler extends SimpleChannelInboundHandler{ /**? ?? ? *此方法會(huì)在連接到服務(wù)器后被調(diào)用 ? ?? ? * */ ? ? ? public void channelActive(ChannelHandlerContext ctx) {? ? ? System.out.println("Netty rocks!"); ? ? ? ? ctx.write(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8)); ? ? ? } ? /** * 接收到服務(wù)器數(shù)據(jù)時(shí)調(diào)用 */ @Override protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { System.out.println("Client received: " + ByteBufUtil.hexDump(msg.readBytes(msg.readableBytes()))); ? } /**? ?? ? *捕捉到異常 ? ?? ? * */ ? ? ? public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ? ? ? ? ? cause.printStackTrace(); ? ? ? ? ? ctx.close(); ? ? ? } ? }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/66352.html
摘要:支持很多協(xié)議,并且提供用于數(shù)據(jù)處理的容器。我們已經(jīng)知道由特定事件觸發(fā)。可專(zhuān)用于幾乎所有的動(dòng)作,包括將一個(gè)對(duì)象轉(zhuǎn)為字節(jié)或相反,執(zhí)行過(guò)程中拋出的異常處理。提供了一個(gè)容器給鏈并提供了一個(gè)用于管理沿著鏈入站和出站事件的流動(dòng)。子類(lèi)通過(guò)進(jìn)行注冊(cè)。 前兩天寫(xiě)了一點(diǎn)netty相關(guān)的知識(shí),并寫(xiě)了一個(gè)demo,但是對(duì)其原理還是沒(méi)有深入,今天我們來(lái)做一次研究吧 首先讓我們來(lái)認(rèn)識(shí)一下netty的幾個(gè)核心人物吧...
摘要:它使用了事件通知以確定在一組非阻塞套接字中有哪些已經(jīng)就緒能夠進(jìn)行相關(guān)的操作。目前,可以把看作是傳入入站或者傳出出站數(shù)據(jù)的載體。出站事件是未來(lái)將會(huì)觸發(fā)的某個(gè)動(dòng)作的操作結(jié)果,這些動(dòng)作包括打開(kāi)或者關(guān)閉到遠(yuǎn)程節(jié)點(diǎn)的連接將數(shù)據(jù)寫(xiě)到或者沖刷到套接字。 netty的概念 定義 Netty 是一款異步的事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架,支持快速地開(kāi)發(fā)可維護(hù)的高性能的面向協(xié)議的服務(wù)器和客戶端。我們可以很簡(jiǎn)單的...
摘要:最后五年工作經(jīng)驗(yàn)以上。所以我希望大家也可以深入某項(xiàng)核心技術(shù)去好好研究。公眾號(hào)貓說(shuō)現(xiàn)架構(gòu)設(shè)計(jì)碼農(nóng)兼創(chuàng)業(yè)技術(shù)顧問(wèn),不羈平庸,熱愛(ài)開(kāi)源,雜談程序人生與不定期干貨。 本博客 貓叔的博客,轉(zhuǎn)載請(qǐng)申明出處 前言 感謝粉絲提問(wèn),由于我最近工作較忙,所以今晚抽空回復(fù)問(wèn)題,可能有點(diǎn)倉(cāng)促,回答的不是很全,不過(guò)希望能對(duì)你有所幫助。 整理自己的技術(shù)棧 首先,我需要你整理出自己一份滿意的簡(jiǎn)歷,我希望程序員可以每...
摘要:,一般稱(chēng)為選擇器。它是核心組件中的一個(gè),用于輪詢一個(gè)或多個(gè)的狀態(tài)是否處于可讀可寫(xiě)。如此,一個(gè)線程就可以管理多個(gè),也就說(shuō)可以管理多個(gè)網(wǎng)絡(luò)連接。 Selector , 一般稱(chēng)為選擇器。它是 Java NIO 核心組件中的一個(gè),用于輪詢一個(gè)或多個(gè) NIO Channel 的狀態(tài)是否處于可讀、可寫(xiě)。如此,一個(gè)線程就可以管理多個(gè) Channel ,也就說(shuō)可以管理多個(gè)網(wǎng)絡(luò)連接。也因此,Select...
摘要:前提好幾周沒(méi)更新博客了,對(duì)不斷支持我博客的童鞋們說(shuō)聲抱歉了。熟悉我的人都知道我寫(xiě)博客的時(shí)間比較早,而且堅(jiān)持的時(shí)間也比較久,一直到現(xiàn)在也是一直保持著更新?tīng)顟B(tài)。 showImg(https://segmentfault.com/img/remote/1460000014076586?w=1920&h=1080); 前提 好幾周沒(méi)更新博客了,對(duì)不斷支持我博客的童鞋們說(shuō)聲:抱歉了!。自己這段時(shí)...
閱讀 1343·2019-08-30 15:55
閱讀 1645·2019-08-26 10:21
閱讀 3438·2019-08-23 18:28
閱讀 3375·2019-08-23 15:38
閱讀 744·2019-08-23 15:24
閱讀 2135·2019-08-23 13:59
閱讀 775·2019-08-23 11:31
閱讀 2871·2019-08-23 10:53