標籤:go paas cloud
最近一年的工作,有很大的比重在做雲平台的事情,簡單來說,就是為公司內使用者提供一個PaaS,使用者可以在我們的雲平台上方便的將單機服務程式擴充為多執行個體程式,以平台服務化的方式對外提供。在這裡簡單分享一下。
首先簡單說一下我們解決了使用者的什麼需求,或者說痛點。
基礎演算法直接以庫的形式提供給應用方?
使用者提供了一個基礎演算法,這個演算法可能以一個動態庫的形式提供,那麼使應用方需要關注編譯依賴,需要關注詞典等模型檔案,開發成本比較高。尤其是如果這個基礎演算法需要升級,或者模型檔案需要升級的時候,還需要通知應用方進行修改。而且,如果基礎演算法不穩定,有出core的行為,那麼勢必影響了應用方的服務品質。還有就是,如果基礎演算法非常耗資源,比如CPU,記憶體佔得太多,可能會影響應用方程式對於資源的使用。
基礎演算法的服務化
為了避免基礎演算法以動態庫提供給應用方的種種弊端,基礎演算法可以以網路服務的形式提供,這就是基礎演算法的服務化。就是說,基礎演算法是一個網路服務,使用者直接存取這個網路服務即可。這樣,基礎演算法的服務介面只要不變,不論它如何升級,都不需要應用方做任何修改。開源的Thrift,等等RPC的方案,都很好的滿足了基礎演算法服務化的需求。
服務化的品質如何衡量
那麼一個服務化的基礎演算法,如何保證上面所說的服務品質和延時上的要求呢。尤其是服務品質,或者說可靠性。如果我們假設機器永遠無故障,網路裝置也永遠運行正常,服務也足夠穩定,不會有core,也不會升級等等,那麼直接找一些機器拉起來就萬事大吉了。但是,現實卻是殘酷了,首先服務可能會有故障,它應該會不斷升級(如果有一個不用升級的程式,要麼是太完美了,要麼就是沒有人用了,大家寫程式都知道,完美的程式你永遠寫不出來,少寫點爛代碼才是正常追求),升級的過程不能影響服務品質,還有服務不可能獨佔機器的,很有可能會和其他服務混布,那麼如何選擇合適的機器部署,也是一個問題。還有,很多時候一個服務執行個體是滿足不了需求的,可能要部署多個服務執行個體,這裡邊的問題就更多了,請求發給哪個執行個體,負載平衡,等等等。
服務平台化需要面對的問題
我們下面將服務化的基礎演算法,以承諾的服務品質對外提供的過程,稱為服務的平台化。就是說,服務化的基礎演算法,經過一個平台對外提供,就能獲得相應的服務品質。那麼平台化的挑戰有哪些呢?
如果一個基礎演算法自己想實現平台化,閉門造車,需要做很多工作。這也是PaaS存在的意義,將大家服務化的工作都通用化,讓策略開發人員解放出來。那麼,平台化要解決的哪些問題,或者基礎演算法服務化的痛點在哪裡呢?
服務的平台化,並不是簡單的在幾台機器上把一個服務部署起來,對外提供服務,尤其是對應用方承諾了服務品質的時候。而且,為了提升機器的資源使用率,一般幾個服務會混布在一起,因此如何合理部署服務也是一個問題。除此之外,服務的平台化還需要關注很多事情,使用者一般需要關注以下幾點:
1. 如何定義服務介面,使得使用者根據這個服務介面就可以自助完成服務訪問
2. 服務定址:應用方通過何種方式訪問訪問背景策略服務,如何做請求的負載平衡,後台服務地址變更時,如何通知應用方
3. 服務上線:既要保證上線新的服務不能影響老的服務,又要滿足當前服務的資源需求
4. 服務擴容:隨著請求的增加,如何擴充執行個體數來滿足應用方需要
5. 機器故障:機器出現故障時,如何保證服務品質不受影響,如何將故障機器上的服務遷移到其他的節點
6. 服務升級:如何?在不影響服務品質的前提下完成服務的升級
7. 訪問統計:如何統計訪問量,服務延時,能夠區分不同使用者訪問的不同服務等,類似於Hadoop Counter,實現一個比較簡單通用的Counter
8. 監控與警示:服務出現問題時,如何?警示機制,以便第一時間發現並解決問題
9. 存取權限與流控:服務屬於保密性質,只能讓指定使用者使用;應用方的訪問頻度需要按照約定來進行限制
10. 服務執行個體的動態擴容與縮容:為了節省資源,增加資源使用率,需要有動態擴容與縮容的機制:即服務執行個體負載高的時候,能夠擴容以滿足計算需求,而在負載低的時候,縮減服務執行個體以將機器資源給其他服務使用。
架構當然要去解決基礎演算法平台化的時候遇到的上述問題。但是除了這些問題之外,還需要關注以下問題:
1. 資源管理和調度:服務要分配哪些機器
2. 服務的部署:分配了機器後,服務執行個體的程式包如何下載,下載後如何拉起服務
3. 服務地址的彙報和更新:服務執行個體拉起後,如何彙報服務地址,讓應用方使用這些地址,還有地址更新後,如何通知到應用方
4. 資源隔離:只能給服務以承諾的配額,比如多少CPU,多少記憶體;避免有問題的服務影響其他的服務
5. 不能影響服務的效能:這就要求不能用有效能損耗的虛擬化技術來做隔離等,我們要實現使用者直接使用物理機相同的效能效果
6. 計費系統,按照不同的資源使用方式來計費。對於公司內部平台來說,如果機器是平台的,使用者只是使用,那麼可以沒有這個系統;但是如果需要服務的提供方提供機器,來換取相應的計算資源,那麼還是需要的。
由於以上問題,RD不能專註於核心策略的實現,不得不做很多平台化的事情。當然了,部分問題可以通過人工營運的來完成的,但是這又會造成服務的維護成本過高。而且,人工營運總有一定的滯後性,可能在某些情境下會出現服務品質下降的問題。還有機器的資源使用率的問題,也是一個複雜問題。
如何解決上述問題
那麼如何解決上述問題,這裡我們給出一些可能的解決方案:
1. 如何定義服務介面:使用一些通用的RPC解決方案,比如Thrift。像我們使用的是sofa-pbrpc,https://github.com/baidu/sofa-pbrpc。這個是百度內部應用比較廣泛的一個RPC,有針對於公司內部應用情境的豐富組件。
2. 服務定址:簡單來說定義一個介面通知應用方後台服務的地址。當然sofa-pbrpc有實現的一個定址組件,應用方只需要指定一個名字就可以完成定址,這個組件也完成了負載平衡的策略,能夠將請求打散平均發送到背景服務商。當然可以以ZK來實現定址。比如服務執行個體拉起後將自己的地址添加到ZK的一個節點下,退出時由於與ZK的串連斷開而自動刪除自己。這樣應用方只要監控這個節點的資料變化即可。負載平衡的話最簡單的就是將請求按照順序發送到後台。但是有一個問題就是機器可能處理能力是不相同的,就是叢集的機器都是異構的,因此可以記錄一下每個節點的處理能力,當一個服務節點pending的請求比較多時,那麼就優先發給處理請求比較快的節點上。
3. 服務上線:這個實際上需要叢集資源管理與調度的功能,就是使用者提交了服務上線的請求時,按照使用者的資源請求,比如每個服務執行個體需要多少CPU Core, Memory以及網路等的情況,還有執行個體的個數,為這個服務分配計算資源。叢集會選擇符合這個服務的機器節點,分配給服務。這個分配演算法業界也有很多研究,核心就是提供資源使用率,而又要保證服務的品質。對這個有興趣的可以看一下dominant resource fairness演算法。
分配了計算資源後,就需要在節點上把這個服務部署好,部署完成後把服務拉起。
4. 服務擴容:當服務的負載變高時,需要擴容服務執行個體數。這個其實和服務上線差不多,需要分配計算資源,部署,服務拉起等。
5. 機器故障:任何雲平台都要考慮這個情況,尤其是機器數量多的時候,機器故障幾乎成為一個必然會發生的事情。這個需要下線這個機器,即資源調度模組標記該機器未不可用。其次還需要將該機器上啟動並執行服務執行個體遷移到其他節點。
6. 服務升級:這個過程可以不需要資源調度模組的參與:在各自的服務執行個體所在的節點上就地升級,比如直接下載程式包,下載完成準備好環境後直接停止原來的進程,啟動新部署的即可。當然這個進程重啟勢必會影響服務品質。如果服務需求不需要是100%的,那麼可能這個最簡單的方法也是可以接受的。當然也可以在用戶端加重試的邏輯,如果延時能夠忍受的話。
另外一個方法就是重新分配一些節點,然後啟動新的服務執行個體後,將老的機器先從應用方的定址中刪除,保證不會再有新請求達到老的服務執行個體。在服務執行個體的負載都為0時,老的服務執行個體下線。這樣做稍微複雜,但是不會影響服務品質。但是如果服務執行個體數百上千,那麼這個代價會比較高,甚至沒有足夠的節點來完成這個升級。當然可以分批次升級,這樣無疑有複雜了些。
第一個方法有一個優點,由雩都是就地升級的,因此可以快速復原的老的版本,因為不需要下包了,復原的時間開銷就是進程重啟的時間。
7. 訪問統計:互連網公司都會有這個模組,就是分布式日誌的收集,匯聚和展現。以便展示服務的調用量,延時,等等的報表。這個開源社區也有很多的實現。一般來說就是每個服務執行個體列印訪問統計的日誌,這些目標日誌會被部署到每個節點的agent收集,發送到比如一個MQ裡,然後由一些背景工作執行緒去處理這些日誌。
8. 監控與警示:平台資源的整體使用量,叢集節點的資源使用方式,比如CPU IDLE,Memory的監控,服務執行個體狀態的監控等。在檢測到異常觸發閾值時警示給使用者,或者叢集管理員等。
9. 存取權限與流控:這個可以和公司的帳號體系打通,這樣就可以追蹤到非常細粒度的存取權限控制,當然簡單的做法也可以直接使用訪問者IP來做限制,實行IP白名單的制度。流控對於離線服務比較重要,離線服務注重吞吐,但是有時候一個Hadoop任務起來,可能發到背景壓力非常大,因此流控可以保證後台服務不被壓垮,或者保證每個Task不會與其他的Task有資源的競爭。對於線上服務,流控有的時候也會有,比如拒絕一部分請求,總比大家都一起慢下來,但是誰都用不了好。說道這裡,又想起一個叢集的慢節點的問題,就是一個叢集有dead的節點不害怕,就怕有比較挫的節點,運行超慢但是半死不活,特殊情況下可能會拖累整個平台。可以看一下這個文章:http://danluu.com/limplock/
10. 服務執行個體的動態擴容與縮容:有的同學會問服務執行個體如果沒有計算,就空跑在那裡唄,但是至少它會佔用記憶體,而且,一般叢集為一個服務分配計算資源時,一般會以CPU,記憶體為度量單位,因此如果一個服務佔用了CPU,記憶體,那麼就會保證它至少能用到這些,對於線上服務來說,“虛擬”一些資源出來在某些情境下會影響服務品質的。
上面這個問題,任何一個問題都可以衍生出好多問題。因此,本文是我想給大家分享的自己構建一個雲平台的時候,需要注意的事情和需要關注的點。完全是拋磚引玉。
我們在過去的一年中,使用Go實現了這麼一個雲平台。在這裡也推薦一下Go。標題中的Go,實際上就是Go的意思。Go,雲時代的系統程式設計語言,就像過去十年伺服器的程式設計語言是C一樣,學了你就知道這句話什麼含義了。
最後做一個廣告吧,百度的同學如果看到這篇文章,可以搜尋內網搜尋SofaCloud,一個徹底解決方案策略開發人員的平台化之痛的雲平台。除此之外,我們通過架構最佳化,還可以節省85%的業務方機器!!我們當前日均數百億的計算量,數千個計算執行個體,服務數十個產品線!!!想什麼呢,還不趕緊遷移到我們這上邊來!!!
用了SofaCloud後,明明的頭髮都長出來了有沒有!!!氣色變好了,有沒有!!!
Cloud,Go!
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
獨立開發一個雲(PaaS)的核心要素, Go, Go, Go!!!