02.10 唯品會RPC服務框架與容器化演進--轉

今天要講的題目比較熱,但也比較“簡單”,因為有很多公司大型系統已經在用。我的演講內容包括兩個方面:一個是分佈式架構的實踐,另外一個是服務體系中容器化怎麼做。


分佈式服務框架實踐

唯品會RPC服務框架與容器化演進--轉

可能大家很多都聽過服務化,或者叫微服務,但是這個“微”字很難平衡,因為每個人有每個人的理解,我們的理念還是以簡單實用為主,下面是唯品會 RPC 服務化框架的主要結構,proxy 層是我們特別重要的一個環節,後面會詳細介紹。


唯品會RPC服務框架與容器化演進--轉

在展開之前,先介紹下唯品會做服務化的原因,重要的有 5 點:

  1. 服務複雜度高。大家知道唯品會做特賣的,裡面涉及到的大的系統比較多,包括庫存、訂單、支付等等。
  2. 團隊規模大,國內的大電商企業規模都是幾千人的技術規模,這是一個比較大的挑戰,不像我們現在說有幾十個人的創業公司。幾千人的公司實際上推動一些公共技術架構比較困難。我們有專門的運維部門、業務部門等。團隊越分越散,最後的結果很難協調一起開發,這是我們最大的問題。
  3. 彈性應對高併發能力,要有足夠的彈性,因為我們有雙十一,12.8 日店慶,接下來馬上是 4.19 大促。業界競爭是我們做大促的原因,但是大促現在已經越來越爛了,包括京東、蘇寧易購,包括唯品會,一週一個大促,這個不能叫大促,只能叫“周促”。大促造成的流量的併發越來越凌亂,今天可能 10 點鐘很頻繁了,到 11 點鐘沒流量了,但到了晚上 8 點流量又上來了,這種無規律的突發流量,要好支撐以及運維高性價比是很困難的一件事情。
  4. 足夠的容錯和自愈能力,這是我們做服務化最大的動力。整個的容錯體系,不能說今天死了,找一個運維人員重新找一個機器上切換 IP。當然,現實還有一部分系統做不到服務化,舊的體系依然還存在。
  5. 降低維護成本,出錯的話到底查還是不查,需要查的成本非常低。不然的話,無法把握下一次發生什麼事情。做開發的,有一大部分時間都是做查錯。
唯品會RPC服務框架與容器化演進--轉

一般公司技術體系可以分成基礎層、業務層、接入層三層的劃分。基礎層技術團隊能做的不多,數據庫、緩存及文件系統都是標準化的組件。但是服務化是在做中間層及業務聚合層,再提供 API 出來給到上面有網站及 APP 使用,服務化怎麼做對整個架構以及所有技術團隊都有影響。

經過對服務化的思考與實踐,我們主要目標是做好兩個事情,一個是整個體系的服務註冊與發現,第二個是服務治理。

服務註冊與發現

唯品會是自己構建的通信框架,基於 Thrift RPC 的方式。整個 RPC 框架分成三段:client、proxy,service。

我們的做法是把 proxy 這一層獨立出來,通過 proxy 調用服務。

為什麼這麼做?

當服務越來越多,會發現一個問題,A 部門今天升級,B 部門不升級,就會造成業務處理很混亂,路由和容錯都會很混亂。我們很難強迫業務部門說今天一定要把業務用的框架升級,業務部門會反感這種自身沒有變更需求的被動升級。所以我們會把服務治理功能獨立出來放在一個地方,就是這裡提的 proxy 端。

唯品會RPC服務框架與容器化演進--轉

服務發現網上已經有很多選擇了,搭建不是太複雜,原理上只要把服務註冊到公共的地方,即把 IP + 端口註冊,然後 client 端獲取對應的 IP + 端口的列表就可以了。有很多不同的技術實現服務發現。如 etcd、consul 及傳統的 DNS 方式。

唯品會RPC服務框架與容器化演進--轉

服務治理

服務治理傳統大家用得多的是代理模式,使用治理功能的服務都需要流經它。考慮到這個遠程代理如果有什麼異常會影響整體服務質量,我們把代理放到本地,沒用採用中心化的部署。

這是我們實現分佈式服務總結的一個理念:儘量讓所有的中心化功能都本地化,通過本地化的方式找到服務在哪裡,在本地完成治理。

當我們需要升級時,只需要把本地代理升級換掉就可以了。

唯品會RPC服務框架與容器化演進--轉

如上圖所示,服務治理還做了很多事情,主要跟業務相關的,通用層面包括服務路由、流量控制等。

灰度流量控制

剛才另外一個朋友也講灰度,我們叫 AB 測試,做法如下。

我們可以通過百分比的方式,在新上一個服務的時候,只放 1% 或者千分之一的流量來做灰度。

這樣的話,影響客戶量是最小的,不然的話,原來有 9 臺機,再上一臺可能有問題的機器,就有十分之一的概率出錯。

治理策略

服務治理方面還做了服務之間的隔離,防火牆的部署和鄰近機房路由等。

如果服務部署在異地多個機房,服務就會產生跨牆的問題,機房與機房最快也要三二十毫秒,需要充分考慮跨牆及延遲的特性。我們還做了一些熔斷、限流的策略。

大家可以對比一下 Dubbo,我們沒有選擇它的原因就是上述服務治理方面功能的需求。

對於 proxy 高可用,實際上我們有一個災備,把同樣的 proxy 在中央找一個地方做容災,當你發現本地不通的時候可以在遠端找到。這樣就可以做災備,實現無縫升級。

另外我們做的彈性路由,在不同的 IDC 機房間配不同的 IP 段之間路由的優先級,當優先級不同的時候優先選鄰近的機房的服務處理。

減化運維

另外一個減化運維的需求,也是跟多機房有關。

唯品會RPC服務框架與容器化演進--轉

如果有很多機房,有一個機房正好做支付,現在支付的要求比較高一些,所有的服務都會被保護起來,就會有一個問題,當找到那臺機器的 IP 時候,有可能發現這臺機器不通。

這是由於我們從註冊發現來找,有可能找到的是防火牆後面的那臺機器,這樣每次去申請支付的時候,就會出現一個問題,要求所有的客戶端的防火牆訪問策略都要被打開,然後才允許不同的客戶端進來。

但最大的問題是做支付服務的那個人根本不知道有多少人在用它。怎麼辦?我們實際上通過判斷服務是不是個特定的服務,如果是把它全部繞到一個防火牆後面的遠程 Proxy,然後通過反向代理的方式進來,這樣的話,避免每次都需要做配置防火牆策略,只需要給(Proxy)獨立開一個對外的開放端口就可以了。

中間聚合層

服務本身是零散化的東西,通常要接入的是中間層。實際上會在中間層做聚合,聚合層本身即可以做業務聚合,也可以做中間層的聚合,每一層的聚合都要做異步調用的設計。同時要對接口進行抽取,這樣的話才能給 APP 使用。因為 APP 本身是沒有服務發現的。

唯品會RPC服務框架與容器化演進--轉

RPC 性能

使用 RPC 有很多理由, 我們這裡對比一下它的整體的性能(當然性能只是一方面,是否真的需要,取決於你到底用多少性能,latency 想要多少)。

這是我們自己內部的一個簡單的對比。我們會起用調用跟蹤、寫日誌等,大概我們在 4.8 萬 TPS,用 Tomcat Rest 方式壓,可以到 2.4 萬。

唯品會RPC服務框架與容器化演進--轉

總結

整個服務化來說,不是純粹引入一個 RPC 框架來做這麼簡單,整個服務化是一個體系,它包括很多東西,服務框架只是其中一個面。服務離散化之後,在管控服務方面,需要付出的代價也會大,大家做服務化之前一定要想清楚。

唯品會RPC服務框架與容器化演進--轉

其他實踐總結

順帶提一下我們的“黑科技”。

1、壓測時候需要把 JMeter 參數調好,不然的話,很有可能不是的服務的問題,而是 JMeter 可能壓不到。

2、注意 Young GC 的次數。

3、ZooKeeper

我們服務發現與治理用的 Zookeeper,Zookeeper 瓶頸非常多,如何在跨機房、大數據量情況下如果用好 ZooKeeper?

首先整個系統設計,核心做選舉的三個節點一定要放在同一個數據中心部署。不然寫數據會造成整個 Zookeeper 集群不穩定。另外所有的業務節點全部掛在觀察者模式上,讓觀察者模式不要影響全局。

唯品會RPC服務框架與容器化演進--轉

容器化演進

唯品會RPC服務框架與容器化演進--轉

下面分享一下我們容器化的演進。

我們運維思路遵循簡單原理,目前採用單進程部署,運維簡單也是為了最大的容錯。

在物理機體系上,雖然私有云我們也在做。但是要打造的體系比較大,運維難度也比較大。不少物理機 CPU 才百分之幾。這是我們為什麼要做容器化的原因。

容器化的選型,沒有說哪一個對哪一個錯,我們選型充分考慮了自己的特性。

我們容器化最後選擇 Marathon 和 Mesos,主要原因是為了適應物理層。

Kubernetes 還沒有做物理機這一層管理。我們需要方案有對整個體系後續的管理能力。K8S 裡面的細節我就不說了(最大到 1000個 節點),每個人都有自己的喜好及場景來選擇。

唯品會RPC服務框架與容器化演進--轉

下面是整個容器平臺的概貌,左邊服務化體系和監控體系,最右邊是原有的物理機運維體系,這兩個都可以直接沿用之前的系統,不需要太多調整。

容器裡面是我們主要提幾個東西,包括業務的服務、Flume Agent, cAdervisor 等,我們還是遵循容器單進程的理念。

唯品會RPC服務框架與容器化演進--轉

整個容器化的發佈流程也比較簡單,從開發一直到運維,通過 Mesos + Marathon 做調度,用 Docker 運行,再做監控分析,還有一些輔助的系統,比如網絡和運維的工具等。

鏡像的發佈

從發佈的角度,要考慮怎麼簡單。我們做的簡易化的發佈,直接用 Registry + Jenkins 實現。大家只要在 Jenkins 寫好腳本就可以了,這是一個簡化的流程。不需要做代碼開發。

唯品會RPC服務框架與容器化演進--轉

對於 Registry HA 方案,如果做一個類似於用分佈式軟件存儲的方式,我不確定能不能做好管理。我們還是走最簡單的方式,在 Jenkins 裡面把它部署到多個 Registry 裡。前面配置反向代理,讓客戶端可以訪問到,這樣容量就不會有問題。

唯品會RPC服務框架與容器化演進--轉

網絡

默認不管用 NAT 的方式還是 host 方式,它的管理始終是很麻煩。我還是希望 Marathon + Mesos 的方式不管網絡,網絡交給我們自己管。目前我的方式是每臺機器用 Linux VLan 的方式。希望後續 libnetwork 可以支撐更好的 DHCP 的方式,目前還沒考慮引入。

唯品會RPC服務框架與容器化演進--轉

VIP DCOS

大家都很熟悉 DCOS,我們要做的事情就是基於 mesos + marathon 和 docker、cAdervisor 等組合成一個服務,包括實現我們自己的監控體系,還有策略的管理,包括彈性伸縮調度的能力,然後做一些預警,這些組件整合在一起,有一個獨立的入口。

業務部門始終都是比較厭煩繁雜的東西。因此提供了一些相對友好的一些界面。

唯品會RPC服務框架與容器化演進--轉

資源共享

當公司大了之後,不同的部門有自己的運維,不同的部門有自己的機器。他不想與別人共享,整個雲化又是共享的概念,我們針對這種方式做一個限制的資源池的隔離,比如購物車和下單隔離成兩組,自己的共享及彈性調度在自己的池裡去做。

唯品會RPC服務框架與容器化演進--轉

當然當大促的時候,我們會從公有池給它分額外的資源。將來繼續演進,如果需要我們可以把它升級到公有云,把公有云機器變成 Mesos 的 slave 機器,把它掛到自己的集群裡面,它就可以被調度了。

容器的“黑科技”

唯品會RPC服務框架與容器化演進--轉

容器使用,我們使用了一些“黑科技”。

首先,我們在做容器化的時候調整了 Linux,在上面做一些額外的手腳。

內存策略:首先是主機 memory,一個是回收的策略的調整,一個是 swap 的調整,它是比較大的問題。默認的 memory 使用 60% 後就會使用 swap,但是最好的方式儘可能用光 memory 再用 swap。

IO 優化:兩個 IO 比較關鍵,一個是磁盤 IO,一個是網絡 IO。因為容器多了之後,實際上一個物理機能支撐 log 輸出的磁盤 IO 是非常有限的。這樣的話,支撐不了幾個容器,所以 IO 是一個很大的影響。儘可能在物理機上配多個磁盤,把不同的 log 文件用不同的磁盤隔離開。第二個手段是應用程序本身將 IO 做一個抽樣,不是所有的應用程序所有的 log 都要輸出,根據情況做抽樣大多可以滿足需要。

磁盤 IO:

再次,像我們這樣的服務化體系,將 log 蒐集到中心地方,log 存到本地意義不大。這樣可以用一塊內存磁盤方式先寫進來,避免磁盤 IO。

網絡 IO:建議最好用高性能萬兆網卡和交換機。如果沒有,則可以用多個千兆卡把它bond在一起。 今天講的大概這麼多,謝謝大家!



原文地址:http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=405781868&idx=1&sn=cbb10d37e25c76a1845f593a222da3c9&scene=0#wechat_redirect


分享到:


相關文章: