摘要:豐富的緩存數(shù)據(jù)結(jié)構(gòu)使用它自己的緩存來(lái)表示字節(jié)序列而不是的。針對(duì)有一個(gè)定義良好的事件模型。有一些協(xié)議是多層的建立在其他低級(jí)協(xié)議基礎(chǔ)上。此外,甚至不是完全線程安全的。協(xié)議由標(biāo)準(zhǔn)化為。協(xié)議緩存整合是一個(gè)高效二進(jìn)制協(xié)議的快速實(shí)現(xiàn)。
Chapter 2、結(jié)構(gòu)概覽
這一節(jié)我們將確認(rèn)Netty提供的核心功能是什么,以及它們?cè)趺礃?gòu)成一個(gè)完整的網(wǎng)絡(luò)應(yīng)用開發(fā)堆棧。
1、豐富的緩存數(shù)據(jù)結(jié)構(gòu)Netty使用它自己的緩存API來(lái)表示字節(jié)序列而不是NIO的ByteBuffer。Netty的新緩存類——ChannelBuffer,徹底解決了ByteBuffer的問(wèn)題,滿足了網(wǎng)絡(luò)應(yīng)用開發(fā)者的日常需求。這里列舉幾個(gè)很酷的特點(diǎn):
需要的話你可以自定義緩存類
通過(guò)一個(gè)內(nèi)置的組合緩存類實(shí)現(xiàn)零拷貝組合
提供開箱即用的動(dòng)態(tài)緩存,自動(dòng)擴(kuò)容,就像StringBuffer一樣
不再需要調(diào)用flip方法
通常比ByteBuffer要快
組合和切分ChannelBuffer當(dāng)在通信層傳輸數(shù)據(jù)時(shí),數(shù)據(jù)經(jīng)常需要被組合或者切分。比如一次裝載被分成多個(gè)包,但是經(jīng)常需要組合起來(lái)解碼。
傳統(tǒng)方式來(lái)說(shuō),多個(gè)包的數(shù)據(jù)通過(guò)復(fù)制到一個(gè)新的字節(jié)緩存而組合起來(lái)。
Netty支持零復(fù)制實(shí)現(xiàn),通過(guò)讓一個(gè)新的ChannelBuffer“指向”所有要求組合的緩存,從而避免了復(fù)制操作。
傳統(tǒng)Java的I/O API對(duì)不同的傳輸類型提供不同的類和方法。舉個(gè)例子,java.net.Socket和java.net.DatagramSocket沒(méi)有公共父類因此它們?cè)趫?zhí)行socket I/O的方式完全不一樣。
這種不匹配的結(jié)果就是使得應(yīng)用程序從一種傳輸方式移植成另一種變得十分困難。也就是說(shuō)你需要支持額外的傳輸方式因?yàn)閼?yīng)用程序的網(wǎng)絡(luò)層經(jīng)常涉及到重寫。邏輯上,許多協(xié)議可以在不只一種傳輸方式,比如TCP/IP、UDO/IP、SCTP和串行通信上運(yùn)行。
更糟的是,Java的新I/O(NIO)API繼承了老阻塞I/O(OIO)API的不兼容性,并且在下一個(gè)版本NIO.2(AIO)繼續(xù)這樣做。因?yàn)檫@些API在設(shè)計(jì)和表現(xiàn)特點(diǎn)上完全不同,你經(jīng)常被迫在應(yīng)用程序開始實(shí)現(xiàn)之前就需要確定好依賴那種API。
舉個(gè)例子,你可能想用OIO方式開始因?yàn)槟惴?wù)的客戶數(shù)量很小且用OIO寫一個(gè)socket服務(wù)比用NIO要簡(jiǎn)單得多。但是,當(dāng)你的業(yè)務(wù)呈指數(shù)級(jí)上升然后你需要同時(shí)服務(wù)成千上萬(wàn)的客戶時(shí),麻煩就大了。你也可以用NIO方式開始,但是這可能會(huì)阻礙開發(fā)速度,畢竟NIO的選擇器API很復(fù)雜。
Netty擁有統(tǒng)一的異步I/O接口——Channel,它抽象了點(diǎn)對(duì)點(diǎn)通信要求的所有操作。只要你用一種Netty傳輸寫的應(yīng)用程序,可以在其他Netty傳輸上運(yùn)行。Nett通過(guò)統(tǒng)一的API提供了必要的傳輸方式:
基于NIO的TCP/IP傳輸(見(jiàn)org.jboss.netty.channel.socket.nio)
基于OIO的TCP/IP傳輸(見(jiàn)org.jboss.netty.channel.socket.oio)
基于OIO的UDP/IP傳輸
本地傳輸(見(jiàn)org.jboss.netty.channel.local)
要從一種傳輸方式切換到另一種,只需要改動(dòng)幾行代碼,比如選擇另一個(gè)ChannelFactory實(shí)現(xiàn)。
你甚至可以使用還沒(méi)發(fā)布的新傳輸方式,比如串行通信傳輸,同樣替換幾行構(gòu)造器調(diào)用的代碼。再者,你也可以通過(guò)繼承核心API實(shí)現(xiàn)自己的傳輸方式。
3、基于過(guò)濾鏈模式的事件模型一個(gè)定義良好的并可擴(kuò)展性高的事件模型是一個(gè)事件驅(qū)動(dòng)應(yīng)用程序的前提。Netty針對(duì)I/O有一個(gè)定義良好的事件模型。你可以在不破壞已有代碼的情況下實(shí)現(xiàn)你自己的事件類,因?yàn)槊恳粋€(gè)事件類都根據(jù)一個(gè)嚴(yán)格的類層次體系區(qū)別于其他事件類。這是另一個(gè)和其他框架的不同點(diǎn)。很多NIO框架都沒(méi)有或者很有限的事件模型概念。如果它們提供了擴(kuò)展,就會(huì)經(jīng)常在嘗試增加自定義事件類時(shí)破壞已有代碼。
一個(gè)ChannelEvent由一個(gè)ChannelPipeline里的一列ChannelHandler來(lái)處理。這個(gè)管道實(shí)現(xiàn)了一個(gè)過(guò)濾鏈模式的高級(jí)形式,讓使用者完全控制一個(gè)事件如何被處理以及管道內(nèi)的handler如何相互聯(lián)系。舉個(gè)例子,你可以規(guī)定數(shù)據(jù)從socket讀取時(shí)做點(diǎn)什么:
public class MyReadHandler implements SimpleChannelHandler { public void messageReceived(ChannelHandlerContext ctx, MessageEvent evt) { Object message = evt.getMessage(); // Do something with the received message. ... // And forward the event to the next handler. ctx.sendUpstream(evt); } }
你也可以規(guī)定一個(gè)handler在接收一個(gè)寫請(qǐng)求時(shí)做點(diǎn)什么:
public class MyWriteHandler implements SimpleChannelHandler { public void writeRequested(ChannelHandlerContext ctx, MessageEvent evt) { Object message = evt.getMessage(); // Do something with the message to be written. ... // And forward the event to the next handler. ctx.sendDownstream(evt); } }4、支持更快速開發(fā)的高級(jí)組件 4.1、編解碼框架
之前“用POJO替代ChannelBuffer”那一節(jié)證實(shí)了,把協(xié)議編解碼從業(yè)務(wù)邏輯中分離出來(lái)通常是一個(gè)好主意。但是從零開始實(shí)現(xiàn)有一些困難。你需要處理信息分片。有一些協(xié)議是多層的(建立在其他低級(jí)協(xié)議基礎(chǔ)上)。還有一些協(xié)議在單機(jī)系統(tǒng)上實(shí)現(xiàn)特別困難。
因此,一個(gè)好的網(wǎng)絡(luò)應(yīng)用框架需要提供一個(gè)可擴(kuò)展的、可重用的、可單元測(cè)試的和多層級(jí)的編解碼器框架,產(chǎn)生可維護(hù)的用戶編解碼器。
Netty提供了一系列基礎(chǔ)和高級(jí)的編解碼器,可以解決你在寫一個(gè)協(xié)議編解碼器是遭遇的大多數(shù)問(wèn)題,無(wú)論編解碼器是否簡(jiǎn)單,是二進(jìn)制的還是文本的。
4.2、SSL/TLS支持不像阻塞I/O,在NIO支持SSL是個(gè)值得正視對(duì)任務(wù)。你不能簡(jiǎn)單得包裝一個(gè)流對(duì)數(shù)據(jù)進(jìn)行加密解密,你必須要用到j(luò)avax.net.ssl.SSLEngine。SSLEngine是一個(gè)跟SSL本身一樣復(fù)雜的狀態(tài)機(jī)。你需要處理所有可能的狀態(tài),如密碼套件、加密密鑰協(xié)商、證書交換以及驗(yàn)證。此外,SSL甚至不是完全線程安全的。
在Netty,SslHandler負(fù)責(zé)對(duì)外屏蔽SSLEngine所有細(xì)枝末節(jié),你只需要配置SslHandler然后添加到你的ChannelPipeline中。SslHandler同時(shí)讓你可以很容易實(shí)現(xiàn)類似StartTLS的高級(jí)特性。
4.3、HTTP實(shí)現(xiàn)HTTP絕對(duì)是互聯(lián)網(wǎng)最流行的協(xié)議?,F(xiàn)在已經(jīng)有一系列HTTP實(shí)現(xiàn),比如Servlet容器。那么為什么Netty還要自己實(shí)現(xiàn)HTTP呢?
Netty的HTTP支持和現(xiàn)有的HTTP庫(kù)很不一樣。它讓你可以完全控制HTTP在底層的消息交換。因?yàn)閺母旧蟻?lái)說(shuō),它就是一個(gè)HTTP編解碼器和HTTP消息類的結(jié)合,沒(méi)有類似強(qiáng)制線程模型這樣的限制。也就是說(shuō),你可以按照你希望的工作方式來(lái)實(shí)現(xiàn)HTTP客戶端和服務(wù)端。你擁有所有HTTP規(guī)范內(nèi)的控制權(quán),包括線程模型、連接生命周期和分塊編碼。
基于它的高可定制性,你可以寫一個(gè)高效的HTTP服務(wù):
要求持續(xù)連接和服務(wù)推送技術(shù)的聊天服務(wù)(如Comet);
需要保持連接直到整個(gè)媒體文件流傳輸完畢的媒體流服務(wù)(如兩小時(shí)的電影);
無(wú)內(nèi)存壓力上傳大文件的文件服務(wù)(如上傳1G文件);
可以異步連接成千上萬(wàn)的第三方web服務(wù)的可伸縮的混合客戶端
4.4、WebSocket實(shí)現(xiàn)WebSocket在單TCP socket上實(shí)現(xiàn)一個(gè)雙向全雙工通信通道,用于web瀏覽器和web服務(wù)端端數(shù)據(jù)交互。
WebSocket協(xié)議由IETF標(biāo)準(zhǔn)化為RFC 6455。
Netty實(shí)現(xiàn)了RFC 6455和一系列舊版本規(guī)范。
Google Protocal Buffers是一個(gè)高效二進(jìn)制協(xié)議的快速實(shí)現(xiàn)。憑借ProtobufEncoder和ProtobufDecoder,你可以將Goodgle Protocal Buffers編譯程序生成的信息類轉(zhuǎn)化為Netty編解碼器。
5、總結(jié)這一節(jié),我們從特點(diǎn)出發(fā)回顧了Netty的總體架構(gòu)。Netty擁有一個(gè)簡(jiǎn)單且至今仍強(qiáng)大的架構(gòu)。它由三個(gè)組件組成——buffer,channel和事件模型,所有高級(jí)特性都是在這三個(gè)組件的基礎(chǔ)上建立的。只要你理解了這三個(gè)組件是如何一起工作的,你就不難理解這節(jié)簡(jiǎn)要提及的那些高級(jí)特性。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/74242.html
摘要:但是它不是自己創(chuàng)建線程,而是從調(diào)用構(gòu)造方法時(shí)指定的線程池中獲取線程。這就意味著,即使發(fā)送兩個(gè)獨(dú)立的消息,操作系統(tǒng)會(huì)把他們視為一個(gè)字節(jié)串。釋放過(guò)程很簡(jiǎn)單,調(diào)用它的方法,所有相關(guān)的和線程池將會(huì)自動(dòng)關(guān)閉。 簡(jiǎn)單找了下發(fā)現(xiàn)網(wǎng)上沒(méi)有關(guān)于Netty3比較完整的源碼解析的文章,于是我就去讀官方文檔,為了加強(qiáng)記憶,翻譯成了中文,有適當(dāng)?shù)暮?jiǎn)化。 原文檔地址:Netty3文檔 Chapter 1 開始 1...
摘要:的選擇器允許單個(gè)線程監(jiān)視多個(gè)輸入通道。一旦執(zhí)行的線程已經(jīng)超過(guò)讀取代碼中的某個(gè)數(shù)據(jù)片段,該線程就不會(huì)在數(shù)據(jù)中向后移動(dòng)通常不會(huì)。 1、引言 很多初涉網(wǎng)絡(luò)編程的程序員,在研究Java NIO(即異步IO)和經(jīng)典IO(也就是常說(shuō)的阻塞式IO)的API時(shí),很快就會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題:我什么時(shí)候應(yīng)該使用經(jīng)典IO,什么時(shí)候應(yīng)該使用NIO? 在本文中,將嘗試用簡(jiǎn)明扼要的文字,闡明Java NIO和經(jīng)典IO之...
摘要:英文全名為,也叫遠(yuǎn)程過(guò)程調(diào)用,其實(shí)就是一個(gè)計(jì)算機(jī)通信協(xié)議,它是一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù)而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。 Hello,Dubbo 你好,dubbo,初次見(jiàn)面,我想和你交個(gè)朋友。 Dubbo你到底是什么? 先給出一套官方的說(shuō)法:Apache Dubbo是一款高性能、輕量級(jí)基于Java的RPC開源框架。 那么什么是RPC? 文檔地址:http://dubbo.a...
摘要:文檔翻譯系列二開始最簡(jiǎn)單的方式就是在上使用示例。最小的例子如下它會(huì)在頁(yè)面上渲染一個(gè)標(biāo)題。接下來(lái)的幾部分會(huì)逐步的介紹如何使用。我們會(huì)查驗(yàn)應(yīng)用的構(gòu)建塊元素和組件。在例子中也使用了一些的語(yǔ)法??梢允褂迷诰€轉(zhuǎn)換器查看的代碼編譯。 React文檔翻譯系列(二)Hello World Hello World 開始React最簡(jiǎn)單的方式就是在CodePen上使用Hello World示例。無(wú)需安裝任...
摘要:開始翻譯函數(shù)式編程專有名詞庫(kù)在翻譯的過(guò)程中,難免會(huì)遇到很多描述不太清楚的專有名詞,一個(gè)辦法是小組內(nèi)進(jìn)行討論,最后商量出來(lái)結(jié)果,小組內(nèi)統(tǒng)一翻譯。因?yàn)楸緯闹黝}是函數(shù)式編程,所以這個(gè)名詞庫(kù)里大部分都是函數(shù)式編程相關(guān)的專有名詞。 在平時(shí)的工作中,我們都會(huì)經(jīng)常查閱一些英文文檔來(lái)解決平時(shí)遇到的問(wèn)題和拓寬視野??吹胶玫奈恼禄蛘邥袥](méi)有想要和小伙伴分享的沖動(dòng),那么我們一起來(lái)翻譯吧~ 翻譯主張 信 ...
閱讀 2990·2021-11-16 11:45
閱讀 5191·2021-09-22 10:57
閱讀 1775·2021-09-08 09:36
閱讀 1605·2021-09-02 15:40
閱讀 2517·2021-07-26 23:38
閱讀 1206·2019-08-30 15:55
閱讀 931·2019-08-30 15:54
閱讀 1223·2019-08-29 14:06