簡單系統(tǒng)的介紹一下Netty。
在網(wǎng)絡(luò)編程體系設(shè)計中间螟,有幾個名詞概念簡單解釋一下:
1 什么是同步??
2 什么是異步??
3 什么是阻塞厢破??
4 什么是非阻塞荣瑟??
5 什么是同步阻塞??
6 什么是同步非阻塞摩泪??
7 什么是異步阻塞笆焰??
8 什么是異步非阻塞?
1,同步和異步是針對應(yīng)用程序和內(nèi)核的交互而言的加勤。?
2,阻塞和非阻塞是針對于進程在訪問數(shù)據(jù)的時候仙辟,根據(jù)IO操作的就緒狀態(tài)來采取的不同方式,說白了是一種讀取或者寫入操作函數(shù)的實現(xiàn)方式鳄梅,阻塞方式下讀取或者寫入函數(shù)將一直等待叠国,而非阻塞方式下,讀取或者寫入函數(shù)會立即返回一個狀態(tài)值戴尸。?
由上描述基本可以總結(jié)一句簡短的話粟焊,同步和異步是目的,阻塞和非阻塞是實現(xiàn)方式孙蒙。
1 同步 指的是用戶進程觸發(fā)IO操作并等待或者輪詢的去查看IO操作是否就緒 自己上街買衣服项棠,自己親自干這件事,別的事干不了挎峦。
2 異步 異步是指用戶進程觸發(fā)IO操作以后便開始做自己的事情香追,而當IO操作已經(jīng)完成的時候會得到IO完成的通知(異步的特點就是通知) 告訴朋友自己合適衣服的尺寸,大小坦胶,顏色透典,讓朋友委托去賣,然后自己可以去干別的事顿苇。(使用異步IO時峭咒,Java將IO讀寫委托給OS處理,需要將數(shù)據(jù)緩沖區(qū)地址和大小傳給OS)?
3 阻塞 所謂阻塞方式的意思是指, 當試圖對該文件描述符進行讀寫時, 如果當時沒有東西可讀,或者暫時不可寫, 程序就進入等待 狀態(tài), 直到有東西可讀或者可寫為止 去公交站充值纪岁,發(fā)現(xiàn)這個時候凑队,充值員不在(可能上廁所去了),然后我們就在這里等待幔翰,一直等到充值員回來為止漩氨。(當然現(xiàn)實社會,可不是這樣遗增,但是在計算機里確實如此叫惊。)?
4 非阻塞 非阻塞狀態(tài)下, 如果沒有東西可讀, 或者不可寫, 讀寫函數(shù)馬上返回, 而不會等待, 銀行里取款辦業(yè)務(wù)時贡定,領(lǐng)取一張小票赋访,領(lǐng)取完后我們自己可以玩玩手機,或者與別人聊聊天,當輪我們時蚓耽,銀行的喇叭會通知渠牲,這時候我們就可以去了。?
再來理解組合方式的IO類型
同步阻塞IO(JAVA BIO):?
同步并阻塞步悠,服務(wù)器實現(xiàn)模式為一個連接一個線程签杈,即客戶端有連接請求時服務(wù)器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷鼎兽,當然可以通過線程池機制改善答姥。?
同步非阻塞IO(Java NIO) : 同步非阻塞,服務(wù)器實現(xiàn)模式為一個請求一個線程谚咬,即客戶端發(fā)送的連接請求都會注冊到多路復(fù)用器上鹦付,多路復(fù)用器輪詢到連接有I/O請求時才啟動一個線程進行處理。用戶進程也需要時不時的詢問IO操作是否就緒择卦,這就要求用戶進程不停的去詢問敲长。?
異步阻塞IO(Java NIO):?
此種方式下是指應(yīng)用發(fā)起一個IO操作以后,不等待內(nèi)核IO操作的完成秉继,等內(nèi)核完成IO操作以后會通知應(yīng)用程序祈噪,這其實就是同步和異步最關(guān)鍵的區(qū)別,同步必須等待或者主動的去詢問IO是否完成尚辑,那么為什么說是阻塞的呢辑鲤?因為此時是通過select系統(tǒng)調(diào)用來完成的,而select函數(shù)本身的實現(xiàn)方式是阻塞的杠茬,而采用select函數(shù)有個好處就是它可以同時監(jiān)聽多個文件句柄(如果從UNP的角度看月褥,select屬于同步操作。因為select之后澈蝙,進程還需要讀寫數(shù)據(jù))吓坚,從而提高系統(tǒng)的并發(fā)性撵幽!?
(Java AIO(NIO.2))異步非阻塞IO:?
?? 在此種模式下灯荧,用戶進程只需要發(fā)起一個IO操作然后立即返回,等IO操作真正的完成以后盐杂,應(yīng)用程序會得到IO操作完成的通知逗载,此時用戶進程只需要對數(shù)據(jù)進行處理就好了,不需要進行實際的IO讀寫操作链烈,因為真正的IO讀取或者寫入操作已經(jīng)由內(nèi)核完成了厉斟。?
簡單介紹Netty
Netty是一個NIO客戶端、服務(wù)端框架强衡。允許快速簡單的開發(fā)網(wǎng)絡(luò)應(yīng)用程序擦秽。例如:服務(wù)端和客戶端之間的協(xié)議。它最牛逼的地方在于簡化了網(wǎng)絡(luò)編程規(guī)范。例如:TCP和UDP的Socket服務(wù)感挥。
Netty本身是用于快速構(gòu)建服務(wù)端與客戶端之間通信協(xié)議的框架缩搅。Netty在消息處理上使用責任鏈模式,用戶可以輕松方便的對它進行擴展触幼。官方也提供了大量的優(yōu)秀的擴展硼瓣。
Netty是一個NIO客戶端服務(wù)器框架,可以快速置谦,輕松地開發(fā)網(wǎng)絡(luò)應(yīng)用程序堂鲤,如協(xié)議服務(wù)器和客戶端。 它大大簡化和簡化了網(wǎng)絡(luò)編程媒峡,如TCP和UDP套接字服務(wù)器瘟栖。
Netty與WebSocket
WebSocket協(xié)議被設(shè)計來取代現(xiàn)有的使用HTTP作為傳輸層的雙向通信技術(shù),服務(wù)器根據(jù)http header識別是否一個websocket請求,如果是,則將請求升級為一個websocket連接,握手成功后就進入雙向長連接的數(shù)據(jù)傳輸階段谅阿。
Netty是基于Java NIO的非阻塞網(wǎng)絡(luò)框架慢宗,Netty是一個NIO client-server(客戶端服務(wù)器)框架,異步非阻塞是其主要的特性奔穿,使用Netty可以快速開發(fā)網(wǎng)絡(luò)應(yīng)用镜沽,例如服務(wù)器和客戶端協(xié)議。
Netty和Tomcat有什么區(qū)別贱田?
Netty和Tomcat最大的區(qū)別就在于通信協(xié)議缅茉,Tomcat是基于Http協(xié)議的,他的實質(zhì)是一個基于http協(xié)議的web容器男摧,但是Netty不一樣蔬墩,他能通過編程自定義各種協(xié)議,因為netty能夠通過codec自己來編碼/解碼字節(jié)流耗拓,完成類似redis訪問的功能拇颅,這就是netty和tomcat最大的不同。
有人說netty的性能就一定比tomcat性能高乔询,其實不然樟插,tomcat從6.x開始就支持了nio模式,并且后續(xù)還有arp模式——一種通過jni調(diào)用apache網(wǎng)絡(luò)庫的模式竿刁,相比于舊的bio模式黄锤,并發(fā)性能得到了很大提高,特別是arp模式食拜,而netty是否比tomcat性能更高鸵熟,則要取決于netty程序作者的技術(shù)實力了。
概念性的介紹到這里负甸,Netty的系統(tǒng)學習可以參考 Netty學習專題流强,在這里介紹springboot整合netty痹届。
下面看Netty的實現(xiàn)。本項目幫助你在spring-boot中使用Netty來開發(fā)聊天t服務(wù)器打月。
首先添加依賴:
可以看到這里只引入了一個第三方的netty的starter依賴短纵,并沒有引入web組件,是因為這里使用tcp協(xié)議僵控,只需要啟動一個netty服務(wù)即可香到,不需要啟動http服務(wù),使用springboot是為了在使用其它組件時报破,像普通的springboot項目一樣簡單悠就。
下面看一下netty服務(wù)端的代碼,springboot本身自帶的啟動類完全不用改充易,需要寫一個netty的啟動類:
然后是netty服務(wù)類梗脾,寫法與普通的netty基本一樣,只是運行方法需要修改返回類型:
這里略作修改是為了配合springboot一起啟動盹靴,下面就是netty處理的類:
這兩個類炸茧,與正常的netty寫法基本就一樣了。上面幾個類就是springboot整合netty實現(xiàn)的服務(wù)端所有的類稿静。注意梭冠,springboot整合netty不是因為netty使用簡單,而是為了在netty項目中操作其它中間件簡單改备,可以借助springboot的方便控漠,所以可以看到這里面的netty使用與其它項目中一樣。
下面看下客戶端的測試代碼:
啟動服務(wù)端盐捷,運行方法與運行普通springboot項目一樣:
這時候項目只啟動了一個tcp服務(wù),只占用了一個7000端口默勾,并沒有啟動http服務(wù)碉渡,如果有需要,可以再加上web組件母剥。下面啟動客戶端:
可以看到客戶端啟動后出現(xiàn)了聊天的提示滞诺,再看下服務(wù)端的控制臺:
出現(xiàn)了提示一個客戶端已經(jīng)連接的字樣,下面在客戶端控制臺發(fā)一條消息:
發(fā)出后收到了服務(wù)端的一個回復(fù)媳搪,服務(wù)端的控制臺在收到客戶端消息時也會有提示:
一個簡單的netty聊天就做好了铭段。
代碼地址:?https://gitee.com/blueses/spring-boot-demo