HTTP服務器之因此稱爲HTTP服務器,是由於編碼解碼協議是HTTP協議,若是協議是Redis協議,那它就成了Redis服務器,若是協議是WebSocket,那它就成了WebSocket服務器,等等。程序員
使用Netty你就能夠定製編解碼協議,實現本身的特定協議的服務器。數據庫
上面咱們說的是一個傳統的多線程服務器,這個也是Apache處理請求的模式。在高併發環境下,線程數量可能會建立太多,操做系統的任務調度壓力大,系統負載也會比較高。那怎麼辦呢?緩存
因而NIO誕生了,NIO並非Java獨有的概念,NIO表明的一個詞彙叫着IO多路複用。它是由操做系統提供的系統調用,早期這個操做系統調用的名字是select,可是性能低下,後來漸漸演化成了Linux下的epoll和Mac裏的kqueue。咱們通常就說是epoll,由於沒有人拿蘋果電腦做爲服務器使用對外提供服務。而Netty就是基於Java NIO技術封裝的一套框架。爲何要封裝,由於原生的Java NIO使用起來沒那麼方便,並且還有臭名昭著的bug,Netty把它封裝以後,提供了一個易於操做的使用模式和接口,用戶使用起來也就便捷多了。服務器
那NIO到底是什麼東西呢?多線程
NIO的全稱是NoneBlocking IO,非阻塞IO,區別與BIO,BIO的全稱是Blocking IO,阻塞IO。那這個阻塞是什麼意思呢?併發
因此傳統的多線程服務器是BlockingIO模式的,從頭至尾全部的線程都是阻塞的。這些線程就乾等在哪裏,佔用了操做系統的調度資源,什麼事也不幹,是浪費。框架
那麼NIO是怎麼作到非阻塞的呢。它用的是事件機制。它能夠用一個線程把Accept,讀寫操做,請求處理的邏輯全乾了。若是什麼事都沒得作,它也不會死循環,它會將線程休眠起來,直到下一個事件來了再繼續幹活,這樣的一個線程稱之爲NIO線程。高併發
while true { events = takeEvents(fds) // 獲取事件,若是沒有事件,線程就休眠 for event in events { if event.isAcceptable { doAccept() // 新連接來了 } elif event.isReadable { request = doRead() // 讀消息 if request.isComplete() { doProcess() } } elif event.isWriteable { doWrite() // 寫消息 } } }
NIO的流程大體就是上面的僞代碼描述的過程,跟實際真實的代碼有較多差別,不過對於初學者,這樣理解也是足夠了。性能
Netty是創建在NIO基礎之上,Netty在NIO之上又提供了更高層次的抽象。優化
在Netty裏面,Accept鏈接可使用單獨的線程池去處理,讀寫操做又是另外的線程池來處理。
Accept鏈接和讀寫操做也可使用同一個線程池來進行處理。而請求處理邏輯既可使用單獨的線程池進行處理,也能夠跟放在讀寫線程一塊處理。線程池中的每個線程都是NIO線程。用戶能夠根據實際狀況進行組裝,構造出知足系統需求的併發模型。
Netty提供了內置的經常使用編解碼器,包括行編解碼器[一行一個請求],前綴長度編解碼器[前N個字節定義請求的字節長度],可重放解碼器[記錄半包消息的狀態],HTTP編解碼器,WebSocket消息編解碼器等等。
Netty提供了一些列生命週期回調接口,當一個完整的請求到達時,當一個鏈接關閉時,當一個鏈接創建時,用戶都會收到回調事件,而後進行邏輯處理。
Netty能夠同時管理多個端口,可使用NIO客戶端模型,這些對於RPC服務是頗有必要的。
Netty除了能夠處理TCP Socket以外,還能夠處理UDP Socket。
在消息讀寫過程當中,須要大量使用ByteBuffer,Netty對ByteBuffer在性能和使用的便捷性上都進行了優化和抽象。
總之,Netty是Java程序員進階的必備神器。若是你知其然,還想知其因此然,必定要好好研究下Netty。若是你以爲Java枯燥無謂,Netty則是從新開啓你對Java興趣大門的鑰匙。
轉載連接:https://www.zhihu.com/question/24322387/answer/282001188