引言
隨著移動互聯網的瘋長式發展,互聯網公司開始因為自身產品的用戶指數級增長的同時,內心是復雜的.用戶量的增加往往會給自己的產品提升知名度和經濟效益.另一方面,超大用戶訪問量也給系統的維護和開始帶來了挑戰.目前國內面臨著巨大高并發的企業典型的有兩家,12306和阿里的各種購物狂歡節.2011年的時候12306還在春運時遭到廣大刷票黨的吐槽,到15年的今天,12306一點一點的在進步著.而淘寶每年的雙11一天的進賬就是千億級,這么大的用戶訪問量是如何做到服務器不當機的呢.這里涉及到一個非常典型的問題,一臺再好的服務器,帶寬再強大也無法保證上億的用戶同時訪問,可以說服務器是一個高并發時的瓶頸,如何解決這個瓶頸?阿里和12306是怎么克服這個問題的呢?作為開始工程師,我對此十分感興趣,做了一些研究,并用Cisco Packet做了簡單的模擬.
在進一步解決服務器瓶頸問題之前,需要有具備一些基礎的計算機網絡知識,理解這些基本概念.這是解決高并發問題的一個基本前提,離開這個根基,去談集群就是耍流氓.
知識準備
- 計算機兩種分層結構OSI和ISO
- IP地址/子網掩碼
- 網關/默認網關
- TCP連接的三次握手與四次分手
- 數據包/mac地址/端口號
- 路由器
- 交換機
- 網卡
互聯網中計算機間的通信
名詞解釋
host1 --- 主機1(可以理解成互聯網中做任意一臺電腦)
host2 --- 主機2
host3 --- 主機3
switcher1 --- 交換機(物理設備,二層,只看目標與源的mac地址與端口)
router1 --- 路由器(三層,看目標與源的IP地址)
網卡 --- 物理設備,維護著一個IP地址,該地址與一個mac地址是綁定關系.
任意兩臺主機想要通信,需要先互發數據包,進行三次握手,成功建立連接后,再由請求主機向目標主機發送數據包.這是一個互聯網請求的大前提.
假如有一臺主機host1, 它本地維護著一張路由表,數據結構如下
host1與host2通信
Step1: 確認要發送的數據包三大內容,mac地址,IP地址,端口.
Step2: 發送數據包建立進行三次握手,這是關于最小網絡連接的導圖.一個簡單的http請求,必須完成的最小粒度應該是三次握手---數據---四次分手.只有雙方主機都確認分手以后,客戶端才會釋放本次連接使用的端口號,以節省資源.
Step3: 發送真實數據,下圖顯示了其發送數據的過程.圖中host1與host2處于同一個網段中,中間只連了一臺交換機,于是直接將數據包扔給交換機,交換機通過物理網卡收發數據,這個速度無疑是非常快的.具體過程下圖有詳細說明.
host1與Host3通信
step1與step2同上.
step3:host1與host3不在同一個網段,因此在確認數據包時,需要取網關的mac地址;此后host1將請求數據扔給肉頭,也就是router1.這后router1要做的事情是重復操作step1,step2,step3,直到找到目標主機.如果目標主機根本不存在,那么連接會超時.過程分析圖如下.
服務器的瓶頸
設計一個極簡單的web網站, 很容易搭建一臺服務器,上面放著用戶可能需要的所有資源文件,圖片,視頻和日記等等.這個模型實現了非常簡單的網絡結構,效果顯著.但也存在問題,當你在為網站做了大量推廣時后,用戶量猛增,同一時間的訪問量跟著漲起來,保持一天增1000個(假設這個網站做的不錯,用戶不會流失),那么三個月后,這臺服務器變得力不從心.用戶關于訪問頁面總是404的一系列負面反饋也日益頻繁.這就是高并發形成的服務器瓶頸.
這個現象揭示了兩個問題
- 用戶訪問量大的時候,服務器甚至都無法保證與每個請求建立連接.
- 同樣是高并發,一臺服務器畢竟只能提供有限的IO,終究導致往外寫數據十分緩慢.
解決辦法1
既然一臺服務器已經無法滿足海量用戶的訪問,那么就多買幾臺服務器好了.話說顧客是上帝,互聯網時代,用戶群就是王道,一切為用戶.
不幸的是問題依然存在.比如:
- 你有多臺服務器,用戶請求的地址始終都是同一個域名這個請求最終該由哪臺服務器響應呢?
- 即使現在的域名解析支持一個域名綁定多個IP地址.那這個IP地址就必須是公網IP,而公網IP資源有限,一臺服務器一個公網IP,顯然不是良策.
解決辦法2
既然不能用公網IP,那么就在這些服務器與客戶端之間再搭一臺中間服務器,這臺服務器負責持有公網IP,然后將用戶請求的數據轉發給其后的真實負服務器,即可.
這種解決方案,會遇到一個網絡技術問題.
用戶在發送請求時,首先會給中間服務器發送數據包,進行三次握手,這個過程建立連接的是用戶與中間服務器.這就會導致負載服務器給用戶發送響應數據時,被用戶認為是不合法的連接,將被用戶丟棄.
解決辦法3
其實這個問題在實際生活中,早在1998年國內就有人提出了解決方案,那就是章文嵩士提出的LVS虛擬服務器.
它是這么解決的.
中間服務器D(10.211.55.2)收到用戶C1(192.168.1.100)的請求數據包后,只是拆包,將目標的mac地址修改到自己網段中一臺真實服務器RS1,然后將數據包打好后發給RS1.
這臺RS1收到數據后,判斷請求信息,其中源信息和目標信息本地都擁有,于是給予自己直接給用戶發送確認連接.而收到請求的用戶C1,再次向中間服務器D發送確認連接的數據包.最終建立TCP連接的是C1與RS1.這樣就使得RS的收發數據變得合理合法與高效.
這就是著名的LVS(Linux Virtual Server).
結束語
有幸的是LVS被Linux內核收錄,只要你的主機上運行著Linux內核,就自帶有LVS軟件服務,這很容易讓有需求了解LVS的人自己動手搭一個集群,模擬這種負載均衡技術.
這將在明天的博文中更新,會有大概三種LVS實現方式.