開始
感謝大家來參加我的分享。今天分享的主題是:高性能服務(wù)器入門小探。我會(huì)盡量抽象一點(diǎn),方便小白食用。
按照我參加的技術(shù)分享的常見套路,第一部分是「個(gè)人簡介」。這一部分我會(huì)盡量低調(diào)。
第二部分是「網(wǎng)絡(luò)基礎(chǔ)」,希望大家關(guān)注一下這部分的「分層」設(shè)計(jì)思想。
第三部分就是今天的主角了,講講「服務(wù)器編程模型演進(jìn)」。其實(shí)這部分可以簡單概括為 —— 說多了都是套路。
最后推薦一點(diǎn)資源,假裝一下自己讀了一些書。
友情提醒:部分演講內(nèi)容不得不使用英文,如果聽不懂,這很正常。
下面是個(gè)人簡介
我的英文名 - daydaygo。為什么起這個(gè)名字,大家可以和奶爸交流,奶爸總結(jié)了三點(diǎn)。我目前的座右銘是 Coder at Work 編程人生。有一本書也叫這個(gè)名字。大家有興趣可以看看,可以幫助解答一個(gè)問題:為什么身邊沒有超過 40 歲的程序員?他們都去哪了?下面還有三句話,代碼,是藝術(shù)的一部分。- farbox。本次分享使用的就是 farbox 的幻燈片服務(wù)。不過有些樣式的問題。第二句話是我仿的,編程,是人生的一部分。- by me。最后一句來自鳥哥的 blog,左右代碼,右手詩。- 鳥哥。php7 的作者。如果有看過「GitHub中國區(qū)前100名到底是什么樣的人?」這篇文章,就很容易找到他。
我的興趣愛好:跑步、騎行、LOLer
我給自己的標(biāo)簽是:持續(xù)創(chuàng)業(yè)者。之前做過爬蟲、P2P、游戲。目前看來:果然還是金融更有意思一點(diǎn)。目前在 「學(xué)堂在線」 上自學(xué)《經(jīng)濟(jì)學(xué)原理》。
我的技術(shù)方向:首先是知乎上的簽名 - 什么都關(guān)注一點(diǎn)的 web 開發(fā)。工作內(nèi)容大部分是服務(wù)器編程,平時(shí)也在折騰 docker、虛擬化技術(shù)、運(yùn)維相關(guān)。當(dāng)然,最想說的是:我們的征途是星辰大海
第二部分:網(wǎng)絡(luò)基礎(chǔ)
首先網(wǎng)絡(luò)協(xié)議棧架構(gòu),無論是OSI七層還是 tcp/ip 四層,都是分層設(shè)計(jì)的思想。以 tcp/ip 模型為例,可以簡單理解為:鏈路層和物理設(shè)備打交道,網(wǎng)絡(luò)層和 ip 打交道,傳輸層和數(shù)據(jù)傳輸打交道,應(yīng)用層就是各種應(yīng)用啦,比如瀏覽器打開網(wǎng)頁,就是 http。
這里有一張概覽圖,可以對(duì)照了看一下。好多英文縮寫完全看不懂怎么辦?不用管,我來劃重點(diǎn)。最下面是鏈路層,然后是網(wǎng)絡(luò)層,網(wǎng)絡(luò)層怎么不只有 ip?不用管,你能用到的基本都是ip。之后是傳輸層,這里怎么又來了UDP?其實(shí)就是兩種傳輸方式,區(qū)別在于網(wǎng)絡(luò)可能會(huì)出問題,但是 udp 只管發(fā)數(shù)據(jù),不管對(duì)方收到?jīng)]有,tcp 做了一些保護(hù)措施。大家可以參考「兩軍問題」,這也是為什么 tcp 連接建立要三次握手。我先給你發(fā)個(gè)消息,你回復(fù)剛才我發(fā)的消息以及你自己的消息,然后我把你發(fā)的消息再回復(fù)給你,這個(gè)流程之后,就可以認(rèn)為我們兩個(gè)之間的通信是可靠的。當(dāng)然,網(wǎng)絡(luò)還是說斷就能斷,那就是一些其他的技術(shù)了。所以,大部分都是 tcp 啦,大家可以想一想 UDP 這樣的「不可靠通信」,會(huì)在什么地方使用呢?比如監(jiān)控、直播。不知道大家有沒有看視頻突然視頻跳了一下經(jīng)歷呢?之后就是我們這群后端程序員經(jīng)常打交道的應(yīng)用層了。最后還有一點(diǎn),看到這條線沒有,有沒有感覺到很屌,居然可以不走傳輸層直接到應(yīng)用層。大家可以猜猜這是啥,后面也會(huì)提到。
MAC 地址,用來定義互聯(lián)網(wǎng)中設(shè)備的位置。
下面講講 IP 地址。首先是本機(jī)回環(huán) 127.0.0.1,我們家測試同學(xué)已經(jīng)很熟了,當(dāng)然它還有另一個(gè)更熟悉的名字 —— localhost。然后是局域網(wǎng)地址,我們俗稱的內(nèi)網(wǎng) ip,比如我們現(xiàn)在使用的虛擬機(jī) 192.168.100.153.剩下的就是外網(wǎng)地址了。本機(jī)回環(huán)只能本機(jī)訪問,內(nèi)網(wǎng)地址只能內(nèi)網(wǎng)訪問,外網(wǎng)地址才能給天南海北的用戶使用。除了這3類地址,還有一個(gè)bug級(jí)的存在,叫做 0.0.0.0. 這個(gè)東西是干嘛的呢?對(duì)了,來者不拒,無論是本機(jī)、內(nèi)網(wǎng)、還是外網(wǎng),都允許訪問。另外感興趣的同學(xué)可以去了解一下 網(wǎng)絡(luò)中的A類、B類、C類地址的劃分,這樣就可以區(qū)分內(nèi)網(wǎng)地址和外網(wǎng)地址了。
剛才提到 127.0.0.1 和 localhost 的時(shí)候,其實(shí)就已經(jīng)能說明「域名」的意義了。網(wǎng)絡(luò)層要通過 ip 來找到目標(biāo)設(shè)備,但是 ip 地址不好記呀,于是大家就想了一個(gè)辦法,這就是域名。這里執(zhí)行了一下 ping 命令,就可以看到域名實(shí)際對(duì)應(yīng)的 ip 了。DNS,域名系統(tǒng),就是專門處理域名和ip對(duì)應(yīng)關(guān)系的系統(tǒng)。另外經(jīng)常聽到大家說改 hosts 文件,其實(shí)作用是一樣的。留個(gè)問題給大家,如果我在 hosts 文件里面瞎寫了一個(gè) shoufuyou.com 的ip,我還能訪問到 shoufuyou.com 么?
再來說一下端口號(hào)??赡艽蠹也惶煜み@個(gè)。你通過 ip 找到主機(jī)地址了,但是怎么找到主機(jī)上面提供的服務(wù)了?于是就有了端口號(hào)。之所以大家不太熟悉這個(gè),是因?yàn)楹芏喽丝诮o常用服務(wù)預(yù)留了。ssh: 22 http: 80 https: 443
好了,最后一個(gè)概念了,兩個(gè)專業(yè)名詞,封裝和分用??梢援?dāng)做快遞來理解,先打包,你收到了之后再拆包裹。
RFC,所有以太網(wǎng)協(xié)議的正式標(biāo)準(zhǔn)。
好了,到今天的主角了,服務(wù)器編程模型演進(jìn)
下面基本上都是「老大和小弟還有顧客」的故事。
首先了解一下和服務(wù)器通信的流程:accept 接受用戶的請(qǐng)求(tcp 建立連接) -》recv 接受用戶傳遞的數(shù)據(jù) -》send 處理完后回復(fù)數(shù)據(jù)給用戶 -》close 處理完了,關(guān)閉
這里簡單看一下 php 的代碼實(shí)現(xiàn)。最開始是這樣的,老大建立了一個(gè)公司,公司在哪呢?就是這里的 ip 和端口。之后等顧客上門,顧客來了,他就招一個(gè)小弟來做事,顧客的事情處理完了,他打發(fā)走這個(gè)小弟。
聽到這里大家就能發(fā)現(xiàn)問題了:每次要重新招人,HR 表示這活我干不來了。
聯(lián)想一下現(xiàn)實(shí)中的公司,于是就能想到第二種解決方案:我先招好人先。就是這里,先招了 32 個(gè)小弟。
但是,這種方式也有問題。首先我們一開始只招了這么多小弟,那我們最多只能處理這么多的顧客。那是不是可以先招很多很多小弟?先不說老大樂意不樂意,從管理學(xué)的角度而言,好的管理者管理的直線匯報(bào)關(guān)系最好不要超過 7 個(gè)。同理,機(jī)器能管理的進(jìn)程數(shù)量也是有極限的。最后,還有經(jīng)典的 C10K 問題。大家可以猜一猜這個(gè)詞是什么意思?其實(shí) c + 10k,同時(shí)保持 1w 連接的問題。最常見的就是聊天室場景。拒 rango 的博客說,qq 早期也有這樣的問題,后來通過 udp 扛過去了。
好了,終于要到了我們今天真正的主角了。名詞先不管,先來看三個(gè)詞:select、poll、epoll。select: 可以在一個(gè)進(jìn)程內(nèi)維持1024個(gè)連接。poll: 可以維持任意數(shù)量的連接。但是他兩都有問題,需要循環(huán)檢測連接是否有事件。其實(shí)就是顧客來了,點(diǎn)菜或者挑衣服啥的,小弟要一個(gè)一個(gè)問才知道是哪個(gè)顧客點(diǎn)菜了。
是不是發(fā)現(xiàn)勝利就在眼前,只要解決顧客有需求的時(shí)候,能夠及時(shí)提供服務(wù)就行了,于是就有了 epoll。這里來簡單看看 epoll 是怎么處理的。Reactor 模型,大家知道這個(gè)單詞么?反應(yīng)堆的意思。其實(shí)就是老大發(fā)現(xiàn)我啥都做的不錯(cuò),但是管理就是不咋樣,于是找了一個(gè)管理團(tuán)隊(duì)。這個(gè)管理團(tuán)隊(duì)做的事情也簡單,add 它要管哪些人。set 這個(gè)人要處理哪些事。del 不管這個(gè)人了。callback,這個(gè)人遇到這些事要怎么處理。
好了,我們簡單看看 php 代碼實(shí)現(xiàn)。先建一個(gè)反應(yīng)堆,然后建公司,招小弟,小弟來處理用戶的需求。
有了這個(gè)之后,什么 C100K,C1M,C10M,C100M 都不是問題了。這里提一下 k 和 m。大家可能看到過一句話:這世界有 10 種人。2^10 = 1024 ~= 10^3
好了,最后一部分了,協(xié)程。當(dāng)程序員還沉浸在解決 C10K 問題帶來的成就感時(shí),一個(gè)新的問題被拋出了。異步嵌套回調(diào)太 TM 難寫了。我是不是應(yīng)該膜拜一下在座的 web 大前端。協(xié)程其實(shí)就像時(shí)間靜止的游戲一樣。國王對(duì)他的巫師說,來一車黃金。于是巫師就施展了一個(gè)時(shí)間靜止的法術(shù),等到一年后騎士把黃金運(yùn)來的時(shí)候在解開法術(shù)。
學(xué)習(xí)資源推薦
實(shí)驗(yàn)樓,前面有圖片就是來自這里,很多小白課程,xx基礎(chǔ),xx入門之類的。
Rango 的博客:本篇的主角主要參考了 rango 的博客來潤色
下面就是專業(yè)書籍啦。
《Unix環(huán)境高級(jí)編程》
《TCP/IP網(wǎng)絡(luò)通信詳解》
《高性能 linux 服務(wù)器編程》