做爲一部被重播數千次的電視劇,86版《西遊記》毫無疑問是一部經典中的經典!對於絕大多數人來講都是童年最深的記憶。算法
本文做者以西遊記爲背景,爲你們講述一個有關計算機網絡協議的故事。數據庫
我佛造經傳極樂編程
話說我佛如來爲度化天下蒼生,有三藏真經,可勸人爲善。json
就如圖中所示,真經所藏之處,在於雲端。佛祖所管轄之下,有四個區域 Region,稱爲四大部洲,一是東勝神洲,二是南贍部洲,三是西牛賀洲,四是北俱盧洲。後端
我佛所在西牛賀洲,是主站點。瀏覽器
在每一個區域 Region,爲保證真經永固,設置多個藏經樓,稱爲可用區(Available Zone)。緩存
每一個藏經樓裏面是一排一排的櫃子,稱爲機櫃,裏面有一排一排的格子,稱爲服務器,經文就擺放在格子中。安全
在藏經樓中,櫃子根據經文分門別類的組織起來,由不一樣的神仙進行管理,管理一個櫃子的經文的神仙,訪問這裏面經文的鑰匙就在他手裏,稱爲接入層神仙(接入層交換機)。服務器
多個接入層神仙被一組匯聚層神仙(匯聚層交換機)管着,多個匯聚層的神仙被一組核心層神仙(核心交換機)管着。網絡
神仙體系組織嚴格,井井有條,不一樣的接入層神仙交換經文,要經過匯聚層神仙贊成,不一樣的匯聚層神仙交換經文,須要核心層神仙贊成。
經文的看守要萬無一失,於是每一層都是分組看護,互相監督,互相備份,稱爲堆疊。
雖然說每一個櫃子裏面放滿了經文,爲了防止經文被偷聽偷看,經文的內容是被仙術封裝在一個虛擬的私密空間裏面。
雖然有人可能會偷到物質的經文,可是沒有仙術打開這個私密空間,看到的經文如同空白的同樣。這個虛擬的私密空間稱爲 VPC。
要解讀經文,須要使用每一格中一個不起眼的法寶,就是稱爲 Openvswitch 的虛擬交換機,顧名思義就是起到經文在虛擬私密空間和物理空間之間的轉換做用。
Openvswitch 如何轉換呢?使用的是一種稱爲 VXLAN 的封裝技術,可是必需要事先知道芝麻開門的 ID,也即 VXLAN ID,才能看到經文的真正內容。
在虛擬的空間中,放着真正能夠解讀的真經。
真經有法一藏,談天;論一藏,說地;經一藏,度鬼;三藏共計三十五部,該一萬五千一百四十四卷,乃是修真之徑,正善之門。
看來已經前中後臺分離,分爲基礎服務層,組合服務層,Controller 層,共三十五個模塊,一萬五千多個服務,真是微服務架構啊。
如何可以不要迷失在這個一萬五千卷經文中,也是頗有挑戰的事情,須要一個索引和指南,這就是常說的 RPC 框架和服務註冊與發現中心。
爲了方便諸多僧侶前來取經,靈山腳下會有一個統一的入口地址,這裏有一個神仙,稱爲金頂大仙,專門來接應取經人的。
因爲前來取經的人不少,同時經文也不少,因此金頂大仙多起到負載均衡的做用,將不一樣的取經人引領到不一樣的藏經樓,訪問不一樣的經文。
金頂大仙所在的靈山腳下,是一個世界知名的地址,稱爲外網 IP 地址,這個地址是全球可定位的,全部的取經人都先到這個地方。
金頂大仙經過 NAT 規則,將外網 IP 地址,變成藏經樓的私有 IP 地址,例如 2 號藏經樓三樓,4 號藏經樓五樓等。
在靈山藏經樓裏面,是經過私有 IP 地址定位的。真經已經準備好,就差東土取經人了。
觀音奉旨上長安
但是佛祖愁啊,是這樣說的:我待要送上東土,叵耐那方衆生愚蠢,毀謗真言,不識我法門之要旨,怠慢了瑜迦之正宗。
怎麼得一個有法力的,去東土尋一個善信,教他苦歷千山,遠經萬水,到我處求取真經,永傳東土,勸他衆生,卻乃是個山大的福緣,海深的善慶、誰肯去走一遭來?
真經就在靈山,但是東土之人愚鈍,不知道靈山咋辦呢?要一個法力無邊的人告訴他們呀。並且最好可以告訴全世界,靈山這裏有真經。
好在有觀音菩薩,道:「弟子不才,願上東土尋一個取經人來也。」,觀音菩薩有什麼法力呢?固然是 BGP 協議了。
剛纔那張圖畫的是一個可用區的狀況,對於多個可用區的狀況,咱們能夠隱去計算節點的狀況,將外網訪問區域放大。
外網 IP 是放在虛擬網關的外網網口上的,這個 IP 如何讓全世界知道呢?在覈心交換外面是安全設備,而後就是邊界路由器。
邊界路由器會和多個運營商鏈接,從而每一個運營商都可以訪問到這個網站。邊界路由器能夠經過 BGP 協議,將本身數據中內心面的外網 IP 向外廣播,也就是告訴全世界,若是要訪問這些外網 IP,都來我這裏。
每一個運營商也有不少的路由器、不少的點,因而就能夠將如何到達這些 IP 地址的路由信息,廣播到全國乃至全世界。
厲害吧,這是我佛如來告訴觀音菩薩的:「這一去。要踏看路道,不準在霄漢中行,須是要半雲半霧;目過山水,謹記程途遠近之數,叮嚀那取經人。「
就是說你去東土的路上,通過了哪些道路,要記住路徑,要記住遠近,才能告訴取經人這一路應該怎麼走。
玄奘秉誠建大會
當觀音菩薩來到東土大唐,正看到玄奘法師坐在高臺上,帶領衆人誦經,念一會《受生度亡經》,談一會《安邦天寶篆》,又宣一會《勸修功卷》。
菩薩近前來,叫道:「那和尚,你只會談小乘教法,可會談大乘麼?」玄奘聞言,心中大喜,翻身跳下臺來,對菩薩起手道:「老師父,弟子失瞻,多罪。見前的蓋衆僧人,都講的是小乘教法,殊不知大乘教法如何。」
菩薩道:「你這小乘教法,度不得亡者超升,只可渾俗和光而已。我有大乘佛法三藏,能超亡者昇天,能度難人脫苦,能修無量壽身,能做無來無去。」
你看,在西方極樂淨土,我佛已經有了更牛的佛經,遙遠的東方,還在讀本土的僧人早期從西方傳過來的經。
這種模式,稱爲 CDN。
咱們部署應用的時候,通常會把靜態資源保存在兩個地方,一個是 Nginx 後面的 varnish 緩存裏面,通常是靜態頁面。
對於比較大的、不常常更新的靜態圖片,會保存在對象存儲裏面。這兩個地方的靜態資源都會配置 CDN,將資源下發到邊緣節點。
最初佛祖傳經,都是口口相傳,經文都會記在高僧大德的內心,隨着高僧雲遊天下,隨着廟宇遍及天下,佛經從而遍及天下。這就至關於將佛經緩存在邊緣節點。
配置了 CDN 以後,權威 DNS 服務器上,會爲靜態資源設置一個 CNAME 別名,指向另一個域名 cdn.com,返回給本地 DNS 服務器。
當本地 DNS 服務器拿到這個新的域名時,須要繼續解析這個新的域名。這個時候,再訪問的時候就不是原來的權威 DNS 服務器了,而是 cdn.com 的權威 DNS 服務器。這是 CDN 本身的權威 DNS 服務器。
在這個服務器上,仍是會設置一個 CNAME,指向另一個域名,也即 CDN 網絡的全局負載均衡器。
本地 DNS 服務器去請求 CDN 的全局負載均衡器解析域名,全局負載均衡器會爲用戶選擇一臺合適的緩存服務器提供服務,將 IP 返回給客戶端,客戶端去訪問這個邊緣節點,下載資源。緩存服務器響應用戶請求,將用戶所需內容傳送到用戶終端。
若是這臺緩存服務器上並無用戶想要的內容,那麼這臺服務器就要向它的上一級緩存服務器請求內容,直至追溯到網站的源服務器,將內容拉到本地。
CDN 的全局負載均衡策略,就至關於當僧人們想讀佛經的時候,沒必要要都去西天,而是能夠就近去問,周圍有沒有廟宇,而後向廟宇的師傅去請教佛經。
然而緩存的佛經固然是比不上西天取到的經文更新,因此東土因爲離西天較遠,緩存的仍是小乘佛教,要讀大乘佛教,就要去西天取經,稱爲回源。
觀音顯像化金蟬
觀音菩薩打算度化玄奘法師,回源去西天取經。
但是怎麼去呢,地址在哪裏呢?玄奘法師只據說西天,不知道具體的地址,這就要問觀音菩薩了。
這個時候,你們才知道,西天在靈山大雷音寺,距此十萬八千里。這個過程稱爲 DNS 解析。
當在手機上面打開一個 App 的時候,首先要作的事情就是解析這個網站的域名。
在手機運營商所在的互聯網區域裏,有一個本地的 DNS,手機會向這個 DNS 請求解析 DNS。當這個 DNS 本地有緩存,則直接返回。
若是沒有緩存,本地 DNS 才須要遞歸地從根 DNS 服務器,查到 .com 的頂級域名服務器,最終查到權威 DNS 服務器。
若是你使用雲平臺的時候,配置了智能 DNS 和全局負載均衡,在權威 DNS 服務中,通常是經過配置 CNAME 的方式,咱們能夠起一個別名,例如 vip.yourcomany.com。
而後告訴本地 DNS 服務器,讓它請求 GSLB 解析這個域名,GSLB 就能夠在解析這個域名的過程當中,經過本身的策略實現負載均衡。
GSLB 經過查看請求它的本地 DNS 服務器所在的運營商和地址,就知道用戶所在的運營商和地址,而後在距離用戶位置比較近的 Region 裏面,將三個本地負載均衡的公網 IP 地址,返回給本地 DNS 服務器。
本地 DNS 解析器將結果緩存後,返回給客戶端。對於手機 App 來講,能夠繞過剛纔的傳統 DNS 解析機制,直接只要 HTTP DNS 服務,經過直接調用 HTTP DNS 服務器,獲得這三個本地負載均衡的公網 IP 地址。
這個公網 IP 地址,就是金頂大仙所在的位置。其實這個時候,金頂大仙已經在等待了。
這個時候,李世民忽然開始說話了,曰:「誰肯領朕旨意,上西天拜佛求經?「 並願意買下觀音手中的兩件寶物,「錦瀾袈裟」一領,「九環錫杖」一根,佛祖說過:」如有取經人堅心來此,穿個人袈裟,免墮輪迴;持個人錫枚,不遭毒害。「
玄奘法師回答:「貧僧不才,願效犬馬之勞,與陛下求取真經,祈保我王江山永固。」
這個時候,菩薩說了:「西天路遠,更多虎豹妖魔。只怕有去無回,難保身命。」
玄奘道:「我已發了弘誓大願,不取真經,永墮沉淪地獄。「
其實這裏的對話是頗有意思的,玄奘法師回覆李世民的和回覆觀音菩薩的不一樣。
這個時候,李世民做爲世俗的君王,已經想求取真經了,也就是東土大唐做爲客戶端,要發起對於服務端的請求了。可是玄奘法師知道,唐王李世民去取經,求的是江山永固。
因此李世民的請求是應用層的,發起的是 HTTP 的協議,在 HTTP 的請求正文中,怕是寫的「江山永固」四個字。
而玄奘法師回覆觀音菩薩的時候,說的就不一樣了,是一種對於真經和佛法自己的堅持。
因此玄奘法師是 TCP 層的,TCP 是面向鏈接的,TCP 是靠譜的協議,可是這不能說明它面臨的網絡環境好。
從 IP 層面來說,若是網絡情況的確那麼差,是沒有任何可靠性保證的,而做爲 IP 的上一層 TCP 也無能爲力,惟一能作的就是更加努力,不斷重傳,經過各類算法保證。
也就是說,對於 TCP 來說,IP 層你丟不丟包,我管不着,可是我在個人層面上,會努力保證可靠性。
這一點在流沙河有了驗證。觀音菩薩度化沙悟淨的時候,沙悟淨說:「菩薩,我在此間吃人無數,向來有幾回取經人來,都被我吃了。凡吃的人頭,拋落流沙,竟沉水底(這個水,鵝毛也不能浮),唯有九個取經人的骷髏,浮在水面,再不能沉。我覺得異物,將索兒穿在一處,閒時拿來頑耍,這去,但恐取經人不獲得此,卻不是反誤了個人前程也?」
菩薩日:「豈有不到之理?你可將骷髏地掛在頭頂下,等候取經入,自有用處。」
因此沙悟淨脖子上這九個骷髏,是唐三藏的前九輩子,一旦吃了,就不斷的重試。
爲了可以實現重試,實現 TCP 的可靠性,客戶端和服務器須要創建鏈接。
HTTPS 協議是基於 TCP 協議的,於是要先創建 TCP 的鏈接。在這個例子中,TCP 的鏈接是從手機上的 App 和負載均衡器 SLB 之間的。也就是唐僧和金頂大仙之間,到了金頂大仙,就不怕了,會指引到佛祖那裏的。
儘管中間要通過不少的路由器和交換機,可是 TCP 的鏈接是端到端的。
TCP 這一層和更上層的 HTTPS 沒法看到中間的包的過程。儘管創建鏈接的時候,全部的包都逃不過在這些路由器和交換機之間的轉發,轉發的細節咱們放到那個下單請求的發送過程當中詳細解讀,這裏只看端到端的行爲。
對於 TCP 鏈接來說,須要經過三次握手創建鏈接,爲了維護這個鏈接,雙方都須要在 TCP 層維護一個鏈接的狀態機。
一開始,客戶端和服務端都處於 CLOSED 狀態。服務端先是主動監聽某個端口,處於 LISTEN 狀態。
而後客戶端主動發起鏈接 SYN,以後處於 SYN-SENT 狀態。服務端收到發起的鏈接,返回 SYN,而且 ACK 客戶端的 SYN,以後處於 SYN-RCVD 狀態。
客戶端收到服務端發送的 SYN 和 ACK 以後,發送 ACK 的 ACK,以後處於 ESTABLISHED 狀態。
這是由於,它一發一收成功了。服務端收到 ACK 的 ACK 以後,處於 ESTABLISHED 狀態,由於它的一發一收也成功了。
當 TCP 層的鏈接創建完畢以後,接下來輪到 HTTPS 層創建鏈接了,在 HTTPS 的交換過程當中,TCP 層始終處於 ESTABLISHED。
對於 HTTPS,客戶端會發送 Client Hello 消息到服務器,用明文傳輸 TLS 版本信息、加密套件候選列表、壓縮算法候選列表等信息。另外,還會有一個隨機數,在協商對稱密鑰的時候使用。
而後,服務器會返回 Server Hello 消息,告訴客戶端,服務器選擇使用的協議版本、加密套件、壓縮算法等。這也有一個隨機數,用於後續的密鑰協商。
而後,服務器會給你一個服務器端的證書,而後說:「Server Hello Done,我這裏就這些信息了。」
客戶端固然不相信這個證書,因而你從本身信任的 CA 倉庫中,拿 CA 的證書裏面的公鑰去解密電商網站的證書。
若是可以成功,則說明電商網站是可信的。這個過程當中,你可能會不斷往上追溯 CA、CA 的 CA、CA 的 CA 的 CA,反正直到一個授信的 CA,就能夠了。
其實觀音菩薩手裏的錫杖和袈裟,就至關於佛祖頒發的證書,保證西行路上的安全,玄奘法師這個網絡包別被別人吃了,或者篡改。
就像誤入小雷音一集中,白眉老佛想吃了唐僧肉,本身披上袈裟,西天取經,求得正果。
固然,一開始觀音菩薩拿出錫杖和袈裟這個證書的時候,你們也不相信,因此須要觀音菩薩現出真身,做爲 CA,證實給客戶端,唐王李世民和玄奘法師才下拜。
證書驗證完畢以後,以爲這個服務端是可信的,因而客戶端計算產生隨機數字 Pre-master,發送 Client Key Exchange,用證書中的公鑰加密,再發送給服務器,服務器能夠經過私鑰解密出來。
接下來,不管是客戶端仍是服務器,都有了三個隨機數,分別是:本身的、對端的,以及剛生成的 Pre-Master 隨機數。經過這三個隨機數,能夠在客戶端和服務器產生相同的對稱密鑰。
有了對稱密鑰,客戶端就能夠說:「Change Cipher Spec,我們之後都採用協商的通訊密鑰和加密算法進行加密通訊了。」
而後客戶端發送一個 Encrypted Handshake Message,將已經商定好的參數等,採用協商密鑰進行加密,發送給服務器用於數據與握手驗證。
一樣,服務器也能夠發送 Change Cipher Spec,說:「沒問題,我們之後都採用協商的通訊密鑰和加密算法進行加密通訊了」,而且也發送 Encrypted Handshake Message 的消息試試。
當雙方握手結束以後,就能夠經過對稱密鑰進行加密傳輸了。
唐王素酒送三藏
玄奘這個網絡包要發出了。太宗設朝,彙集文武,要去送行。李世民送給玄奘三個東西。
上一節說了太宗是應用層,關注保大唐江山永固,玄奘是 TCP 層,要經過堅決的意志到達西天。
李世民給的第一個東西是通關文牒,這個是 IP 層的,未來要經過這個文牒經過一個個城關。
第二個東西是紫金鉢盂,這個用於玄奘法師到了某個城市裏面化齋,同時打聽路的時候使用,這個是一個 MAC 層的。
第三個東西是白馬一匹,做爲遠程腳力,這個是物理層的。
最後,太宗敬了玄奘一杯素酒,言道:寧戀本鄉一捻土,莫愛他鄉萬兩金。三藏方悟捻土之意,復謝恩飲盡,辭謝出關而去。
當客戶端和服務端之間創建了鏈接後,接下來就要發送下單請求的網絡包了。
在用戶層發送的是 HTTP 的網絡包,由於服務端提供的是 RESTful API,於是 HTTP 層發送的就是一個請求。
POST /purchaseOrder HTTP/1.1
Host: www.xxxxxx.com
Content-Type: application/json; charset=utf-8
Content-Length: nnn
{
"order": {
"date": "2018-07-01",
"className": "趣談網絡協議",
"Author": "劉超",
"price": "68"
}
}
HTTP 的報文大概分爲三大部分。第一部分是請求行,第二部分是請求的首部,第三部分纔是請求的正文實體。
在請求行中,URL 就是 www.xxxxxx.com/purchaseOrder ,版本爲 HTTP 1.1。
請求的類型叫做 POST,它須要主動告訴服務端一些信息,而非獲取。須要告訴服務端什麼呢?通常會放在正文裏面。正文能夠有各類各樣的格式,常見的格式是 JSON。
請求行下面就是咱們的首部字段。首部是 key value,經過冒號分隔。
Content-Type 是指正文的格式。例如,咱們進行 POST 的請求,若是正文是 JSON,那麼咱們就應該將這個值設置爲 JSON。
接下來是正文,這裏是一個 JSON 字符串,裏面經過文本的形式描述了,要買一個課程,做者是誰,多少錢。
這樣,HTTP 請求的報文格式就拼湊好了。接下來瀏覽器或者移動 App 會把它交給下一層傳輸層。
怎麼交給傳輸層呢?也是用 Socket 進行程序設計。若是用的是瀏覽器,這些程序不須要你本身寫,有人已經幫你寫好了;若是在移動 App 裏面,通常會用一個 HTTP 的客戶端工具來發送,而且幫你封裝好。
HTTP 協議是基於 TCP 協議的,因此它使用面向鏈接的方式發送請求,經過 Stream 二進制流的方式傳給對方。固然,到了 TCP 層,它會把二進制流變成一個的報文段發送給服務器。
在 TCP 頭裏面,會有源端口號和目標端口號,目標端口號通常是服務端監聽的端口號,源端口號在手機端,每每是隨機分配一個端口號。這個端口號在客戶端和服務端用於區分請求和返回,發給那個應用。
在 IP 頭裏面,都須要加上本身的地址(即源地址)和它想要去的地方(即目標地址)。
當一個手機上線的時候,PGW 會給這個手機分配一個 IP 地址,這就是源地址,而目標地址則是雲平臺的負載均衡器的外網 IP 地址。
在 IP 層,客戶端須要查看目標地址和本身是不是在同一個局域網,計算是不是同一個網段,每每須要經過 CIDR 子網掩碼來計算。
對於這個下單場景,目標 IP 和源 IP 不會在同一個網段,於是須要發送到默認的網關。通常經過 DHCP 分配 IP 地址的時候,也會同時配置默認網關的 IP 地址。
可是客戶端不會直接使用默認網關的 IP 地址,而是發送 ARP 協議,來獲取網關的 MAC 地址,而後將網關 MAC 做爲目標 MAC,本身的 MAC 做爲源 MAC,放入 MAC 頭,發送出去。
一個完整的網絡包的格式是這樣的:
接下來,網絡包就正式發出了。若是你是用手機打開 App,下單購物發送網絡包,通常經過手機運營商的網絡。
客戶的手機開機之後,在附近尋找基站 eNodeB,發送請求,申請上網。基站將請求發給 MME,MME 對手機進行認證和鑑權,還會請求 HSS 看有沒有錢,看看是在哪裏上網。
當 MME 經過了手機的認證以後,開始創建隧道,建設的數據通路分兩段路,實際上是兩個隧道。一段是從 eNodeB 到 SGW,第二段是從 SGW 到 PGW,在 PGW 以外,就是互聯網。
PGW 會爲手機分配一個 IP 地址,手機上網都是帶着這個 IP 地址的。
對於手機來說,默認的網關在 PGW 上。在移動網絡裏面,從手機到 SGW,到 PGW 是有一條隧道的。
在這條隧道里面,會將上面的這個包做爲隧道的乘客協議放在裏面,外面 SGW 和 PGW 在覈心網機房的 IP 地址。網絡包直到 PGW(PGW 是隧道的另外一端)纔將裏面的包解出來,轉發到外部網絡。
因此,從手機發送出來的時候,網絡包的結構爲:
源 MAC:手機也即 UE 的 MAC。
目標 MAC:網關 PGW 上面的隧道端點的 MAC。
源 IP:UE 的 IP 地址。
目標 IP:SLB 的公網 IP 地址。
進入隧道以後,要封裝外層的網絡地址,於是網絡包的格式爲:
外層源 MAC:E-NodeB 的 MAC。
外層目標 MAC:SGW 的 MAC。
外層源 IP:E-NodeB 的 IP。
外層目標 IP:SGW 的 IP。
內層源 MAC:手機也即 UE 的 MAC。
內層目標 MAC:網關 PGW 上面的隧道端點的 MAC。
內層源 IP:UE 的 IP 地址。
內層目標 IP:SLB 的公網 IP 地址。
當隧道在 SGW 的時候,切換了一個隧道,爲從 SGW 到 PGW 的隧道,於是網絡包的格式爲:
外層源 MAC:SGW 的 MAC。
外層目標 MAC:PGW 的 MAC。
外層源 IP:SGW 的 IP。
外層目標 IP:PGW 的 IP。
內層源 MAC:手機也即 UE 的 MAC。
內層目標 MAC:網關 PGW 上面的隧道端點的 MAC。
內層源 IP:UE 的 IP 地址。
內層目標 IP:SLB 的公網 IP 地址。
在 PGW 的隧道端點將包解出來,轉發出去的時候,通常在 PGW 出外部網絡的路由器上,會部署 NAT 服務,將手機的 IP 地址轉換爲公網 IP 地址,當請求返回的時候,再 NAT 回來。
於是在 PGW 以後,至關於作了一次歐洲十國遊型的轉發,網絡包的格式爲:
源 MAC:PGW 出口的 MAC。
目標 MAC:NAT 網關的 MAC。
源 IP:UE 的 IP 地址。
目標 IP:SLB 的公網 IP 地址。
在 NAT 網關,至關於作了一次玄奘西遊型的轉發,網絡包的格式變成:
源 MAC:NAT 網關的 MAC。
目標 MAC:A2 路由器的 MAC。
源 IP:UE 的公網 IP 地址。
目標 IP:SLB 的公網 IP 地址。
在手機運營商的網絡裏面,網絡情況是比較好的。對於玄奘法師,在大唐國境以內,仍是比較平安的。
原文說:師徒們行了很多天,到了鞏州城。早有鞏州合屬官吏人等,迎接入城中。安歇一晚上,次早出城前去。
一路飢餐渴飲,夜住曉行,兩三日,又至河州衛。早有鎮邊的總兵與本處僧道,聞得是欽差御弟法師上西方見佛,無不恭敬,接至裏面供給了,着僧綱請往福原寺安歇。
本寺僧人,一一參見,安排晚齋。齋畢,吩咐二從者飽餵馬匹,天不明就行。
真的是有接有送。行經半日,只見對面處,有一座大山,真個是高接青霄,崔巍險峻。
此山喚作兩界山,東半邊屬我大唐所管,西半邊乃是韃靼的地界。過了這座山,就不是大唐的土地了。
歷經千山與萬險
離開大唐的國土,接下來的路應該怎麼走呢?
好在此去西天,要通過一個個國家,每一個國家有一個個城關,玄奘法師只要處處問路,只要這些城關的守門人知道大概路怎麼走,就能一個個國家的走下去,若是遇到國家,還有通關文牒,還能保護玄奘法師在國內的安全。
這裏有兩個問題要解決,第一個是每一個城關的守門人和每一個國家,是怎麼知道去西天怎麼走的。第二個問題是玄奘如何問路,如何走。
咱們先第一個問題,這個觀音菩薩從西天來東土的時候,已經經過一種法術告訴這些國家和城關了。
菩薩的法術主要分兩種狀況,一種狀況是在一個國家內部如何走,另外一種狀況在國家之間,在野外如何走的問題。
在一個國家內部,菩薩主要遵循最短路徑原則,就是走得路越少越好,道路越短越好。
可是國家之間,菩薩不但要考慮遠近的問題,還要考慮政策的問題。例若有的國家路近,可是路過的國家看不慣僧人,見了僧人就抓。例如滅法國,連光頭都要抓。這樣的狀況即使路近,也最好繞遠點走。
菩薩的法術是什麼呢?我們在大學裏面學習計算機網絡與數據結構的時候,知道求最短路徑經常使用的有兩種方法:
Bellman-Ford 算法
Dijkstra 算法
在計算機網絡中基本也是用這兩種方法計算的。距離矢量路由(distance vector routing),它是基於 Bellman-Ford 算法的。鏈路狀態路由(link state routing),基於 Dijkstra 算法。
最經常使用的兩種路由協議:
OSPF(Open Shortest Path First,開放式最短路徑優先)就是這樣一個基於鏈路狀態路由協議,普遍應用在數據中心中的協議,稱爲內部網關協議(Interior Gateway Protocol,簡稱 IGP)。
BGP 協議使用的算法是路徑矢量路由協議(path-vector protocol)。它是距離矢量路由協議的升級版,稱爲外網路由協議(Border Gateway Protocol,簡稱 BGP)。
路由協議是城關之間相互溝通到哪裏應該怎麼走的協議。
第二個問題,也就是玄奘如何問路,如何走。這就是 IP 協議。
這就要靠通關文牒了,裏面寫着貧僧來自東土大唐(就是源 IP 地址),欲往西天拜佛求經(指的是目標 IP 地址)。路過寶地,借宿一晚,明日啓行,請問接下來該怎麼走啊?
在解決第一個問題的時候,每一個城關已經經過菩薩的法術,和鄰近的城關進行溝通,知道了下面的信息。
這個叫路由表,根據這個表格,能夠告訴唐僧怎麼走。接下來咱們看完整故事。
出了 NAT 網關,就從核心網到達了互聯網。在網絡世界,每個運營商的網絡成爲自治系統 AS。每一個自治系統都有邊界路由器,經過它和外面的世界創建聯繫。
對於雲平臺來說,它能夠被稱爲 Multihomed AS,有多個鏈接連到其餘的 AS,可是大多拒絕幫其餘的 AS 傳輸包。例如一些大公司的網絡。
對於運營商來講,它能夠被稱爲 Transit AS,有多個鏈接連到其餘的 AS,而且能夠幫助其餘的 AS 傳輸包,好比主幹網。
如何從出口的運營商到達雲平臺的邊界路由器?在路由器之間須要經過 BGP 協議實現,BGP 又分爲兩類,eBGP 和 iBGP。自治系統間,邊界路由器之間使用 eBGP 廣播路由。內部網絡也須要訪問其餘的自治系統。
邊界路由器如何將 BGP 學習到的路由導入到內部網絡呢?經過運行 iBGP,使內部的路由器可以找到到達外網目的地最好的邊界路由器。
網站的 SLB 的公網 IP 地址早已經經過雲平臺的邊界路由器,讓全網都知道了。
因而這個下單的網絡包選擇了下一跳是 A2,也即將 A2 的 MAC 地址放在目標 MAC 地址中。
到達 A2 以後,從路由表中找到下一跳是路由器 C1,因而將目標 MAC 換成 C1 的 MAC 地址。
到達 C1 以後,找到下一跳是 C2,將目標 MAC 地址設置爲 C2 的 MAC。到達 C2 後,找到下一跳是雲平臺的邊界路由器,因而將目標 MAC 設置爲邊界路由器的 MAC 地址。
你會發現,這一路,都是隻換 MAC,不換目標 IP 地址。這就是所謂下一跳的概念。
在雲平臺的邊界路由器,會將下單的包轉發進來,通過核心交換,匯聚交換,到達外網網關節點上的 SLB 的公網 IP 地址。
咱們能夠看到,手機到 SLB 的公網 IP,是一個端到端的鏈接,鏈接的過程發送了不少包。
全部這些包,不管是 TCP 三次握手,仍是 HTTPS 的密鑰交換,都是要走如此複雜的過程到達 SLB 的,固然每一個包走的路徑不必定一致。
當網絡包走在這個複雜的道路上,極可能一不當心就丟了,怎麼辦?這就須要藉助 TCP 的機制從新發送。
既然 TCP 要對包進行重傳,就須要維護一個 Sequence Number,看哪些包到了,哪些沒到,哪些須要重傳,傳輸的速度應該控制到多少,這就是 TCP 的滑動窗口協議。
整個 TCP 的發送,一開始會協商一個 Sequence Number,從這個 Sequence Number 開始,每一個包都有編號。
滑動窗口將接收方的網絡包分紅四個部分:
已經接收,已經 ACK,已經交給應用層的包。
已經接收,已經 ACK,未發送給應用層。
已經接收,還沒有發送 ACK。
未接收,尚有空閒的緩存區域。
對於 TCP 層來說,每個包都有 ACK。ACK 須要從 SLB 回覆到手機端,將上面的那個過程反向來一遍,固然路徑不必定一致,可見 ACK 也不是那麼輕鬆的事情。
若是發送方超過必定的時間沒有收到 ACK,就會從新發送。只有 TCP 層 ACK 過的包,纔會發給應用層,而且只會發送一份,對於下單的場景,應用層是 HTTP 層。
你可能會問了,TCP 總是重複發送,會不會致使一個單下了兩遍?是否要求服務端實現冪?
從 TCP 的機制來看,是不會的。只有收不到 ACK 的包纔會重複發,發到接收端,在窗口裏面只保存一份,因此在同一個 TCP 鏈接中,不用擔憂重傳致使二次下單。
可是 TCP 鏈接會由於某種緣由斷了,例如手機信號很差,這個時候手機把全部的動做從新作一遍,創建一個新的 TCP 鏈接,在 HTTP 層調用兩次 RESTful API。這個時候可能會致使兩遍下單的狀況,於是 RESTful API 須要實現冪等。
當 ACK 過的包發給應用層以後,TCP 層的緩存就空了出來,這會致使上面圖中的大三角,也即接收方可以容納的總緩存,總體順時針滑動。
小的三角形,也即接收方告知發送方的窗口總大小,也即尚未徹底確認收到的緩存大小,若是把這些填滿了,就不能再發了,由於沒確認收到,因此一個都不能扔。
功成行滿見真如
唐僧經歷九九八十一難,終於到達了西天。發現金頂大仙已經在等他們了。
網絡包從手機端經歷千難萬險,終於到了 SLB 的公網 IP 所在的公網網口。因爲匹配上了 MAC 地址和 IP 地址,於是將網絡包收了進來。
到了西天,唐僧度過最後一條河凌雲仙渡的時候,發現滾浪飛流,約有八九里寬闊,四無人跡。
好不容易盼來一條船,尚未底。原來駕船的是接引佛祖,玄奘法師的肉體隨着河水飄走,從而脫胎換骨,成就金身。
在虛擬網關節點的外網網口上,會有一個 NAT 規則,將公網 IP 地址轉換爲 VPC 裏面的私網 IP 地址,這個私網 IP 地址就是 SLB 的 HAProxy 所在的虛擬機的私網 IP 地址。
從而網絡包也脫胎換骨,實現公網 IP 到私有網絡 IP 的轉換。
固然爲了承載比較大的吞吐量,虛擬網關節點會有多個,物理網絡會將流量分發到不一樣的虛擬網關節點。
一樣 HAProxy 也會是一個大的集羣,虛擬網關會選擇某個負載均衡節點,將某個請求分發給它,負載均衡以後是 Controller 層,也是部署在虛擬機裏面的。
當網絡包裏面的目標 IP 變成私有 IP 地址以後,虛擬路由會查找路由規則,將網絡包從下方的私網網口發出來。
這個時候包的格式爲:
源 MAC:網關 MAC。
目標 MAC:HAProxy 虛擬機的 MAC。
源 IP:UE 的公網 IP。
目標 IP:HAProxy 虛擬機的私網 IP。
在第一部分,咱們說佛經是存放在一個虛擬空間裏面的,要打開這個虛擬空間,解讀經文,須要一個芝麻開門的 ID。接引佛祖會給玄奘法師一個 ID。
在虛擬路由節點上,也會有 OVS,將網絡包封裝在 VXLAN 隧道里面,VXLAN ID 就是給你的租戶建立 VPC 的時候分配的。
VXLAN ID 就是 VPC 虛擬空間的 ID,OVS 就是那個可以封裝和解開私密空間的法寶。
包的格式爲:
外層源 MAC:網關物理機 MAC。
外層目標 MAC:物理機 A 的 MAC。
外層源 IP:網關物理機 IP。
外層目標 IP:物理機 A 的 IP。
內層源 MAC:網關 MAC。
內層目標 MAC:HAProxy 虛擬機的 MAC。
內層源 IP:UE 的公網 IP。
內層目標 IP:HAProxy 虛擬機的私網 IP。
在物理機 A 上,OVS 會將包從 VXLAN 隧道里面解出來,發給 HAProxy 所在的虛擬機。
HAProxy 所在的虛擬機發現 MAC 地址匹配,目標 IP 地址匹配,就根據 TCP 端口,將包發給 HAProxy 進程,由於 HAProxy 是在監聽這個 TCP 端口的。
於是 HAProxy 就是這個 TCP 鏈接的服務端,客戶端是手機。對於 TCP 的鏈接狀態,滑動窗口等,都是在 HAProxy 上維護的。
在這裏 HAProxy 是一個四層負載均衡,也即他只解析到 TCP 層,裏面的 HTTP 協議他不關心,就將請求轉發給後端的多個 Controller 層的一個。
HAProxy 發出去的網絡包就認爲 HAProxy 是客戶端了,看不到手機端了,網絡包格式以下:
源 MAC:HAProxy 所在虛擬機的 MAC。
目標 MAC:Controller 層所在虛擬機的 MAC。
源 IP:HAProxy 所在虛擬機的私網 IP。
目標 IP:Controller 層所在虛擬機的私網 IP。
固然這個包發出去以後,仍是會被物理機上的 OVS 放入 VXLAN 隧道里面,網絡包格式爲:
外層源 MAC:物理機 A 的 MAC。
外層目標 MAC:物理機 B 的 MAC。
外層源 IP:物理機 A 的 IP。
外層目標 IP:物理機 B 的 IP。
內層源 MAC:HAProxy 所在虛擬機的 MAC。
內層目標 MAC:Controller 層所在虛擬機的 MAC。
內層源 IP:HAProxy 所在虛擬機的私網 IP。
內層目標 IP:Controller 層所在虛擬機的私網 IP。
在物理機 B 上,OVS 會將包從 VXLAN 隧道里面解出來,發給 Controller 層所在的虛擬機。
Controller 層所在的虛擬機發現 MAC 地址匹配,目標 IP 地址匹配,就根據 TCP 端口,將包發給 Controller 層的進程,由於他是在監聽這個 TCP 端口的。
在 HAProxy 和 Controller 層之間,維護一個 TCP 的鏈接。Controller 層收到包以後,他是關心 HTTP 裏面是什麼的,因而解開 HTTP 的包,發現是一個 POST 請求,內容是下單購買一個課程。
取得真經成金身
玄奘法師終於到達西天大雷音寺,見到了我佛如來。
佛祖願意傳經給玄奘,因而讓玄奘去藏經樓取經文,誰知道西天也有西天的規矩,若是不懂這裏的規矩,就很難和管理經文的人溝通,取不到真經。
同理,在電商服務裏面,每每在組合服務層會有一個專門管理下單的服務,Controller 層雖然對外暴露的是標準的 RESTful 協議,可是對內會經過 RPC 協議調用這個組合服務層。若是不懂這個協議,就無法通訊。
假設咱們使用的是 Dubbo,則 Controller 層須要讀取註冊中心,將下單服務的進程列表拿出來,選出一個來調用。
Dubbo 中默認的 RPC 協議是 Hessian2。Hessian2 將下單的遠程調用序列化爲二進制進行傳輸。
Netty 是一個非阻塞的基於事件的網絡傳輸框架。Controller 層和下單服務之間,使用了 Netty 的網絡傳輸框架。
有了 Netty,就不用本身編寫複雜的異步 Socket 程序了。Netty 使用的方式,就是我們講 Socket 編程的時候,一個項目組支撐多個項目(IO 多路複用,從派人盯着到有事通知)這種方式。
Netty 仍是工做在 Socket 這一層的,發送的網絡包仍是基於 TCP 的。在 TCP 的下層,仍是須要封裝上 IP 頭和 MAC 頭。
若是跨物理機通訊,仍是須要封裝的外層的 VXLAN 隧道里面。固然底層的這些封裝,Netty 都不感知,它只要作好它的異步通訊便可。
在 Netty 的服務端,也即下單服務中,收到請求後,先用 Hessian2 的格式進行解壓縮。而後將請求分發到線程中進行處理,在線程中,會調用下單的業務邏輯。
玄奘師徒好在後來碰到了懂得內情的註冊中心——彌勒佛,從而回到靈山,仍是按照人家的規矩辦了,纔將無字經文,換成有字經文。
下單的業務邏輯比較複雜,每每要調用基礎服務層裏面的庫存服務、優惠券服務等,將多個服務調用完畢,纔算下單成功。
下單服務調用庫存服務和優惠券服務,也是經過 Dubbo 的框架,經過註冊中心拿到庫存服務和優惠券服務的列表,而後選一個調用。
調用的時候,統一使用 Hessian2 進行序列化,使用 Netty 進行傳輸,底層若是跨物理機,仍然須要經過 VXLAN 的封裝和解封裝。
我們以庫存爲例子的時候,講述過冪等的接口實現的問題。由於若是扣減庫存,僅僅是誰調用誰減一。
這樣存在的問題是,若是扣減庫存由於一次調用失敗,而屢次調用,這裏指的不是 TCP 屢次重試,而是應用層調用的屢次重試,就會存在庫存扣減屢次的狀況。
這裏經常使用的方法是,使用樂觀鎖(Compare and Set,簡稱 CAS)。CAS 要考慮三個方面,當前的庫存數、預期原來的庫存數和版本,以及新的庫存數。
在操做以前,查詢出原來的庫存數和版本,真正扣減庫存的時候,判斷若是當前庫存的值與預期原值和版本相匹配,則將庫存值更新爲新值,不然不作任何操做。
這是一種基於狀態而非基於動做的設計,符合 REST 的架構設計原則。這樣的設計有利於高併發場景。
當多個線程嘗試使用 CAS 同時更新同一個變量時,只有其中一個線程能更新變量的值,而其餘線程都失敗,失敗的線程並不會被掛起,而是被告知此次競爭中失敗,並能夠再次嘗試。
最終,當下單更新到分佈式數據庫中以後,整個下單過程纔算真正告一段落。
固然,這個下單調用要返回一個結果。咱們下單成功啦!!!!!!