最近在做系統(tǒng)升級(jí),由于當(dāng)時(shí)設(shè)計(jì)的局限,導(dǎo)致系統(tǒng)不停服,保證服務(wù)的做法非常麻煩。當(dāng)時(shí)再定方案的時(shí)候,由于自己在這方面沒(méi)有經(jīng)驗(yàn),導(dǎo)致有些樂(lè)觀。到了實(shí)際做的時(shí)候,預(yù)期時(shí)間至少比預(yù)想的多了一周的時(shí)間,要知道,在互聯(lián)網(wǎng)公司,一周的時(shí)間是個(gè)非常長(zhǎng)的時(shí)間。而這一周,還包括了OT。
在這里總結(jié)一下分布式系統(tǒng)設(shè)計(jì)的大忌,本來(lái)想試著分一下級(jí),但是還是算了,一來(lái)標(biāo)準(zhǔn)太多,無(wú)法制定一個(gè)合適的規(guī)則來(lái)界定;二來(lái)自己的經(jīng)驗(yàn)也在增長(zhǎng),低調(diào)一下是自己也沒(méi)詳細(xì)的研究過(guò)超過(guò)5個(gè)分布式系統(tǒng);三來(lái)做事情還是要嚴(yán)謹(jǐn),不做沒(méi)有十足把握的事情。
1. 忽視服務(wù)接口的設(shè)計(jì)
雖然大家口口聲聲說(shuō)對(duì)于一個(gè)集群來(lái)說(shuō),每臺(tái)機(jī)器都可能出故障。但是做方案設(shè)計(jì)的時(shí)候,某些資源卻向用戶直接暴漏了服務(wù)的實(shí)際地址。對(duì)于一個(gè)服務(wù)幾年的服務(wù)器來(lái)說(shuō),故障的可能性非常大,尤其是如果這個(gè)服務(wù)器的平時(shí)負(fù)載比較高的話。我不清楚一臺(tái)服務(wù)器的平均保修時(shí)間是多少,但是絕對(duì)不可能是幾個(gè)小時(shí)能搞定的,這個(gè)時(shí)間少則一天,多則半個(gè)月甚至更長(zhǎng)。對(duì)于一些高級(jí)的用戶,它會(huì)使用本地的cache,或者其他的策略來(lái)屏蔽調(diào)用服務(wù)不可用帶來(lái)的影響,但是,幾天的停服對(duì)于用戶方的影響是無(wú)論如何不可能忽略的。
這種問(wèn)題發(fā)現(xiàn)后,可能簡(jiǎn)單的發(fā)布一個(gè)新版本的api,或者一個(gè)簡(jiǎn)單的配置文件就可以糾正。但是對(duì)于線上用戶來(lái)說(shuō),他們運(yùn)行的是一個(gè)一直都在running狀態(tài)的服務(wù)。這個(gè)簡(jiǎn)單的改正可能需要他們服務(wù)重啟,這對(duì)于一個(gè)大型的集群來(lái)說(shuō),帶來(lái)的成本非常高。如果是因?yàn)檫@個(gè)服務(wù)的不可用導(dǎo)致了線上事故,那么應(yīng)用方肯定會(huì)非常主動(dòng)的去修正這個(gè)錯(cuò)誤。但是如果使用架構(gòu)方發(fā)現(xiàn)了這個(gè)問(wèn)題,而主動(dòng)推動(dòng)應(yīng)用方去修改,可能應(yīng)用方會(huì)因?yàn)楦鞣N原因而推脫。
因此,設(shè)計(jì)服務(wù)的接口一定要注意,這個(gè)接口一定要是穩(wěn)定的,而且后臺(tái)服務(wù)的故障,升級(jí)等操作絕對(duì)對(duì)于用戶要是透明的。不要將服務(wù)的實(shí)際地址暴漏給用戶方:這臺(tái)服務(wù)器終有一天會(huì)掛掉。尤其是對(duì)于C++等需要編譯的api來(lái)說(shuō),這個(gè)接口就更加重要了。畢竟api的修改對(duì)于應(yīng)用方來(lái)說(shuō)意味著要重新編譯;重新編譯意味著要重新走一下發(fā)布流程:至少要提測(cè)吧。
2. 后臺(tái)升級(jí)對(duì)用戶不透明
這實(shí)際上是又是一句大家都知道的。但是設(shè)計(jì)時(shí)確實(shí)有時(shí)候會(huì)忽略。對(duì)于彈性計(jì)算系統(tǒng)來(lái)說(shuō),服務(wù)的伸縮是必須的,這個(gè)也是設(shè)計(jì)的目標(biāo)之一。但是對(duì)于一些小規(guī)模的計(jì)算集群來(lái)說(shuō),可能大家認(rèn)為伸縮不是最重要的feature。最重要的feature就是能夠快速的完成系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn),為用戶服務(wù)。但是實(shí)際上,這個(gè)通過(guò)一些簡(jiǎn)單的修改,就可以完成:Worker上帶一個(gè)agent和master或者meta server通信,保持心跳。心跳超時(shí)的Worker會(huì)被下線,以后的服務(wù)都不會(huì)發(fā)送到這個(gè)Worker上來(lái)。而新加入的Worker則會(huì)加入集群接收計(jì)算任務(wù)。這個(gè)不單是應(yīng)對(duì)服務(wù)的伸縮,也是為了應(yīng)對(duì)機(jī)器的故障。因此不用太大的改動(dòng),就可以將一個(gè)系統(tǒng)從山寨提升到真正的可用。
一個(gè)系統(tǒng)的服務(wù)質(zhì)量,不是說(shuō)在一般情況下的服務(wù)是可靠的,除了網(wǎng)絡(luò)丟包、網(wǎng)絡(luò)傳輸造成的問(wèn)題外,服務(wù)質(zhì)量可以做到10000個(gè)請(qǐng)求至多有1個(gè)失敗就是說(shuō)這個(gè)系統(tǒng)是可用的。評(píng)價(jià)服務(wù)質(zhì)量的另外一個(gè)重要指標(biāo)是全年可服務(wù)時(shí)間。這個(gè)要將機(jī)器故障,機(jī)房故障考慮在內(nèi)。如果依賴于運(yùn)行環(huán)境沒(méi)有問(wèn)題,才能達(dá)到99.99,那么這個(gè)服務(wù)就有點(diǎn)山寨,對(duì)于重要的應(yīng)用方來(lái)說(shuō),這種服務(wù)不可接受。
3. 應(yīng)用方設(shè)計(jì)時(shí)未衡量后臺(tái)服務(wù)失敗的影響
如果服務(wù)的可靠性要求非常高,比如是直接面向互聯(lián)網(wǎng)用戶的,要求任何時(shí)間都能夠?qū)ヂ?lián)網(wǎng)用戶提供服務(wù),那么就需要在調(diào)用服務(wù)時(shí)做下服務(wù)不可用的預(yù)案。甚至做下超時(shí)機(jī)制:如果服務(wù)調(diào)用指定時(shí)間不返回,那么需要有其余的邏輯來(lái)替代。
當(dāng)然了本次還遇到很多其他的痛點(diǎn),每個(gè)都是設(shè)計(jì)上得小瑕疵,當(dāng)時(shí)注意的話不會(huì)增加工作量,或者增加很少的工作量就可以做到可用?;ヂ?lián)網(wǎng)強(qiáng)調(diào)快,那么底線應(yīng)該是可用吧。易用可能是更要的要求。當(dāng)然了這個(gè)可能可以一種互聯(lián)網(wǎng)風(fēng)格,就是一個(gè)事情可以快速做完,快速上線。當(dāng)時(shí)上線時(shí)候也做了二期需要做的改進(jìn),但是后臺(tái)發(fā)現(xiàn)上線效果好,符合預(yù)期。又去做其它高優(yōu)先級(jí)的事情去了。導(dǎo)致原來(lái)設(shè)計(jì)的局限就永遠(yuǎn)的停留在那里了,這就是為后來(lái)人埋下一個(gè)坑。。
本次升級(jí)的時(shí)候,由于信息的不一致導(dǎo)致一臺(tái)服務(wù)器停服,導(dǎo)致大面積的失敗。后來(lái)為了避免其它的集群出現(xiàn)類似的問(wèn)題,因此所有的信息都重新確認(rèn)了一遍。而這帶來(lái)了半天的枯燥工作。因此,自己做設(shè)計(jì)的時(shí)候,一定要注意,不求最好,但求可用,在機(jī)器故障,服務(wù)升級(jí),對(duì)于用戶來(lái)說(shuō),服務(wù)都可用。
BTW,正在做一個(gè)架構(gòu)的設(shè)計(jì),細(xì)節(jié)是魔鬼,正在和魔鬼做斗爭(zhēng)。