簡(jiǎn)單系統(tǒng)的介紹一下Netty。
在網(wǎng)絡(luò)編程體系設(shè)計(jì)中,有幾個(gè)名詞概念簡(jiǎn)單解釋一下:
1 什么是同步??
2 什么是異步??
3 什么是阻塞??
4 什么是非阻塞??
5 什么是同步阻塞??
6 什么是同步非阻塞??
7 什么是異步阻塞??
8 什么是異步非阻塞?
1,同步和異步是針對(duì)應(yīng)用程序和內(nèi)核的交互而言的。?
2,阻塞和非阻塞是針對(duì)于進(jìn)程在訪問數(shù)據(jù)的時(shí)候,根據(jù)IO操作的就緒狀態(tài)來(lái)采取的不同方式,說(shuō)白了是一種讀取或者寫入操作函數(shù)的實(shí)現(xiàn)方式,阻塞方式下讀取或者寫入函數(shù)將一直等待,而非阻塞方式下,讀取或者寫入函數(shù)會(huì)立即返回一個(gè)狀態(tài)值。?
由上描述基本可以總結(jié)一句簡(jiǎn)短的話,同步和異步是目的,阻塞和非阻塞是實(shí)現(xiàn)方式。
1 同步 指的是用戶進(jìn)程觸發(fā)IO操作并等待或者輪詢的去查看IO操作是否就緒 自己上街買衣服,自己親自干這件事,別的事干不了。
2 異步 異步是指用戶進(jìn)程觸發(fā)IO操作以后便開始做自己的事情,而當(dāng)IO操作已經(jīng)完成的時(shí)候會(huì)得到IO完成的通知(異步的特點(diǎn)就是通知) 告訴朋友自己合適衣服的尺寸,大小,顏色,讓朋友委托去賣,然后自己可以去干別的事。(使用異步IO時(shí),Java將IO讀寫委托給OS處理,需要將數(shù)據(jù)緩沖區(qū)地址和大小傳給OS)?
3 阻塞 所謂阻塞方式的意思是指, 當(dāng)試圖對(duì)該文件描述符進(jìn)行讀寫時(shí), 如果當(dāng)時(shí)沒有東西可讀,或者暫時(shí)不可寫, 程序就進(jìn)入等待 狀態(tài), 直到有東西可讀或者可寫為止 去公交站充值,發(fā)現(xiàn)這個(gè)時(shí)候,充值員不在(可能上廁所去了),然后我們就在這里等待,一直等到充值員回來(lái)為止。(當(dāng)然現(xiàn)實(shí)社會(huì),可不是這樣,但是在計(jì)算機(jī)里確實(shí)如此。)?
4 非阻塞 非阻塞狀態(tài)下, 如果沒有東西可讀, 或者不可寫, 讀寫函數(shù)馬上返回, 而不會(huì)等待, 銀行里取款辦業(yè)務(wù)時(shí),領(lǐng)取一張小票,領(lǐng)取完后我們自己可以玩玩手機(jī),或者與別人聊聊天,當(dāng)輪我們時(shí),銀行的喇叭會(huì)通知,這時(shí)候我們就可以去了。?
再來(lái)理解組合方式的IO類型
同步阻塞IO(JAVA BIO):?
同步并阻塞,服務(wù)器實(shí)現(xiàn)模式為一個(gè)連接一個(gè)線程,即客戶端有連接請(qǐng)求時(shí)服務(wù)器端就需要啟動(dòng)一個(gè)線程進(jìn)行處理,如果這個(gè)連接不做任何事情會(huì)造成不必要的線程開銷,當(dāng)然可以通過(guò)線程池機(jī)制改善。?
同步非阻塞IO(Java NIO) : 同步非阻塞,服務(wù)器實(shí)現(xiàn)模式為一個(gè)請(qǐng)求一個(gè)線程,即客戶端發(fā)送的連接請(qǐng)求都會(huì)注冊(cè)到多路復(fù)用器上,多路復(fù)用器輪詢到連接有I/O請(qǐng)求時(shí)才啟動(dòng)一個(gè)線程進(jìn)行處理。用戶進(jìn)程也需要時(shí)不時(shí)的詢問IO操作是否就緒,這就要求用戶進(jìn)程不停的去詢問。?
異步阻塞IO(Java NIO):?
此種方式下是指應(yīng)用發(fā)起一個(gè)IO操作以后,不等待內(nèi)核IO操作的完成,等內(nèi)核完成IO操作以后會(huì)通知應(yīng)用程序,這其實(shí)就是同步和異步最關(guān)鍵的區(qū)別,同步必須等待或者主動(dòng)的去詢問IO是否完成,那么為什么說(shuō)是阻塞的呢?因?yàn)榇藭r(shí)是通過(guò)select系統(tǒng)調(diào)用來(lái)完成的,而select函數(shù)本身的實(shí)現(xiàn)方式是阻塞的,而采用select函數(shù)有個(gè)好處就是它可以同時(shí)監(jiān)聽多個(gè)文件句柄(如果從UNP的角度看,select屬于同步操作。因?yàn)閟elect之后,進(jìn)程還需要讀寫數(shù)據(jù)),從而提高系統(tǒng)的并發(fā)性!?
(Java AIO(NIO.2))異步非阻塞IO:?
?? 在此種模式下,用戶進(jìn)程只需要發(fā)起一個(gè)IO操作然后立即返回,等IO操作真正的完成以后,應(yīng)用程序會(huì)得到IO操作完成的通知,此時(shí)用戶進(jìn)程只需要對(duì)數(shù)據(jù)進(jìn)行處理就好了,不需要進(jìn)行實(shí)際的IO讀寫操作,因?yàn)檎嬲腎O讀取或者寫入操作已經(jīng)由內(nèi)核完成了。?
簡(jiǎn)單介紹Netty
Netty是一個(gè)NIO客戶端、服務(wù)端框架。允許快速簡(jiǎn)單的開發(fā)網(wǎng)絡(luò)應(yīng)用程序。例如:服務(wù)端和客戶端之間的協(xié)議。它最牛逼的地方在于簡(jiǎn)化了網(wǎng)絡(luò)編程規(guī)范。例如:TCP和UDP的Socket服務(wù)。
Netty本身是用于快速構(gòu)建服務(wù)端與客戶端之間通信協(xié)議的框架。Netty在消息處理上使用責(zé)任鏈模式,用戶可以輕松方便的對(duì)它進(jìn)行擴(kuò)展。官方也提供了大量的優(yōu)秀的擴(kuò)展。
Netty是一個(gè)NIO客戶端服務(wù)器框架,可以快速,輕松地開發(fā)網(wǎng)絡(luò)應(yīng)用程序,如協(xié)議服務(wù)器和客戶端。 它大大簡(jiǎn)化和簡(jiǎn)化了網(wǎng)絡(luò)編程,如TCP和UDP套接字服務(wù)器。
Netty與WebSocket
WebSocket協(xié)議被設(shè)計(jì)來(lái)取代現(xiàn)有的使用HTTP作為傳輸層的雙向通信技術(shù),服務(wù)器根據(jù)http header識(shí)別是否一個(gè)websocket請(qǐng)求,如果是,則將請(qǐng)求升級(jí)為一個(gè)websocket連接,握手成功后就進(jìn)入雙向長(zhǎng)連接的數(shù)據(jù)傳輸階段。
Netty是基于Java NIO的非阻塞網(wǎng)絡(luò)框架,Netty是一個(gè)NIO client-server(客戶端服務(wù)器)框架,異步非阻塞是其主要的特性,使用Netty可以快速開發(fā)網(wǎng)絡(luò)應(yīng)用,例如服務(wù)器和客戶端協(xié)議。
Netty和Tomcat有什么區(qū)別?
Netty和Tomcat最大的區(qū)別就在于通信協(xié)議,Tomcat是基于Http協(xié)議的,他的實(shí)質(zhì)是一個(gè)基于http協(xié)議的web容器,但是Netty不一樣,他能通過(guò)編程自定義各種協(xié)議,因?yàn)閚etty能夠通過(guò)codec自己來(lái)編碼/解碼字節(jié)流,完成類似redis訪問的功能,這就是netty和tomcat最大的不同。
有人說(shuō)netty的性能就一定比tomcat性能高,其實(shí)不然,tomcat從6.x開始就支持了nio模式,并且后續(xù)還有arp模式——一種通過(guò)jni調(diào)用apache網(wǎng)絡(luò)庫(kù)的模式,相比于舊的bio模式,并發(fā)性能得到了很大提高,特別是arp模式,而netty是否比tomcat性能更高,則要取決于netty程序作者的技術(shù)實(shí)力了。
概念性的介紹到這里,Netty的系統(tǒng)學(xué)習(xí)可以參考 Netty學(xué)習(xí)專題,在這里介紹springboot整合netty。
下面看Netty的實(shí)現(xiàn)。本項(xiàng)目幫助你在spring-boot中使用Netty來(lái)開發(fā)聊天t服務(wù)器。
首先添加依賴:

可以看到這里只引入了一個(gè)第三方的netty的starter依賴,并沒有引入web組件,是因?yàn)檫@里使用tcp協(xié)議,只需要啟動(dòng)一個(gè)netty服務(wù)即可,不需要啟動(dòng)http服務(wù),使用springboot是為了在使用其它組件時(shí),像普通的springboot項(xiàng)目一樣簡(jiǎn)單。
下面看一下netty服務(wù)端的代碼,springboot本身自帶的啟動(dòng)類完全不用改,需要寫一個(gè)netty的啟動(dòng)類:

然后是netty服務(wù)類,寫法與普通的netty基本一樣,只是運(yùn)行方法需要修改返回類型:

這里略作修改是為了配合springboot一起啟動(dòng),下面就是netty處理的類:


這兩個(gè)類,與正常的netty寫法基本就一樣了。上面幾個(gè)類就是springboot整合netty實(shí)現(xiàn)的服務(wù)端所有的類。注意,springboot整合netty不是因?yàn)閚etty使用簡(jiǎn)單,而是為了在netty項(xiàng)目中操作其它中間件簡(jiǎn)單,可以借助springboot的方便,所以可以看到這里面的netty使用與其它項(xiàng)目中一樣。
下面看下客戶端的測(cè)試代碼:



啟動(dòng)服務(wù)端,運(yùn)行方法與運(yùn)行普通springboot項(xiàng)目一樣:

這時(shí)候項(xiàng)目只啟動(dòng)了一個(gè)tcp服務(wù),只占用了一個(gè)7000端口,并沒有啟動(dòng)http服務(wù),如果有需要,可以再加上web組件。下面啟動(dòng)客戶端:

可以看到客戶端啟動(dòng)后出現(xiàn)了聊天的提示,再看下服務(wù)端的控制臺(tái):

出現(xiàn)了提示一個(gè)客戶端已經(jīng)連接的字樣,下面在客戶端控制臺(tái)發(fā)一條消息:

發(fā)出后收到了服務(wù)端的一個(gè)回復(fù),服務(wù)端的控制臺(tái)在收到客戶端消息時(shí)也會(huì)有提示:

一個(gè)簡(jiǎn)單的netty聊天就做好了。
代碼地址:?https://gitee.com/blueses/spring-boot-demo