日均请求量百亿级数据处理平台的容器云实践
from:?http://geek.csdn.net/news/detail/97887
聲明:本文為CSDN原創(chuàng)投稿文章,未經(jīng)許可,禁止任何形式的轉(zhuǎn)載。?
作者:袁曉沛,目前在七牛云的主要工作是基于容器平臺(tái)構(gòu)建分布式應(yīng)用,借助容器的優(yōu)勢(shì),實(shí)現(xiàn)大規(guī)模分布式應(yīng)用的自動(dòng)化運(yùn)維以及高可用,以PaaS服務(wù)的形式提供服務(wù)器后端應(yīng)用,同時(shí)致力于讓開(kāi)發(fā)者從繁瑣的后端運(yùn)維工作中解放出來(lái)。曾參與盛大網(wǎng)盤(pán)EverBox、EMC備份服務(wù)Mozy后端存儲(chǔ)的設(shè)計(jì)、開(kāi)發(fā)工作,主要方向在分布式系統(tǒng)的架構(gòu)設(shè)計(jì)、開(kāi)發(fā)、性能調(diào)優(yōu)以及后期運(yùn)維優(yōu)化。?
責(zé)編:錢(qián)曙光,關(guān)注架構(gòu)和算法領(lǐng)域,尋求報(bào)道或者投稿請(qǐng)發(fā)郵件qianshg@csdn.net,另有「CSDN 高級(jí)架構(gòu)師群」,內(nèi)有諸多知名互聯(lián)網(wǎng)公司的大牛架構(gòu)師,歡迎架構(gòu)師加微信qshuguang2008申請(qǐng)入群,備注姓名+公司+職位。
七牛云研發(fā)架構(gòu)師袁曉沛日前結(jié)合七牛云自定義數(shù)據(jù)處理平臺(tái)業(yè)務(wù)的容器化實(shí)踐,從平臺(tái)的業(yè)務(wù)特點(diǎn)、為什么容器化、如何實(shí)現(xiàn)容器化以及容器實(shí)踐的具體效果等角度進(jìn)行了分享。以下是對(duì)他演講內(nèi)容的整理:
數(shù)據(jù)處理業(yè)務(wù)簡(jiǎn)介
數(shù)據(jù)主要有三種處理方式:
官方數(shù)據(jù)處理:?
提供基礎(chǔ)的數(shù)據(jù)處理服務(wù),包括但不限于圖片的轉(zhuǎn)碼、水印、原圖保護(hù)、防盜鏈等,以及音視頻的轉(zhuǎn)碼、切片和拼接等。
自定義數(shù)據(jù)處理:?
允許用戶構(gòu)建、上傳自定義的私有數(shù)據(jù)處理服務(wù),并無(wú)縫對(duì)接七牛云存儲(chǔ)上的數(shù)據(jù)以及其他數(shù)據(jù)處理服務(wù)。
第三方數(shù)據(jù)處理:?
一個(gè)開(kāi)放的應(yīng)用平臺(tái),提供大量功能豐富的第三方數(shù)據(jù)處理服務(wù),比如圖片鑒黃、人臉識(shí)別、廣告過(guò)濾、語(yǔ)言翻譯、TTS 等。
圖 1
圖1是數(shù)據(jù)處理的一個(gè)調(diào)用示例。無(wú)論是七牛云的官方數(shù)據(jù)處理,還是自定義數(shù)據(jù)處理,或者第三方數(shù)據(jù)處理,都是以這種形式調(diào)用的。最左邊的是一個(gè)URL,代表一個(gè)文件,中間綠色的Facecrop是數(shù)據(jù)處理命令,右邊的200×200是請(qǐng)求參數(shù)。
圖 2
如圖2所示,從左邊的人物肖像圖原圖到右邊200×200的小圖片,這個(gè)服務(wù)可以把人臉從原圖中剪裁出來(lái)。通過(guò)管道操作,還可以把圖片再存到存儲(chǔ)中,以后直接使用這個(gè)小圖,不需要再走數(shù)據(jù)處理計(jì)算。這是一個(gè)典型的數(shù)據(jù)處理調(diào)用。
官方數(shù)據(jù)處理的挑戰(zhàn)
第一,請(qǐng)求量非常大。目前,系統(tǒng)每天有近百億的數(shù)據(jù)處理請(qǐng)求量。年底,可能會(huì)在目前近千臺(tái)的計(jì)算集群基礎(chǔ)上翻好幾倍,整個(gè)存量、增量都非常大;
第二,突發(fā)流量非常頻繁。很多客戶是從其它云遷到七牛云,首次把大量文件遷移到七牛存儲(chǔ)后,往往會(huì)發(fā)起大量的數(shù)據(jù)處理請(qǐng)求,這會(huì)帶來(lái)大量突發(fā)流量;
第三,CPU密集型計(jì)算。目前后端集群中,絕大部分的機(jī)器都是用來(lái)跑圖片、音視頻轉(zhuǎn)碼的,這些都是CPU密集型的計(jì)算,這意味著后臺(tái)需要很多臺(tái)機(jī)器,而且CPU的核數(shù)越多越好;
第四,IO操作頻繁。IO分為磁盤(pán)IO和網(wǎng)絡(luò)IO,數(shù)據(jù)處理前,往往需要先把原始文件從七牛存儲(chǔ)中下載到本地磁盤(pán),所以磁盤(pán)IO和網(wǎng)絡(luò)IO都很頻繁。
官方數(shù)據(jù)處理的架構(gòu)演化
圖 3
圖3是數(shù)據(jù)處理早期的一個(gè)架構(gòu)圖。當(dāng)時(shí)比較簡(jiǎn)單,所有請(qǐng)求都經(jīng)過(guò)FopGate,每個(gè)節(jié)點(diǎn)上都部署了很多圖片、音視頻或者文檔處理的Worker,是具體做轉(zhuǎn)碼的計(jì)算服務(wù)。整個(gè)架構(gòu),Worker在網(wǎng)關(guān)上是靜態(tài)配置,增加新的Worker時(shí)需要改網(wǎng)關(guān)配置重新加載,做起來(lái)會(huì)很麻煩。另外,請(qǐng)求進(jìn)來(lái)時(shí),對(duì)應(yīng)要處理的數(shù)據(jù)也是通過(guò)網(wǎng)關(guān)服務(wù)進(jìn)入,控制流和數(shù)據(jù)流放在一起,網(wǎng)關(guān)整體壓力非常大,當(dāng)時(shí)出了很多問(wèn)題。
圖 4
圖4是數(shù)據(jù)處理目前的主體架構(gòu)。右圖左上角增加了一個(gè)Discovery組件,收集Agent上報(bào)的信息,Agent和Worker把自己能做什么事都上報(bào)到Discovery。每增加新的主機(jī)Agent和Worker時(shí),不再需要靜態(tài)配置,只需指向的該Discovery服務(wù)。網(wǎng)關(guān)可以通過(guò)Discovery獲取信息,根據(jù)進(jìn)入的具體請(qǐng)求,將這個(gè)請(qǐng)求路由到不同的Agent,Agent再把請(qǐng)求轉(zhuǎn)到Worker處理。Agent組件還有負(fù)載均衡的作用,請(qǐng)求會(huì)選擇后端相應(yīng)的節(jié)點(diǎn)執(zhí)行,另外也起到下載文件的作用。下載文件的數(shù)據(jù)流不經(jīng)過(guò)網(wǎng)關(guān)服務(wù),Worker向Agent發(fā)起一個(gè)下載請(qǐng)求,然后這個(gè)Agent到存儲(chǔ)上下載數(shù)據(jù),放到自己的緩存中。
這個(gè)架構(gòu)解決了一些問(wèn)題,但是之前提及的挑戰(zhàn)依然存在。主要的問(wèn)題是FopGate在過(guò)載時(shí)依然會(huì)崩潰,每個(gè)主機(jī)會(huì)過(guò)載出問(wèn)題,造成請(qǐng)求變慢或宕機(jī)。接下來(lái)討論一下如何解決這些問(wèn)題。
如何應(yīng)對(duì)官方數(shù)據(jù)處理的挑戰(zhàn)
系統(tǒng)測(cè)量
第一,測(cè)量FopGate的服務(wù)能力。按照線上的配置,針對(duì)同比例縮小的集群做性能測(cè)試,測(cè)試出FopGate單機(jī)最大的請(qǐng)求數(shù)和句柄數(shù),根據(jù)實(shí)際的業(yè)務(wù)量,確定機(jī)器配置和數(shù)量。
第二,測(cè)量某種數(shù)據(jù)處理的資源使用范式。大多數(shù)據(jù)處理是CPU密集型計(jì)算,我們需要找到單個(gè)處理的資源使用規(guī)律。測(cè)試方式如下:取線上約10萬(wàn)或100萬(wàn)個(gè)請(qǐng)求,針對(duì)一臺(tái)測(cè)試機(jī)器壓力測(cè)試。比如測(cè)Image,測(cè)試這臺(tái)機(jī)器的變量有以下三個(gè):Image 實(shí)例數(shù),并發(fā)處理數(shù)和隊(duì)列長(zhǎng)度。最終拿到的一個(gè)結(jié)果是,做圖片剪裁、圖片處理、圖片轉(zhuǎn)碼等服務(wù),一個(gè)進(jìn)程一個(gè)CPU的邏輯核,同時(shí)處理一個(gè)任務(wù),對(duì)它來(lái)說(shuō)是最快的,多個(gè)任務(wù)同時(shí)處理反倒會(huì)讓CPU的處理變慢。
第三,測(cè)量單實(shí)例的服務(wù)能力。一個(gè)程序?qū)崿F(xiàn)得很好,可以把多核利用起來(lái)。針對(duì)這樣的實(shí)例,分配多個(gè)CPU線程、調(diào)大并發(fā)、并壓測(cè)這個(gè)的實(shí)例,試圖用10萬(wàn)個(gè)請(qǐng)求看整體處理速度,發(fā)現(xiàn)整體處理速度并沒(méi)有起多個(gè)實(shí)例,但每個(gè)實(shí)例限制CPU線程數(shù)、限制并發(fā)好。所以最終的結(jié)論是操作系統(tǒng)對(duì)于CPU的調(diào)度,比進(jìn)程要好;相比起一個(gè)大實(shí)例、接受高并發(fā)請(qǐng)求,我們更傾向于運(yùn)行多個(gè)實(shí)例、但每個(gè)實(shí)例限制并發(fā)。
增加隊(duì)列
這個(gè)主要的考慮是提高服務(wù)質(zhì)量,避免單實(shí)例過(guò)載。前面得到結(jié)論,一個(gè)圖片處理的實(shí)例,一個(gè)核,并發(fā)量為1時(shí)最快。我們?yōu)槊颗_(tái)節(jié)點(diǎn)機(jī)器加了一個(gè)排隊(duì)機(jī)制,排隊(duì)之后不爭(zhēng)搶資源,整體處理速度反而變快。
另外,從運(yùn)營(yíng)角度講,可以用隊(duì)列長(zhǎng)度來(lái)區(qū)分免費(fèi)用戶和付費(fèi)用戶。比如,可以將免費(fèi)用戶的排隊(duì)長(zhǎng)度設(shè)置得長(zhǎng)一點(diǎn),比如設(shè)成10,意味著最后一個(gè)請(qǐng)求要等前面9個(gè)請(qǐng)求處理完才能處理。而對(duì)于付費(fèi)用戶,可以將隊(duì)列長(zhǎng)度調(diào)短一點(diǎn),只有3或者5,這樣平均等待時(shí)間就變短。總原則是區(qū)別付費(fèi)用戶和免費(fèi)用戶,免費(fèi)用戶保證高可用,但是不能保證高質(zhì)量和低延遲,因?yàn)橘Y源有限;對(duì)于付費(fèi)用戶可以保證高質(zhì)量,因?yàn)榭梢酝ㄟ^(guò)排隊(duì)長(zhǎng)度控制這個(gè)事情。
限流
為什么有了隊(duì)列之后還要限流?兩個(gè)原因:
第一,大量長(zhǎng)鏈接影響FopGate性能。因?yàn)槠吲T铺幚碜疃嗟氖菆D片、音頻和視頻三種請(qǐng)求。圖片請(qǐng)求往往比較快,高峰期時(shí)可能幾秒、幾十毫秒完成,但是視頻和音頻轉(zhuǎn)碼往往比較慢,可能需要好幾分鐘或者好幾十分鐘,它取決于一個(gè)具體的轉(zhuǎn)碼參數(shù)和轉(zhuǎn)碼時(shí)長(zhǎng)。如果不限流,網(wǎng)關(guān)會(huì)維持大量的長(zhǎng)鏈接,累積大量句柄,輕則影響的性能,嚴(yán)重的情況下會(huì)造成宕機(jī)。
第二,突發(fā)流量,導(dǎo)致隊(duì)列過(guò)長(zhǎng)。隊(duì)列太長(zhǎng),有大量任務(wù)積壓的情況下,會(huì)有任務(wù)在處理之前就超時(shí)。與其超時(shí),還不如直接限流,拒絕處理不掉的請(qǐng)求。
限流手段有三種:
第一,并發(fā)HTTP請(qǐng)求限制。超過(guò)這個(gè)限制,直接拒絕請(qǐng)求并返回。但這并不是最好的方式,因?yàn)槌瑫r(shí)的請(qǐng)求已經(jīng)解析處理過(guò),這對(duì)于性能是有一定損耗的。最好的做法是用一個(gè)信號(hào)量控制TCP accept,比如控制信號(hào)量個(gè)數(shù)是1萬(wàn)個(gè),1萬(wàn)個(gè)請(qǐng)求正在并發(fā)處理時(shí)就不accept 。這是最好的方式,但實(shí)現(xiàn)略復(fù)雜。
第二,單用戶請(qǐng)求數(shù)限制。有些用戶可能會(huì)在特殊情況下發(fā)起大量的請(qǐng)求,為了不讓他影響別的用戶,系統(tǒng)會(huì)限制單個(gè)用戶的請(qǐng)求量。
第三,Cmd數(shù)限制。主要指具體某個(gè)操作,比如圖片查看,要對(duì)Cmd數(shù)進(jìn)行限制。因?yàn)椴荒茏尨罅客瑯拥腃md把資源消耗殆盡,影響其他Cmd的操作。
合理協(xié)調(diào)IO和CPU
為什么要合理協(xié)調(diào)?因?yàn)閿?shù)據(jù)處理的流程是:下載、寫(xiě)盤(pán)、處理、寫(xiě)盤(pán)、返回,涉及到網(wǎng)絡(luò)IO和磁盤(pán)IO。整個(gè)優(yōu)化方式總原則是就近計(jì)算,將下載和計(jì)算部署在一起。目前,新的架構(gòu)中是混合部署的。本來(lái)可以設(shè)計(jì),將下載部署在其他機(jī)器上,但這樣會(huì)增加一次網(wǎng)絡(luò)的路由次數(shù)。所以,從一臺(tái)機(jī)器的Agent下載后,直接在本機(jī)處理,不會(huì)再經(jīng)過(guò)一次網(wǎng)絡(luò)路由。另外一種方式是掛載ramfs,直接把下載內(nèi)容放在內(nèi)存中。比如內(nèi)存分8G,下載完成后直接放在內(nèi)存中,要用的時(shí)候直接進(jìn)內(nèi)存讀,這樣可以節(jié)約磁盤(pán)IO的開(kāi)銷,也能整體加快單個(gè)請(qǐng)求處理速度。
前面這些是官方數(shù)據(jù)處理的一些挑戰(zhàn)、架構(gòu)演化以及我們采取的一些對(duì)策,后面講一下自定義數(shù)據(jù)處理所面臨的挑戰(zhàn)。
自定義數(shù)據(jù)處理的挑戰(zhàn)
第一,處理程序由客戶提供,我們不知道客戶在程序里做了什么事情,也不知道客戶的程序會(huì)使用多少資源,這意味著我們至少要做兩點(diǎn):一是安全性,不能訪問(wèn)到別的資源,二是隔離性,單個(gè)程序不能無(wú)限制使用資源。
第二,業(yè)務(wù)規(guī)模不確定性,無(wú)法估算量有多大。這個(gè)帶來(lái)的挑戰(zhàn)是業(yè)務(wù)可伸縮性,需要客戶可控。
基于這三個(gè)需求:安全性、隔離性、可伸縮性,Docker非常適合這個(gè)業(yè)務(wù)場(chǎng)景,整個(gè)自定義數(shù)據(jù)處理在14年開(kāi)始基于Docker實(shí)現(xiàn)。
圖 5
圖5是自定義數(shù)據(jù)處理的業(yè)務(wù)流程:
第一,用戶要?jiǎng)?chuàng)建一個(gè)自定義數(shù)據(jù)處理,即注冊(cè)一個(gè)UFOP;
第二,用戶在本機(jī)上開(kāi)發(fā)自定義數(shù)據(jù)處理程序。開(kāi)發(fā)這個(gè)程序要遵循七牛UFOP范式;
第三,把這個(gè)程序提交一個(gè)構(gòu)建版本;
第四,切換到這個(gè)版本,設(shè)置實(shí)例數(shù)。實(shí)例啟動(dòng)后,該UFOP就可以訪問(wèn)了。
這是迭代的,有一個(gè)箭頭直接指回開(kāi)發(fā)自定義數(shù)據(jù)處理程序,意味著升級(jí)程序、構(gòu)建另一個(gè)新版本、切換到新版本實(shí)例的一個(gè)過(guò)程。
業(yè)務(wù)流程-注冊(cè)
圖 6
圖6是注冊(cè)的過(guò)程,第一個(gè)qufopctl是客戶端工具,第二個(gè)是reg注冊(cè),第三個(gè)ufop-demo是名字,最后-m 2是模式,支持私有和公有模式。
圖 7
圖7是自定義數(shù)據(jù)處理后端注冊(cè)的流程,qufopctl把前面描述的注冊(cè)命令,發(fā)到ufop-controller,它會(huì)進(jìn)一步走鑒權(quán)服務(wù),鑒權(quán)成功之后通過(guò)Keeper服務(wù)存盤(pán)到DB。注冊(cè)成功后,用戶開(kāi)始在本地實(shí)現(xiàn)UFOP應(yīng)用。
圖 8
圖8左邊是一個(gè)最小的UFOP代碼,簡(jiǎn)單來(lái)說(shuō)就是在UFOP請(qǐng)求路由上加一個(gè)UFOP請(qǐng)求,拿到待處理文件URL后下載對(duì)應(yīng)文件,然后獲取文件的類型和長(zhǎng)度,并作為結(jié)果返回。右上角是我們定義的一個(gè)描述性文件。2014 年,我們做的時(shí)候Docker還沒(méi)有那么火,所以沒(méi)有直接用Dockerfile,而是自己定義描述模式。第一行是引用源;第二行是構(gòu)建腳本,把外面的程序改成可寫(xiě);第三是執(zhí)行,怎么執(zhí)行這個(gè)程序。右下角是要打包成tar包的本地目錄。
業(yè)務(wù)流程-構(gòu)建
圖 9
如圖9所示為構(gòu)建命令,是把本地的程序上傳到服務(wù)端,并構(gòu)建一個(gè)版本。
圖 10
圖10是構(gòu)建的后端。整個(gè)后端的過(guò)程如下:qufopctl把程序tar包上傳到Kodo,發(fā)起構(gòu)建請(qǐng)求,再把構(gòu)建請(qǐng)求轉(zhuǎn)發(fā)到構(gòu)建機(jī)器,接著把UFOP描述文件轉(zhuǎn)化為Dockerfile,基于Dockerfile構(gòu)建Docker image,最后推送到Docker Registry。
下面是構(gòu)建后端我們踩過(guò)的一些小坑。
使用Debian鏡像服務(wù)
原先使用AppRox,是Debian包下載、緩存服務(wù),但實(shí)際上經(jīng)常下載超時(shí),而且下載出錯(cuò)后,自己沒(méi)辦法辨別本地文件存在問(wèn)題,需要手動(dòng)清除,比較糟糕。后來(lái),搭建了一個(gè)鏡像源。鏡像源的做法是首次全量下載,全部下載完畢后,設(shè)置一個(gè)定時(shí)增量同步的時(shí)間,在凌晨,一天一次,每天更新的量只有幾十兆,幾分鐘便可完成。從此,再也沒(méi)有出現(xiàn)過(guò)這方面的問(wèn)題。
避免Docker構(gòu)建緩存
圖 11
Docker的構(gòu)建緩存比較容易出錯(cuò)。圖11第一個(gè)是錯(cuò)誤用法:第一步,下載一個(gè)jdk的壓縮包;第二步,創(chuàng)建一個(gè)目錄,將壓縮包解壓到這個(gè)目錄,并且把原來(lái)的壓縮包刪除。分了兩條命令,但是容器其實(shí)會(huì)對(duì)每一條命令做緩存。
假如我們第一次運(yùn)行這兩條命令時(shí)是沒(méi)有問(wèn)題的。第二次運(yùn)行時(shí),我們覺(jué)得第二條命令中OPT目錄不好,想到另外一個(gè)目錄,于是對(duì)第二條語(yǔ)句做了更改,那么就會(huì)出問(wèn)題。為什么?因?yàn)榈谝粭l命令沒(méi)有任何變化,所以容器構(gòu)建系統(tǒng)認(rèn)為,沒(méi)有任何的變化就不去執(zhí)行,于是直接跑第二條命令,第二條在前一次執(zhí)行時(shí),已經(jīng)將壓縮包刪除,因此會(huì)跑失敗。這種錯(cuò)誤很容易犯,解決方法是把壓縮包的下載、目錄的創(chuàng)建、解壓縮和刪除壓縮包,都放在同一條命令里。當(dāng)這條命令被修改后,每次都會(huì)重新執(zhí)行,就不會(huì)出現(xiàn)這個(gè)問(wèn)題了。
調(diào)整實(shí)例數(shù)
圖 12
圖 13
接下來(lái)是調(diào)整實(shí)例數(shù),前面已經(jīng)構(gòu)建完成,程序已經(jīng)上傳到服務(wù)器端。qufopctl resize ufop-demo -n 3,這條命令會(huì)增加3個(gè)實(shí)例。
整個(gè)后端的過(guò)程如圖13所示,qufopclt發(fā)送請(qǐng)求到ufop-controller,中心調(diào)度器Scheduler下面有很多個(gè)node,運(yùn)行著我們實(shí)現(xiàn)的Daemon服務(wù),所有容器都是由Scheduler下發(fā)給某個(gè)Daemon,這些Daemon啟動(dòng)對(duì)應(yīng)的容器。Daemon會(huì)把所在機(jī)器剩余資源的情況,包括CPU、內(nèi)存和磁盤(pán),實(shí)時(shí)報(bào)給Scheduler,Scheduler會(huì)根據(jù)實(shí)例的規(guī)格要求找到相應(yīng)滿足要求的node。這些容器實(shí)例創(chuàng)建成功后,Daemon會(huì)把具體的端口信息返回到Scheduler,Scheduler再通過(guò)Keeper服務(wù)持久化,這樣就結(jié)束了。Docker Registry是Docker的鏡像倉(cāng)庫(kù)。
升級(jí)實(shí)例
圖 14
到前面這一步,UFOP已經(jīng)運(yùn)行起來(lái)并且可以使用,如圖14所示為升級(jí)實(shí)例的過(guò)程。我們有一個(gè)Upgrade的命令,-r是一個(gè)實(shí)例,現(xiàn)在要做的是升級(jí)前兩個(gè)實(shí)例,后端會(huì)發(fā)生什么事情呢?
圖 15
圖15所示為一個(gè)灰度升級(jí)階段。首先原始階段有三個(gè)實(shí)例,假設(shè)每個(gè)版本都是V1,現(xiàn)在要升級(jí)兩個(gè)實(shí)例,后端的做法是增加兩個(gè)實(shí)例,實(shí)例4和實(shí)例5,這兩個(gè)對(duì)應(yīng)的版本是V2,圖15中橙色部分。等V4和V5徹底被啟動(dòng)后,我們將老的實(shí)例刪除,它的結(jié)果是原來(lái)的一個(gè)V1, 兩個(gè)V2,整體灰度升級(jí)過(guò)程就是這樣子。
有些細(xì)節(jié)值得注意:
第一,新實(shí)例WarmUp,往往剛開(kāi)始很多內(nèi)部組件沒(méi)有初始化,像內(nèi)存池、線程池、連接池需要初始化,所以初始請(qǐng)求處理得往往比較慢,但是又不能不發(fā)請(qǐng)求,因?yàn)椴话l(fā)請(qǐng)求永遠(yuǎn)熱不起來(lái)。做法是設(shè)定預(yù)熱時(shí)間段,定時(shí)間段的權(quán)重,保證在這個(gè)時(shí)間段預(yù)熱好之后就承擔(dān)正常的流量。
第二,老實(shí)例CoolDown。如果直接刪除老實(shí)例,對(duì)服務(wù)的可用性沒(méi)有影響,因?yàn)槔系恼?qǐng)求正在被處理。做法是:使用Docker StopWait,當(dāng)用Docker Stop停止一個(gè)容器時(shí),它默認(rèn)的行為是先發(fā)一個(gè)SIGTERM,如果不指定StopWait時(shí)間,就會(huì)馬上發(fā)一個(gè)SIGKILL信號(hào),這樣你的容器將被直接殺死。若一個(gè)容器正在處理請(qǐng)求,那么我們希望能有一段時(shí)間讓我們將請(qǐng)求處理完后,優(yōu)雅的關(guān)閉,否則會(huì)影響可用性。所以使用這個(gè)命令時(shí),可以設(shè)置StopWait時(shí)間,若等待超過(guò)設(shè)置的時(shí)間,卻發(fā)現(xiàn)容器沒(méi)有優(yōu)雅關(guān)閉,再發(fā)SIGKILL信號(hào)。另外在業(yè)務(wù)層面,老實(shí)例在CoolDown時(shí),應(yīng)該設(shè)成一個(gè)關(guān)閉中的狀態(tài),避免新的請(qǐng)求再打進(jìn)去。
第三,保留足夠的計(jì)算冗余。這個(gè)是如何考慮的呢?因?yàn)樯?jí)需要考慮步長(zhǎng),如果升級(jí)的步長(zhǎng)大于計(jì)算的冗余實(shí)例數(shù),意味著剩余的等待實(shí)例會(huì)承擔(dān)更多的請(qǐng)求,多于預(yù)期的請(qǐng)求會(huì)影響服務(wù)的質(zhì)量,因?yàn)檎?qǐng)求的時(shí)間會(huì)變長(zhǎng)。所以選用的升級(jí)步長(zhǎng)應(yīng)該小于冗余的實(shí)例數(shù)。
數(shù)據(jù)流
圖 16
剛才講的是控制流,包括如何注冊(cè)、如何創(chuàng)建一個(gè)新的實(shí)例。而這些數(shù)據(jù)流的請(qǐng)求過(guò)來(lái)是什么樣的?這涉及到一些內(nèi)部組件,即云存儲(chǔ)的服務(wù)器。服務(wù)器后面有數(shù)據(jù)處理,自定義數(shù)據(jù)處理會(huì)從之前說(shuō)的狀態(tài)服務(wù)中獲取某一個(gè)后端實(shí)例列表,由它做負(fù)載均衡傳給后端。在后端數(shù)據(jù)流的維度上,每臺(tái)機(jī)器還有一個(gè)Fetcher,它接收到請(qǐng)求后會(huì)把請(qǐng)求路由到本機(jī),并執(zhí)行實(shí)例。同時(shí),它會(huì)做數(shù)據(jù)下載的工作,我們出于對(duì)用戶隱私安全的考慮做了一些混淆,不允許他直接下載,而是轉(zhuǎn)化成本地的。這是數(shù)據(jù)流的流程。右邊有一個(gè)組件叫DiskCache,是一個(gè)緩存集群。
圖 17
圖17是數(shù)據(jù)鏈路的V2版本,是一個(gè)思路,還沒(méi)有完全實(shí)現(xiàn)。唯一的改動(dòng)是在實(shí)例之間加了一個(gè)隊(duì)列,當(dāng)然這個(gè)隊(duì)列是可選的。當(dāng)前所有請(qǐng)求都放在這個(gè)隊(duì)列中,由UFOP實(shí)例獲取請(qǐng)求,處理完成后將結(jié)果返回,這是一步處理的過(guò)程。這個(gè)隊(duì)列有什么作用?前面提到,調(diào)整實(shí)例可以做手動(dòng)伸縮,沒(méi)有說(shuō)自動(dòng)伸縮。而這個(gè)隊(duì)列可以做自動(dòng)伸縮。
自動(dòng)伸縮設(shè)置
自動(dòng)伸縮需要用戶做一些配置,一個(gè)是默認(rèn)的實(shí)例數(shù),也就是第一次用戶上傳一個(gè)自定義數(shù)據(jù)處理的版本,上傳完成后調(diào)整實(shí)例數(shù),調(diào)整成10個(gè),還要設(shè)置一個(gè)平均單實(shí)例待處理任務(wù)數(shù)的配置,假如,這個(gè)設(shè)置是10,當(dāng)隊(duì)列里面有小于100個(gè)待處理任務(wù)數(shù)時(shí)是不需要伸縮的,但是當(dāng)隊(duì)列里面的任務(wù)數(shù)大于100,比如到110就要伸縮了,因?yàn)閱蝹€(gè)實(shí)例平均待處理的任務(wù)數(shù)已經(jīng)超過(guò),這個(gè)時(shí)候再增加一個(gè)實(shí)例是最適合的選擇。通過(guò)對(duì)隊(duì)列的監(jiān)控,可以達(dá)到自動(dòng)伸縮。
自動(dòng)伸縮的后端
圖 18
圖18是自動(dòng)伸縮的后端。最上面中間有一個(gè)Scaler組件,會(huì)實(shí)時(shí)監(jiān)控隊(duì)列長(zhǎng)度,拿到每個(gè)隊(duì)列的配置,即平均單任務(wù)待處理任務(wù)數(shù)。它根據(jù)這兩個(gè)信息,可以實(shí)時(shí)地發(fā)出調(diào)整實(shí)例的請(qǐng)求,比如平均單任務(wù)處理數(shù)超過(guò)預(yù)想時(shí),它可以自動(dòng)增加一個(gè)實(shí)例,并告訴調(diào)度器,調(diào)度器會(huì)找相應(yīng)的節(jié)點(diǎn)啟動(dòng)實(shí)例,啟動(dòng)后告訴Keeper,Keeper會(huì)把這些信息記錄下來(lái)。回到前面的數(shù)據(jù)流,及時(shí)從里面獲取信息,達(dá)到自動(dòng)伸縮的目的。
如何應(yīng)對(duì)自定義數(shù)據(jù)處理的挑戰(zhàn)
解決方案:
第一,安全性。這一部分做法比較簡(jiǎn)單。自定義數(shù)據(jù)處理單個(gè)物理機(jī)上的容器數(shù)約幾十個(gè),這與CPU的核數(shù)有關(guān)。可以設(shè)置某個(gè)范圍的端口不互訪,以達(dá)到容器不能互訪的目的,從而獲得安全性;
第二,隔離性。可以限定某一個(gè)容器只用指定配額的CPU和內(nèi)存,這取決于用戶的配置;
第三,可伸縮性。首先實(shí)現(xiàn)了一個(gè)簡(jiǎn)單高效的容器調(diào)度系統(tǒng),它是支持秒級(jí)伸縮的;其次是暴露伸縮API,用戶可以手動(dòng)伸縮達(dá)到伸縮目的;最后是利用隊(duì)列長(zhǎng)度,達(dá)到自動(dòng)伸縮的目的。
總結(jié)
以上是生活随笔為你收集整理的日均请求量百亿级数据处理平台的容器云实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C\C++网络编程总结
- 下一篇: 目标检测简要综述