雪球首席架構(gòu)師唐福林:雪球服務(wù)化實(shí)踐歷程
原創(chuàng)服務(wù)化的話題在兩三年前很熱,眾多公開場(chǎng)合都在說(shuō),最開始是亞馬遜、Twitter,緊接著就是國(guó)內(nèi)的淘寶、微博都在談服務(wù)化。在這之后,感覺(jué)這個(gè)話題慢慢趨向過(guò)時(shí),之所以有這樣的感覺(jué)一是大公司或因人員流動(dòng)或其他各種關(guān)系大家做的服務(wù)化都大致相似,二是當(dāng)下并沒(méi)有大量的創(chuàng)業(yè)公司有這樣需求。其實(shí)每年都會(huì)有一些正在從小到大的成長(zhǎng),這個(gè)過(guò)程中總會(huì)碰到服務(wù)化的問(wèn)題,是繞不過(guò)的。
當(dāng)一些初創(chuàng)公司遇到人員、業(yè)務(wù)、流量等膨脹之時(shí),還是需要有類似的解決方案來(lái)借鑒。遇到這樣的問(wèn)題,如何解決,馬上解決還是緩一緩再做。每當(dāng)這個(gè)時(shí)候,看淘寶怎么做,微博怎么做其實(shí)并不適合初創(chuàng)公司的場(chǎng)景。因?yàn)樗媾R的問(wèn)題不一樣,如人數(shù),背景做事方式等都有所不同。在由51CTO高招主辦的“CTO訓(xùn)練營(yíng)”活動(dòng)現(xiàn)場(chǎng),雪球首席架構(gòu)師唐福林分享了其公司在面對(duì)這個(gè)問(wèn)題的時(shí)候是如何做的。他表示,這其實(shí)痛定思痛或說(shuō)是反思。雪球的解決方案也并不是很理想,但可以給大家做一個(gè)前車之鑒。
關(guān)于雪球,關(guān)于唐福林
演講開始,唐福林簡(jiǎn)單介紹了雪球的發(fā)展和自身的經(jīng)歷。
雪球,一個(gè)聰明的投資者的社區(qū),有Web1.0:新聞資訊,股價(jià)信息,K線圖、Web2.0:SNS 訂閱,分享,聊天、Web3.0:移動(dòng)APP,交易閉環(huán)等業(yè)務(wù),還有非互聯(lián)網(wǎng)業(yè)務(wù),如做資產(chǎn)管理,私募工場(chǎng),是一個(gè)典型的創(chuàng)業(yè)公司。雪球當(dāng)前員工數(shù)剛好過(guò)100,其中技術(shù)人員占50%?,F(xiàn)在的技術(shù)棧由Java,Scala,Akka,F(xiàn)inagle,Nodejs,Docker ,Hadoop組件組成。當(dāng)前是租用IDC機(jī)房自建私有云,正在往“公私混合云”方向發(fā)展。
唐福林,雪球首席架構(gòu)師,負(fù)責(zé)雪球大數(shù)據(jù)體系建設(shè)及服務(wù)性能與穩(wěn)定架構(gòu)優(yōu)化工作。曾任微博平臺(tái)資深架構(gòu)師,微博技術(shù)委員會(huì)成員,深度參與微博快速增長(zhǎng)期的性能和穩(wěn)定性問(wèn)題解決。
雪球服務(wù)化歷程
在講雪球服務(wù)化歷程之前,唐福林簡(jiǎn)單介紹了雪球公司業(yè)務(wù)的發(fā)展歷程,如下圖:
服務(wù)化歷程之雪球技術(shù)發(fā)展
上圖為,以2012年初為基準(zhǔn),雪球的團(tuán)隊(duì)人數(shù),服務(wù)個(gè)數(shù)和代碼行數(shù)的增長(zhǎng)趨勢(shì)。
服務(wù)化歷程之技術(shù)演進(jìn)
唐福林表示,最初整個(gè)雪球服務(wù)是在一個(gè)大一統(tǒng)的工程里實(shí)現(xiàn),內(nèi)部命名為Snowball ,就是滾雪球的意思。 Snowball系統(tǒng)從 2012年到2013年初一直運(yùn)轉(zhuǎn)良好。但隨著2013年業(yè)務(wù)的膨脹,代碼的增長(zhǎng),團(tuán)隊(duì)的擴(kuò)張,漸漸出現(xiàn)了很多問(wèn)題,比如重復(fù)代碼,比如代碼不夠規(guī)范,比如測(cè)試?yán)щy,比如溝通成本越來(lái)越高,比如不相干的功能在實(shí)現(xiàn)上存在耦合等。
- 針對(duì)業(yè)務(wù)膨脹。開始了模塊化改造,將底層基礎(chǔ)模塊抽取成公共庫(kù),做到代碼級(jí)的服用;
- 針對(duì)代碼量增長(zhǎng)過(guò)快。采取了一種在國(guó)內(nèi)互聯(lián)網(wǎng)公司不太常見(jiàn)的措施:引入一種描述能力更強(qiáng)的語(yǔ)言 scala。簡(jiǎn)單來(lái)說(shuō),它是一種 jvm 上的混合語(yǔ)言,混合了面向?qū)ο缶幊毯秃瘮?shù)式編程兩種方式,它的編譯器其實(shí)就是一個(gè) jar 包,源碼會(huì)被編譯成跟 java 一樣的 bytecode,然后在 jvm 上運(yùn)行。在 scala 中,可以無(wú)縫的調(diào)用絕大多數(shù) java 的庫(kù)。scala 語(yǔ)言的描述能力很強(qiáng),平均下來(lái),同樣的邏輯,scala 語(yǔ)言實(shí)現(xiàn)大概會(huì)是 java 實(shí)現(xiàn)長(zhǎng)度的 1/5 到 1/10 的樣子。
- 針對(duì)團(tuán)隊(duì)的擴(kuò)張。開始推行一種工程師文化:鼓勵(lì)大家使用新的更好的技術(shù)和工具,鼓勵(lì)大家制造更多的工具和輪子,鼓勵(lì)大家交流分享。
唐福林在演講中說(shuō)到:“在那個(gè)時(shí)候,推行工程師文化的兩個(gè)重大結(jié)果,一是在線上服務(wù)和基礎(chǔ)設(shè)施層引入了 scala,二是在基礎(chǔ)設(shè)施層引入了 docker 。這兩個(gè)決策在現(xiàn)在看來(lái),當(dāng)時(shí)的引入肯定是沒(méi)有經(jīng)過(guò)深思熟慮的,后來(lái)的一路上也是踩了不少坑,當(dāng)然也付出了很大的時(shí)間和精力代價(jià)。但是當(dāng)回過(guò)頭去看的時(shí)候,還是很慶幸引入了這些基礎(chǔ)設(shè)施,它們既幫助雪球完成了功能,方便了部署,也幫助雪球在技術(shù)上有了積累,在團(tuán)隊(duì)上有了進(jìn)步”。
隨著時(shí)間的推移,雖然采取了上述一系列的措施,問(wèn)題有了一定程度的緩解。但隨著業(yè)務(wù)繼續(xù)加速膨脹,代碼加速增長(zhǎng),團(tuán)隊(duì)加速擴(kuò)展,問(wèn)題還是不可避免的越來(lái)越嚴(yán)重。這時(shí)候雪球到了一個(gè)大的關(guān)口:流量增長(zhǎng)到一定程度,代碼模塊之間開始互相影響,一個(gè)模塊的性能問(wèn)題很快擴(kuò)散到影響全站訪問(wèn),git 分支合并開始頻繁出現(xiàn)沖突,開發(fā)迭代速度明顯受影響。另外一個(gè)比較嚴(yán)重的問(wèn)題是,不同的模塊帶進(jìn)來(lái)的第三方依賴偶爾產(chǎn)生沖突,解決起來(lái)很麻煩。面對(duì)這樣的嚴(yán)重的問(wèn)題,雪球很對(duì)采取了進(jìn)一步的對(duì)癥下藥:
- 對(duì)穩(wěn)定性,性能互相影響的問(wèn)題,標(biāo)準(zhǔn)解法是切分流量單獨(dú)部署
- 代碼合并沖突,第三方依賴的標(biāo)準(zhǔn)解法就是:服務(wù)化拆分。
唐福林在演講中說(shuō)到:“對(duì)于像雪球這樣的小公司,服務(wù)器不多,服務(wù)化拆分后會(huì)嚴(yán)重增加部署成本,包括線上和測(cè)試環(huán)境。針對(duì)這個(gè)問(wèn)題,當(dāng)時(shí)采取的辦法是:Docker 容器化?,F(xiàn)在大家可能覺(jué)得這也是一個(gè)標(biāo)準(zhǔn)解法了。但在兩年前,Docker 的版本號(hào)還小于 1.0,這樣的選擇,不能不說(shuō)是具有相當(dāng)?shù)那罢靶缘?rdquo;。
服務(wù)化歷程之服務(wù)化框架選擇
做服務(wù)化,就面臨一個(gè)服務(wù)化框架的問(wèn)題。自己開發(fā)的選項(xiàng)是早早就被放棄了,畢竟公司所有技術(shù)人員加起來(lái),都不如淘寶開發(fā) dubbo 的團(tuán)隊(duì)人多。 選一個(gè)現(xiàn)有的?因?yàn)橐呀?jīng)引入了部分 scala 業(yè)務(wù)代碼,rpc 框架也必須要支持 scala 才行。理論上,所有純粹的 java rpc 框架,scala 也都能用,但是,想要以純粹的 scala 的方式寫代碼的話,調(diào)用java方法和處理java的參數(shù),返回值對(duì)象的時(shí)候,都需要轉(zhuǎn)一下才行。另外一個(gè)考慮因素就是,這個(gè)框架必須是開源的,經(jīng)歷過(guò)大廠驗(yàn)證過(guò)的。最后,選定了 finagle 。
服務(wù)化歷程 - Finagle 介紹
Finagle支持多協(xié)議適配,對(duì) client 端和 server 端來(lái)說(shuō),它具備標(biāo)準(zhǔn)的連接池,失敗檢測(cè)重試,負(fù)載均衡,監(jiān)控統(tǒng)計(jì),追蹤,分區(qū) etc。
它的編程模型如下:
- 所有的客戶端操作都返回一個(gè) Future,也就是說(shuō),所有操作都是異步的,可以往 Future 里面放 callback 回調(diào),也可以把多個(gè) Future 串起來(lái)。
- 所有的服務(wù)抽象成一個(gè)個(gè)的 Service:每個(gè) service 的輸入都是接收一個(gè) request,返回都是一個(gè) Future[Response]。
- 所有的策略實(shí)現(xiàn)都是一個(gè)個(gè)的 Filter,F(xiàn)ilter 是包裝在 service 外面的。
服務(wù)化歷程之嘗試、推廣、升級(jí)、服務(wù)治理、收尾
唐福林表示,F(xiàn)nagle看起來(lái)功能強(qiáng)大,又非常符合當(dāng)時(shí)的各種期望。于是,就引入雪球。之后經(jīng)過(guò)嘗試、推廣、升級(jí)、服務(wù)治理和收尾等環(huán)節(jié),直到2015年9月,F(xiàn)inagle架構(gòu)如下如:
2015年9月 Finagle架構(gòu)圖
未來(lái)與微服務(wù)化
當(dāng)前這個(gè)方案最大的問(wèn)題,還是在于開發(fā)團(tuán)隊(duì)的hold程度,簡(jiǎn)單來(lái)說(shuō),Scala是一門會(huì)用不難,會(huì)用好還是挺難的編程語(yǔ)言,所以,用它寫業(yè)務(wù)邏輯問(wèn)題不大,但用它來(lái)寫基礎(chǔ)設(shè)施,那就需要一個(gè)精煉的技術(shù)小組才能搞定了。而 finagle 呢,Twitter 的那些開源代碼開發(fā)人員,那是相當(dāng)?shù)撵偶?,有的時(shí)候,團(tuán)隊(duì)里對(duì) finagle 最精通的人,也會(huì)忍不住連連贊同。
唐福林演講中說(shuō)到:“雪球的 scala 技術(shù)團(tuán)隊(duì)免不了有一些人員更替,有轉(zhuǎn)產(chǎn)品的,有轉(zhuǎn)管理的,有轉(zhuǎn)去做另外的業(yè)務(wù)項(xiàng)目的,導(dǎo)致后面的框架升級(jí)和二次開發(fā)力量嚴(yán)重不足。加上 finagle 自己迭代速度快,向后兼任又差,整個(gè)一個(gè) no zuo no die why you try 的感覺(jué)”。于是,唐福林個(gè)人花了差不多兩周的時(shí)間,做了一個(gè)簡(jiǎn)單版本 rpc 框架的嘗試。得益于在微博做 motan 框架的經(jīng)驗(yàn)和教訓(xùn),框架開發(fā)很快,開發(fā)出來(lái)后,拿給整個(gè)技術(shù)團(tuán)隊(duì)做討論的時(shí)候,才發(fā)現(xiàn)問(wèn)題很多:再后來(lái),團(tuán)隊(duì)在針對(duì) rpc 框架的接下來(lái)需求的討論過(guò)程中,越討論越覺(jué)得方向有一些偏:大家對(duì)基礎(chǔ)設(shè)施需求的重點(diǎn)并不是在 rpc 調(diào)用框架,而更多在于:大量的小服務(wù),開發(fā)業(yè)務(wù)邏輯的便捷性,升級(jí)基礎(chǔ)包的便捷性,單節(jié)點(diǎn)的運(yùn)行狀態(tài),數(shù)據(jù)收集,監(jiān)控報(bào)警的便捷性等等。于是,在未來(lái),會(huì)把接下來(lái)服務(wù)化工作的重點(diǎn)定義成:微服務(wù)化,具體來(lái)說(shuō),就是開發(fā)并維護(hù)一個(gè)滿足雪球自己業(yè)務(wù)需要的微服務(wù)容器。
思考和教訓(xùn)
當(dāng)服務(wù)到了一定程度,做服務(wù)化是肯定的。但不建議自己做服務(wù)化框架,可以找一個(gè)比較成熟一點(diǎn)的東西來(lái)做。穩(wěn)定性和可用性是一個(gè)最重要的工作。做服務(wù)化拆分時(shí)會(huì)引起穩(wěn)定性和可用性下降,更何況如果拆了很多個(gè)不同的服務(wù),由不同的人去維護(hù),很容易出問(wèn)題,所以一定要重視單個(gè)節(jié)點(diǎn)的一致性。 可以嘗試新技術(shù),但要保證技術(shù)先進(jìn)性與技術(shù)棧一致性。之后,唐福林還從技術(shù)深度與技術(shù)新鮮度、團(tuán)隊(duì)擴(kuò)張和成員更替、個(gè)人興趣和團(tuán)隊(duì)合作等方面分享了很多寶貴的經(jīng)驗(yàn)。
在演講最后,唐福林提到了細(xì)節(jié)和規(guī)范。他說(shuō):“想要用好一個(gè)框架,有很多細(xì)節(jié)需要仔細(xì)注意的。如 finagle 的重試邏輯,跟我們平常說(shuō)的不太一樣,retry=3 的時(shí)候,并不是重試三次,而是加上第一次嘗試,一共三次,也就是說(shuō)重試2次。 在使用開源框架的時(shí)候,首先遵守框架本身的規(guī)范,開源社區(qū)的規(guī)范,然后在這個(gè)基礎(chǔ)上,制定自己(小團(tuán)隊(duì))的規(guī)則,或者叫使用約定。規(guī)則成熟后,最后形成固定的(公司大團(tuán)隊(duì))的規(guī)定。”
了解更多訓(xùn)練營(yíng)內(nèi)容:http://x.51cto.com