原創聲明 本文作者:黃小斜 轉載請務必在文章開頭註明出處和作者。 本文思維導圖 簡介 Java作為一門後端語言,對於網路編程的支持是必不可少的,但是,作為一個經常CRUD的Java工程師,很多時候都不需要接觸到網路編程,自然而然地對這個東西不那麼重視了,畢竟,即使像是JVM虛擬機,Java多線程,在 ...
原創聲明
本文作者:黃小斜
轉載請務必在文章開頭註明出處和作者。
本文思維導圖
簡介
Java作為一門後端語言,對於網路編程的支持是必不可少的,但是,作為一個經常CRUD的Java工程師,很多時候都不需要接觸到網路編程,自然而然地對這個東西不那麼重視了,畢竟,即使像是JVM虛擬機,Java多線程,在平時工作的時候還會用到一些,但是對於網路編程,除非你做的東西確實是需要自己寫通訊服務代碼的,比如網路游戲,以及偏向中間件方向的開發, 可能會接觸到一些網路編程的實踐,要不然在平時的開發工作中確實不多見。
讓我們看下網路編程在百度百科上的定義:網路編程最主要的工作就是在發送端把信息通過規定好的協議進行組裝包,在接收端按照規定好的協議把包進行解析,從而提取出對應的信息,達到通信的目的。
那麼,為什麼網路編程重要呢,簡單來說,電腦之間之所以能夠通信,靠的就是網路編程,只不過平時這些代碼不需要我們自己來寫罷了,TCP/IP的協議代碼已經封裝在了Linux內核中 ,而Tomcat里的代碼則負責處理一個個網路請求,返回請求方需要的數據。再比如像netty這樣的網路編程框架,也會把複雜的NIO處理邏輯封裝成簡單的API,即使如此,需要使用netty來做服務端開發的工程師仍然不多。
Java網路編程對於Java工程師來說是很重要的能力,這也是我在接觸了一系列相關面試題,以及Tomcat和netty實現之後才逐漸意識到的,想要瞭解這兩個東西的實現原理,就必須要會網路編程的知識,當然了,這一切的基礎就是你要首先懂得電腦網路,這部分內容也可以參考我關於電腦網路的一篇文章。
本文思維導圖
Java網路編程該怎麼學
電腦網路和Java網路編程的關係
電腦網路之於Java網路編程,好比數據結構之於演算法,前者是後者的基礎,沒有前者的支撐,直接學習後者,是沒有意義的。
之前我也寫了一篇關於電腦網路該怎麼學的文章,可以先看看。總體來看,電腦網路告訴我們的是,兩台電腦想要進行通信,它們需要約定一種傳輸協議和編碼解碼的標準,因此電腦網路通常分為5層,而其中一些標準就包括TCP和IP,HTTP等等,這些協議都是為了更好地實現網路數據傳輸而產生的。
但是,這些協議只是協議而已,要真正在Java代碼里實現網路傳輸,就需要讓代碼實現協議,當然了,像TCP/IP這樣通用的協議棧。還輪不到Java應用程式自己來實現,否則也太麻煩了,Linux的內核里已經對其進行了封裝,並且會向上提供API,所以Java應用程式只需要調用Linux內核提供的即可。
而再往上,也就是HTTP這類應用層協議,Java代碼是可以直接進行解析或者組裝的,畢竟HTTP的報文比較簡單,我們可以直接通過Java提供的API進行操作,大家也都知道,Java里有一些網路編程的包,提供了一些常用於網路通訊的類,比如Socket可以用來建立網路連接,IO流則可以用來處理網路傳輸的IO輸入和輸出。
換言之,網路編程的實質就是先進行網路連接,然後進行IO傳輸,而網路IO這個東西里又大有門道,這部分內容我們在下一節里繼續分享。
網路編程里BIO、NIO和AIO
說到這三個東西,相比學過Java的朋友都不會陌生,畢竟面試題也經常考,背也都背下來了。
但是這幾個東西為什麼會有這樣的區別呢,不妨一起來探究一下。
BIO是最原始的Java IO模式,也叫阻塞式IO,多個BIO處理必須要串列執行,因為IO此時被阻塞了。
而NIO則是相對較新的一種模式,它基於Linux的epoll來進行實現,通過一個線程對多個連接進行處理,當發現有活躍的連接時進行對應的IO處理,本質上是IO多路復用的一種實現。
而AIO和上面兩者不太一樣,它強調的不是阻塞非阻塞,而是對IO的處理是非同步化的,通常來說就是建立連接,然後提供一個處理完IO的回調介面,然後就可以扔在一邊不管了,等待IO處理結束後回調相應的介面。值得一提的是,AIO需要底層操作系統的支持。
通信框架netty
瞭解了BIO、NIO和AIO之後,你對於網路編程中的幾個核心概念你應該已經有所瞭解了,接下來就不得不看看Java網路編程中最牛掰的一個框架:netty了。比起NIO和BIO,瞭解netty的人應該更少了,其實,netty就是基於NIO實現的非同步網路編程框架,既有了NIO的高性能IO處理方式,又通過非同步化編程使得netty的編程方式更加簡單高效。
我當時接觸netty的時候,還是在學習RPC和分散式服務的時候,我發現每當有RPC出現的地方,也總有網路編程框架的身影,好比netty這樣的通訊框架常常會被提到,我當時並不太理解通訊框架是幹嘛用的,以至於我對RPC是什麼東西都不太理解。
當我現在搞懂了RPC之後,再去研究網路編程框架就有了新的感覺,其實,不管是RPC還是HTTP,都需要通信框架的支持,只不過支持HTTP的伺服器已經有很多了,比如Tomcat,比如Nginx,這些伺服器完全可以cover掉網路框架,後面我們也會再來聊一下Tomcat這個神奇的伺服器。
Tomcat這個神奇的伺服器
Tomcat這個伺服器我們Java工程師一直在用,但是很多朋友對它其實知之甚少,只知道它可以運行JavaWeb應用。
其實Tomcat這個伺服器,也是基於NIO實現的一個伺服器,不妨把Tomcat分為兩個部分來看,一部分是connector,負責網路連接,接受請求和處理請求,另一部分是container,也就是容器,Tomcat本質上是一個servlet容器,這一部分負責的就是編排一系列容器里的處理器、調用鏈以及層級結構,比如engine的下一層是host,host的下一層是context。
當一個網路請求到達Tomcat時,connector先負責處理這個請求,再扔到container跑一遍拿到結果,但在生產環境中,connector一次性要處理的請求就多的去了,因此就必須要支持高併發以及IO多路復用,因此Tomcat也採用了NIO的IO處理方式,同時通過多線程進行請求處理,總體來說已經達到了非常不錯的性能了。
面向面試複習
一個小小的Java網路編程,居然一下子牽扯出這麼多複雜的知識點出來,先是電腦網路,再到Java網路編程API,再到BIO、NIO和AIO,然後又談到了Tomcat和netty。
其實,網路編程的內容可能還不止這些,比如NIO的底層實現是基於Linux的epoll來完成了,而Linux的網路IO模型有select、poll和epoll等方式,要真正搞懂NIO,你還需要搞懂epoll。
其實一開始我對於Java網路編程也沒有什麼概念,只不過在看了很多面試題之後,才逐漸發現問題所在,比如BIO和NIO的區別,背了好幾次面試答案仍然不解其意,要是再問到epoll、poll和select的區別,更是完全不得要領,究其原因還是不知道這些東西到底是什麼,有什麼用,以及它們和一些實際場景間的關係。
因此,我覺得,網路編程方向的面試題重在理解概念,對於電腦網路、IO模型,以及網路編程框架要能夠真正理解了這些東西之後,你才能夠對面試題游刃有餘,否則,這類面試題再怎麼背都不會有什麼效果,正如電腦網路這種純理論的課程一樣,在不理解的情況下,分析問題和回答問題肯定是難以達到面試官要求的。
所以,請按照這樣的一個順序進行複習和實踐,相信這對於你學習網路編程會有所幫助。
1、電腦網路知識
2、Java網路編程基礎
3、NIO、BIO、AIO
4、Linux的網路IO模型:epoll、select和poll
5、netty網路編程框架
6、Tomcat伺服器
推薦資源
這方面能推薦的資源就非常多了,我儘量按照先易後難的順序為大家推薦資源
書籍
《Java網路編程》
《netty權威指南》
《How Tomcat Work》
《Tomcat架構解析》
視頻
我整理一些Java網路編程複習的視頻資源,習慣看視頻的朋友可以瞭解一下。
博客
Java技術倉庫《Java程式員複習指南》
https://github.com/h2pl/Java-Tutorial
整合全網優質Java學習內容,幫助你從基礎到進階系統化複習Java。
總結
關於如何學習Java網路編程,並且搞定相關面試題,我們今天就講到這裡了,如果還有什麼疑問也可以到我公眾號里找我探討,後續會有更多的文章推出,包括如何系統性地學習JavaWeb,以及如何系統性地學習後端技術。敬請期待。
對了,你想問我文章里提到的資源去哪找?我已經給你準備好了
文中提到的資源都可以免費領取,在我的公眾號【程式員黃小斜】回覆“Java網路編程“即可免費領取對應的資源。
寫在最後
如果覺得本文對你有幫助的話,請你也不要吝嗇你的“好看”哈,轉發朋友圈就是對我最大的支持啦,你們的支持是對我最大的鼓勵。
對本系列文章有什麼建議和意見,也歡迎留言告訴我,期待你的回饋。
微信公眾號:程式員黃小斜
知乎:黃小斜
B站:黃小斜