2018/1/19 Netty學習筆記(一)

這段時間學了好多好多東西,不過更可能是細節和思想上的,好比分佈式事物,二次提交,改善代碼質量,還有一些看了一些源碼什麼的;java

記錄一下真正的技術學習,關於Netty的學習過程;web

首先說Netty以前先說一下BIO,NIO和AIO的區別吧,我這裏對於AIO只說個大概,下午或者晚上有時間會寫個具體的,其實原本想說說websocket的不過太基礎了,各位百度下就行;api

BIO,NIO和AIO的區別
BIO也就是同步阻塞的I/O,由JAVA程序本身處理I/O流操做;一個線程啓用I/O請求後,必須等I/O處理完畢才能進行下一步;
NIO是同步非阻塞的I/O,仍是由JAVA處理應用操做,不過單獨開啓一個線程去作I/O處理,並且會將數據讀寫到一個Buffer緩衝區中,以後交由OS去進行處理,缺點是須要多路複用器不斷去輪詢,在觸發I/O操做後,用戶線程也會須要時不時的去訪問查看是否已經完成(jdk7後已經使用了epoll進行了改善)
AIO也就是NIO2.0,只須要發起一個I/O請求,以後具體的I/O操做都交由系統完成,系統在完成後會自行通知程序;緩存

不論是NIO仍是AIO都是避免了傳統BIO使用TCP鏈接建立輸出和輸入流通道進行通訊的弊端,它們使用的是http長鏈接創建了一個可讀寫的通道(channel);websocket

Channel 管道(這裏只說網絡讀寫的Channel (SelecttableChannel 它有兩個子類SocketChannel和ServerSockerChannel)避免了傳統BIO的三次握手模型創建的OutputStream,InputStream鏈接通道),既能夠讀也能夠寫,也能夠讀寫同時進行,而且channel上有四種狀態位,分別是(Connect 鏈接狀態,Accept 阻塞狀態,Read 可讀狀態,Write 可寫狀態)不論是讀寫數據都是要先進入一個Buffer中,
而Buffer其實也是一個對象,有對應JAVA八種基本數據類型的八種緩存區,但咱們通常使用ByteBuffer對象進行讀寫的存儲就夠了;網絡


Selector 多路複用器,管理着一個註冊的通道集合的信息和它們的就緒狀態(使用輪詢),若是某個通道發生了讀寫操做,會被它輪詢出來,並經過SelectionKey能夠取得就緒的Channel集合,從而進行後續的I/O操做;
一個Selector能夠管理成千上萬個Channel通道,若是使用傳統的輪詢機制就會使得性能很底下,因此JDK使用了epoll(內部對於通道的節點位置使用紅黑樹存儲,對於每一個通道都添加了一個事件,只有當進程調用了必定的方法後,掃描纔會被觸發,並且能夠並利用紅黑樹快速找到通道的節點位置)
Selector模式: 當管道註冊到選擇器之後,selector會分配給每一個管道一個key值,至關於標籤.selector選擇器是以輪詢的方式方式進行查找註冊的全部IO事件(管道),當咱們的IO事件(管道準備就緒後),selector會識別,並經過對應的key值找到對應的管道,進行相關的數據處理操做(從管道中讀獲寫數據,讀的話就是寫到咱們的數據緩衝區中).socket

每一個管道都有不一樣的事件狀態,以便選擇器查找;
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE分佈式


//Buffer api
public void test() {
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
byteBuffer.put((byte) 1);
byteBuffer.put((byte) 2);
System.out.println(byteBuffer);
// 打印此緩衝區,注意看它的結構 java.nio.HeapByteBuffer[pos=2 lim=10 cap=10]
// pos:至關於一個遊標,lim是具體長度,cap是容量上限,能夠看到如今lim長度不對
// 復位
byteBuffer.flip();
System.out.println(byteBuffer);
// 此時再打印 java.nio.HeapByteBuffer[pos=0 lim=2 cap=10]能夠看到遊標變成了0,lim也正常了;
//爲何會這樣?
/* public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}*/
//看源碼就知道了,那麼若是不復位會發生什麼呢?當你想取得數據的時候會發現會把後面沒有數據的部分也打印出來
//咱們在復位的狀況下打印下試試
for (int i = 0; i < byteBuffer.limit(); i++) {
byte b = byteBuffer.get(i);
System.out.print(b+"\t");
}
//結果爲1 2
//再看看不復位的狀況下是什麼 1 2 0 0 0 0 0 0 0 0 ,也就是說咱們要保證limit,也就是實際長度的準備性性能

//事實上,若是咱們使用調用get()方法,也就是不經過索引查找數據,而且在沒有復位的狀況下,會連1 2都顯示不出來,而是直接顯示後面的默認值數據,由於get方法是以pos遊標當前處日後推,而且還會致使溢出異常,由於不復位的狀況下,limit是最大容量,也就是10;就算是默認值數據,也是如下標爲準的,也就是10個數據,最大下標就是9,而get()會一直到10;

}學習

相關文章
相關標籤/搜索