? Netty中的Channel是與網(wǎng)絡(luò)套接字相關(guān)的,可以理解為是socket連接,在客戶端與服務(wù)端連接的時(shí)候就會(huì) 建立一個(gè)Channel,它負(fù)責(zé)基本的IO操作,比如:bind()、connect(),read(),write() 等 ? 主要作用:
站在用戶的角度思考問題,與客戶深入溝通,找到鶴慶網(wǎng)站設(shè)計(jì)與鶴慶網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、空間域名、網(wǎng)站空間、企業(yè)郵箱。業(yè)務(wù)覆蓋鶴慶地區(qū)。1. 通過Channel可獲得當(dāng)前網(wǎng)絡(luò)連接的通道狀態(tài)。
2. 通過Channel可獲得網(wǎng)絡(luò)連接的配置參數(shù)(緩沖區(qū)大小等)。
3. Channel提供異步的網(wǎng)絡(luò)I/O操作,比如連接的建立、數(shù)據(jù)的讀寫、端口的綁定等。
? 不同協(xié)議、不同的I/O類型的連接都有不同的 Channel 類型與之對(duì)
EventLoopGroup&EventLoop? Netty是基于事件驅(qū)動(dòng)的,比如:連接注冊(cè),連接激活;數(shù)據(jù)讀?。划惓J录鹊?,有了事件,就需要一 個(gè)組件去監(jiān)控事件的產(chǎn)生和事件的協(xié)調(diào)處理,這個(gè)組件就是EventLoop(事件循環(huán)/EventExecutor),在 Netty 中每個(gè)Channel 都會(huì)被分配到一個(gè) EventLoop。一個(gè) EventLoop 可以服務(wù)于多個(gè) Channel。每個(gè) EventLoop 會(huì)占用一個(gè) Thread,同時(shí)這個(gè) Thread 會(huì)處理 EventLoop 上面發(fā)生的所有 IO 操作和事件。
? EventLoopGroup 是用來生成 EventLoop 的,包含了一組EventLoop(可以初步理解成Netty線程池)
eventLoopThreads 是多少?
EventLoopGroup 是接口,我們采用的實(shí)現(xiàn)是NioEventLoopGroup
// 主線程,不處理任何業(yè)務(wù)邏輯,只是接收客戶的連接請(qǐng)求
EventLoopGroup boss = new NioEventLoopGroup();
// 工作線程,處理注冊(cè)其上Channel的I/O事件及其他
Task EventLoopGroup worker = new NioEventLoopGroup();
?核心線程數(shù)默認(rèn):cpu核數(shù)*2
?核心線程數(shù)在創(chuàng)建時(shí)可通過構(gòu)造函數(shù)指定
?對(duì)于boss group,我們其實(shí)也 只用到了其中的一個(gè)線程因?yàn)榉?wù)端一般只會(huì)綁定一個(gè)端口啟動(dòng)
ChannelHandler&ChannelHandlerContext&ChannelPipeline(這些組件比較重要,單獨(dú)在netty從入門到精通(中)詳細(xì)做了介紹)
netty從入門到精通(中)http://t.csdn.cn/DDMaA
ChannelHandler復(fù)用
每個(gè)客戶端Channel創(chuàng)建后初始化時(shí), 均會(huì)向與該Channel綁定的Pipeline中 添加handler,此種模式下,每個(gè) Channel享有的是各自獨(dú)立的Handler
@Sharable注解可以解決這個(gè)問題
備注:handler被復(fù)用可能導(dǎo)致線程安全問題,比如在handler中操作成員變量。線程安全的問題需要開發(fā)者自行保證。
ChannelInboundHandlerAdapter&SimpleChannelInboundHandler對(duì)于編寫Netty數(shù)據(jù)入站處理器,可以選擇繼承 ChannelInboundHandlerAdapter,也可以選擇繼承 SimpleChannelInboundHandler,區(qū)別是什么?
ByteBuf概念和作用:
? Java NIO 提供了ByteBuffer 作為它的字節(jié)容器,但是這個(gè)類使用起來過于復(fù)雜,而且也有些繁瑣。Netty 使用ByteBuf來替代ByteBuffer,它是一個(gè)強(qiáng)大的實(shí)現(xiàn),既解決了JDK API 的局限性, 又為網(wǎng)絡(luò)應(yīng)用程序的 開發(fā)者提供了更好的API
? 從結(jié)構(gòu)上來說,ByteBuf 由一串字節(jié)數(shù)組構(gòu)成。數(shù)組中每個(gè)字節(jié)用來存放信息,ByteBuf提供了兩個(gè)索引, 一個(gè)用于讀取數(shù)據(jù)(readerIndex ),一個(gè)用于寫入數(shù)據(jù)(writerIndex)。這兩個(gè)索引通過在字節(jié)數(shù)組中 移動(dòng),來定位需要讀或者寫信息的位置。而JDK的ByteBuffer只有一個(gè)索引,因此需要使用flip方法進(jìn)行讀 寫切換
ByteBuf的三個(gè)指針
? readerIndex:指示讀取的起始位置, 每讀取一個(gè)字節(jié), readerIndex自增累加1。 如果readerIndex 與 writerIndex 相等,ByteBuf 不可讀。
? writerIndex:指示寫入的起始位置, 每寫入一個(gè)字節(jié), writeIndex自增累加1。如果增加到 writerIndex 與 capacity() 容量相等,表示 ByteBuf 已經(jīng)不可寫,但是這個(gè)時(shí)候,并不代表不能往 ByteBuf 中寫數(shù)據(jù)了, 如果 發(fā)現(xiàn)往ByteBuf 中寫數(shù)據(jù)寫不進(jìn)去的話,Netty 會(huì)自動(dòng)擴(kuò)容 ByteBuf,直到擴(kuò)容到底層的內(nèi)存大小為 maxCapacity
? maxCapacity:指示ByteBuf 可以擴(kuò)容的大容量, 如果向ByteBuf寫入數(shù)據(jù)時(shí), 容量不足, 可以進(jìn)行擴(kuò)容的最 大容量
常用API
容量API:
讀寫指針相關(guān)的API:
讀寫操作API:
丟棄、清理,釋放:
wrap:
通過Wrap操作可以快速轉(zhuǎn)換或得到一個(gè)ByteBuf對(duì)象,Unpooled 工具類中提供了很多重載的wrappedBuffer方法
理解:wrappedBuffer相當(dāng)于剪切粘貼,copiedBuffer相當(dāng)于復(fù)制粘貼
ByteBuf分類
1.按照內(nèi)存位置劃分:分為Heap 和 Direct?
? 堆緩沖區(qū)(HeapByteBuf):內(nèi)存分配在jvm堆,分配和回收速度比較快,可以被JVM自動(dòng)回收,缺點(diǎn)是,如果進(jìn)行 socket的IO讀寫,需要額外做一次內(nèi)存復(fù)制,將堆內(nèi)存對(duì)應(yīng)的緩沖區(qū)復(fù)制到內(nèi)核Channel中,性能會(huì)有一定程度的下 降。由于在堆上被 JVM 管理,在不被使用時(shí)可以快速釋放。可以通過 ByteBuf.array() 來獲取 byte[] 數(shù)據(jù)。
? 直接緩沖區(qū)(DirectByteBuf):內(nèi)存分配的是堆外內(nèi)存(系統(tǒng)內(nèi)存),相比堆內(nèi)存,它的分配和回收速度會(huì)慢一些, 但是將它寫入或從Socket Channel中讀取時(shí),由于減少了一次內(nèi)存拷貝,速度比堆內(nèi)存塊。
? 復(fù)合緩沖區(qū)(CompositeByteBuf):顧名思義就是將兩個(gè)不同的緩沖區(qū)從邏輯上合并,讓使用更加方便。
Netty默認(rèn)使用的是DirectByteBuf,如果需要使用HeapByteBuf模式,則需要進(jìn)行系統(tǒng)參數(shù)的設(shè)置
堆外內(nèi)存
2.根據(jù)內(nèi)存結(jié)構(gòu):Pooled 池化內(nèi)存和 Unpooled 非池化內(nèi)存
? 對(duì)于Pooled類型的ByteBuf,不管是PooledDirectByteBuf還是PooledHeapByteBuf都只能由Netty內(nèi)部自己使用(構(gòu)造是私有和受保護(hù)的)。 ? Netty提供Unpooled工具類創(chuàng)建的ByteBuf都是unpooled類型,默認(rèn)采用的Allocator是direct類型;當(dāng)然用戶可以自己選擇創(chuàng)建UnpooledDirectByteBuf和UnpooledHeapByteBuf3.Unsafe 和非 Unsafe
Unsafe:是 JDK 底層的一個(gè)負(fù)責(zé) IO 操作的對(duì)象,可以直接拿到對(duì)象的內(nèi)存地址,基于內(nèi)存地址進(jìn)行讀寫操作。
ByteBuf 的釋放 ByteBuf如果采用的是堆緩沖區(qū)模式的話,可以由GC回收,但是如果采用的是直接緩沖區(qū),就不受GC的管理,就得手 動(dòng)釋放,否則會(huì)發(fā)生內(nèi)存泄露,Netty自身引入了引用計(jì)數(shù),提供了ReferenceCounted接口,當(dāng)對(duì)象的引用計(jì)數(shù)>0 時(shí)要保證對(duì)象不被釋放,當(dāng)為0時(shí)需要被釋放 關(guān)于ByteBuf的釋放,分為手動(dòng)釋放與自動(dòng)釋放: ? 手動(dòng)釋放 ,就是在使用完成后,調(diào)用ReferenceCountUtil.release(byteBuf); 進(jìn)行釋放,這種方式的弊端就是一旦忘 記釋放就可能會(huì)造成內(nèi)存泄露 ? 自動(dòng)釋放有三種方式 ,分別是: ? TailContext:Inbound流水線的末端,如果前面的handler都把消息向后傳遞最終由TailContext釋放該消息,需 要注意的是,如果沒有進(jìn)行向下傳遞,是不會(huì)進(jìn)行釋放操作的 ? SimpleChannelInboundHandler:自定義的InboundHandler繼承自SimpleChannelInboundHandler,在 SimpleChannelInboundHandler中自動(dòng)釋放 ? HeadContext:outbound流水線的末端,出站消息一般是由應(yīng)用所申請(qǐng),到達(dá)最后一站時(shí),經(jīng)過一輪復(fù)雜的調(diào) 用,在flush完成后終將被release掉你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧