- 創建一個ServerSocket,監聽並綁定一個端口
- 一系列客戶端來請求這個端口
- 服務器使用Accept,獲得一個來自客戶端的Socket連接對象
- 啟動一個新線程處理連接
- 讀Socket,得到字節流
- 解碼協議,得到Http請求對象
- 處理Http請求,得到一個結果,封裝成一個HttpResponse對象
- 編碼協議,將結果序列化字節流
- 寫Socket,將字節流發給客戶端
- 繼續循環步驟3
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。那這個阻塞是什么意思呢?
- Accept是阻塞的,只有新連接來了,Accept才會返回,主線程才能繼
- Read是阻塞的,只有請求消息來了,Read才能返回,子線程才能繼續處理
- Write是阻塞的,只有客戶端把消息收了,Write才能返回,子線程才能繼續讀取下一個請求
所以傳統的多線程服務器是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