开源项目使用经验原则
軟件開(kāi)發(fā)領(lǐng)域有一個(gè)流行的原則:DRY,Don’t?repeat?yourself,我們翻譯過(guò)來(lái)更形象通俗:不要重復(fù)造輪子。開(kāi)源項(xiàng)目主要目的是共享,其實(shí)就是為了讓大家不要重復(fù)造輪子,尤其是在互聯(lián)網(wǎng)這樣一個(gè)快速發(fā)展的領(lǐng)域,速度就是生命,引入開(kāi)源項(xiàng)目,可以節(jié)省大量的人力和時(shí)間,大大加快業(yè)務(wù)的發(fā)展速度,何樂(lè)而不為呢?
?
然而現(xiàn)實(shí)往往沒(méi)有那么美好,開(kāi)源項(xiàng)目雖然節(jié)省了大量的人力和時(shí)間,但帶來(lái)的問(wèn)題也不少,相信絕大部分同學(xué)都踩過(guò)開(kāi)源軟件的坑,小的影響可能是宕機(jī)半小時(shí),大的問(wèn)題可能是丟失幾十萬(wàn)數(shù)據(jù),甚至災(zāi)難性的事故是全部數(shù)據(jù)都丟失。
?
除此以外,雖然DRY原則擺在那里,但實(shí)際上開(kāi)源項(xiàng)目反而是最不遵守DRY原則的,重復(fù)的輪子好多,尤其是歪果仁,一看哪個(gè)開(kāi)源方案不爽,自己就吭哧吭哧搞一個(gè)差不多的:你有MySQL,我有PostgreSQL;你有MongoDB,我有Cassandra;你有memcached,我有redis;你有Gson,我有Jackson;你有Angular,我有React。。。。。。總之放眼望去,其實(shí)相似的輪子很多!相似輪子太多,選擇就是讓人頭疼的問(wèn)題了。
?
怎么辦?完全不用開(kāi)源項(xiàng)目幾乎是不可能的,我們需要更加聰明的去選擇和使用開(kāi)源項(xiàng)目。形象點(diǎn)說(shuō):不要重復(fù)發(fā)明輪子,但要找到合適的輪子!你開(kāi)的是保時(shí)捷,可別找個(gè)拖拉機(jī)的輪子。
?
接下來(lái)我將根據(jù)加入U(xiǎn)C?5年與開(kāi)源項(xiàng)目有關(guān)的經(jīng)歷,總結(jié)出一些“如何正確使用開(kāi)源項(xiàng)目”的經(jīng)驗(yàn)和教訓(xùn)。有的項(xiàng)目是我親身經(jīng)歷,有的是我接觸到的,有的是我觀(guān)察的,其中部分描述細(xì)節(jié)可能并不完全準(zhǔn)確,大家可以結(jié)合自己的經(jīng)歷一起探討。
?
以下內(nèi)容主要分3個(gè)部分進(jìn)行描述,分別是“選”、“用”、“改”。
選:如何選擇一個(gè)開(kāi)源項(xiàng)目
【聚焦是否滿(mǎn)足業(yè)務(wù)】
我們?cè)谶x擇開(kāi)源項(xiàng)目的時(shí)候,一個(gè)頭疼的問(wèn)題就是相似的開(kāi)源方案較多,而且后面的總是要宣稱(chēng)比前面的更加牛逼。我們?cè)谶x擇的時(shí)候有點(diǎn)無(wú)所適從,總是會(huì)擔(dān)心選擇了A方案而錯(cuò)過(guò)了B方案,或者反過(guò)來(lái)。這里我們的經(jīng)驗(yàn)是聚焦于是否滿(mǎn)足業(yè)務(wù),而不需要過(guò)于關(guān)注開(kāi)源方案是否牛逼。
?
案例:當(dāng)時(shí)嘗試一個(gè)社交類(lèi)業(yè)務(wù)時(shí),我們發(fā)現(xiàn)了TT(Tokyo?Tyrant)這個(gè)開(kāi)源方案,覺(jué)得既能夠做緩存取代Memcached,又有持久化存儲(chǔ)功能,可以取代MySQL,很牛逼,很高大上,于是就在業(yè)務(wù)里面大量使用了。但后來(lái)的使用過(guò)程讓人很蛋疼,主要表現(xiàn)為:
1??不能完全取代MySQL,因此有兩份存儲(chǔ),設(shè)計(jì)的時(shí)候每次都要討論和決策
2??功能上看起來(lái)很高大上,但相應(yīng)的bug也不少,而且有的bug是致命的,例如所有數(shù)據(jù)不可讀,后來(lái)是自己研究源碼寫(xiě)了一個(gè)工具才恢復(fù)了部分?jǐn)?shù)據(jù)。
3??功能確實(shí)牛逼,但需要花費(fèi)較長(zhǎng)時(shí)間熟悉各種細(xì)節(jié)
后來(lái)我們反思和總結(jié),其實(shí)當(dāng)時(shí)的業(yè)務(wù)Memcached?+?MySQL完全能夠滿(mǎn)足,且大家都熟悉,當(dāng)時(shí)的業(yè)務(wù)完全不需要引入TT。
?
簡(jiǎn)單來(lái)說(shuō):如果你的業(yè)務(wù)要求1000?TPS,那么一個(gè)20000?TPS?和50000?TPS的方案是沒(méi)有區(qū)別的。有的人可能會(huì)擔(dān)心我TPS不斷上漲怎么辦?其實(shí)不用擔(dān)心,我們的架構(gòu)會(huì)不斷演進(jìn)的,等到真的需要這么高的時(shí)候我們?cè)賮?lái)架構(gòu)重構(gòu),記住:不要過(guò)早優(yōu)化,過(guò)早優(yōu)化是萬(wàn)惡之源?——?《UNIX編程哲學(xué)》
?
【聚焦是否成熟】
很多新的開(kāi)源項(xiàng)目往往都會(huì)聲稱(chēng)自己比以前的項(xiàng)目更加牛逼:性能更高、功能更強(qiáng)、引入更多新概念。。。。。。看起來(lái)都很誘人,但實(shí)際上都有意無(wú)意的隱藏了一個(gè)負(fù)面的問(wèn)題:都更加不成熟!不管多牛逼的程序員寫(xiě)出來(lái)的項(xiàng)目都會(huì)有bug,千萬(wàn)不要以為作者牛逼就沒(méi)有bug,Windows、Linux、MySQL的開(kāi)發(fā)者都是頂級(jí)的開(kāi)發(fā)者吧,一樣很多bug。
?
不成熟的開(kāi)源項(xiàng)目應(yīng)用到生產(chǎn)環(huán)境,風(fēng)險(xiǎn)極大。輕則宕機(jī),重則宕機(jī)后重啟都恢復(fù)不了,更嚴(yán)重的是數(shù)據(jù)丟失都找不回了。還是以上面提到的TT為例:我們真的遇到異常斷電后,文件被損壞,重啟也恢復(fù)不了的故障,還好當(dāng)時(shí)每天做了備份,于是只能用1天前的數(shù)據(jù)進(jìn)行恢復(fù),但當(dāng)天的數(shù)據(jù)全部丟失了。后來(lái)我們花費(fèi)了大量的時(shí)間和人力去看源碼,自己寫(xiě)工具恢復(fù)了部分?jǐn)?shù)據(jù),還好這些數(shù)據(jù)不是金融相關(guān)的數(shù)據(jù),丟失一部分問(wèn)題也不大,否則就有大麻煩了。
?
所以在選擇開(kāi)源項(xiàng)目的時(shí)候,盡量選擇成熟的開(kāi)源項(xiàng)目,降低風(fēng)險(xiǎn),形象點(diǎn)說(shuō):寧要2.0的熟女,不要0.2的處女!一般建議除非特殊情況,否則不要選0.X版本的,至少選1.X版本的,版本號(hào)越高越好。
?
【聚焦運(yùn)維能力】
我們?cè)谶x擇開(kāi)源項(xiàng)目的時(shí)候,基本上都是聚焦于技術(shù)指標(biāo),例如性能、可靠性、功能這些方案,而幾乎不會(huì)去關(guān)注運(yùn)維方面的能力。但如果要將方案應(yīng)用到線(xiàn)上生產(chǎn)環(huán)境,運(yùn)維能力是必不可少的一環(huán),否則一旦出問(wèn)題,運(yùn)維、研發(fā)、測(cè)試都只能干瞪眼,求菩薩保佑了!
?
可以從以下幾個(gè)方案去考察運(yùn)維能力:
1??開(kāi)源方案日志是否齊全:有的開(kāi)源方案日志只有寥寥啟動(dòng)停止幾行,出了問(wèn)題根本無(wú)法排查
2??開(kāi)源方案是否有命令行、管理控制臺(tái)等維護(hù)工具,能夠看到系統(tǒng)運(yùn)行時(shí)的情況
3??開(kāi)源方案是否有故障檢測(cè)和恢復(fù)的能力,例如告警、倒換等
?
用:如何使用開(kāi)源方案
【深入研究,仔細(xì)測(cè)試】
很多人用開(kāi)源項(xiàng)目,其實(shí)是完完全全的“拿來(lái)主義”,看了幾個(gè)Demo,把程序跑起來(lái)就開(kāi)始部署到線(xiàn)上應(yīng)用了。就好像看了一下開(kāi)車(chē)指南,知道了方向盤(pán)是轉(zhuǎn)向、油門(mén)是加速、剎車(chē)是減速,然后就開(kāi)車(chē)上路了,其實(shí)是非常危險(xiǎn)的。
?
案例:我們有團(tuán)隊(duì)使用了elasticsearch,基本上是拿來(lái)就用,倒排索引是什么不太清楚,配置都是用默認(rèn)值,跑起來(lái)就上線(xiàn)了,結(jié)果就遇到節(jié)點(diǎn)ping時(shí)間太長(zhǎng),剔除異常節(jié)點(diǎn)太慢,導(dǎo)致整站訪(fǎng)問(wèn)掛掉。
案例2:UC很多團(tuán)隊(duì)最初使用MySQL的時(shí)候,也沒(méi)有怎么研究過(guò),經(jīng)常有業(yè)務(wù)部門(mén)抱怨MySQL太慢了,其實(shí)經(jīng)過(guò)定位,發(fā)現(xiàn)最關(guān)鍵的幾個(gè)參數(shù)(例如innodb_buffer_pool_size,?sync_binlog,innodb_log_file_size等)都沒(méi)有配置或者配置錯(cuò)誤,性能當(dāng)然會(huì)慢。
?
可以從如下幾方面進(jìn)行研究和測(cè)試:
1??通讀開(kāi)源項(xiàng)目的設(shè)計(jì)文檔或者白皮書(shū),了解其設(shè)計(jì)原理
2??核對(duì)每個(gè)配置項(xiàng)的作用和影響,識(shí)別出關(guān)鍵配置項(xiàng)
3??進(jìn)行多種場(chǎng)景的性能測(cè)試
4??進(jìn)行壓力測(cè)試,連續(xù)跑幾天,觀(guān)察cpu、內(nèi)存、磁盤(pán)io等指標(biāo)波動(dòng)
5??進(jìn)行故障測(cè)試:kill,斷電、拔網(wǎng)線(xiàn)、重啟100次以上、倒換等
?
?【小心應(yīng)用,灰度發(fā)布】
假如我們做了上面的“深入研究、仔細(xì)測(cè)試”,發(fā)現(xiàn)沒(méi)什么問(wèn)題,是否就可以放心大膽的應(yīng)用到線(xiàn)上了呢?別高興太早,即使你的研究再深入,測(cè)試再仔細(xì),也還是要小心為妙,因?yàn)樵僭趺瓷钊氲难芯?#xff0c;再怎么仔細(xì)的測(cè)試,都只能降低風(fēng)險(xiǎn),但不可能完全覆蓋所有線(xiàn)上場(chǎng)景。
?
案例:還是以TT為例吧,其實(shí)我們?cè)趹?yīng)用之前專(zhuān)門(mén)安排一個(gè)大牛看源碼、做測(cè)試,做了大約1個(gè)月,但最后上線(xiàn)還是遇到各種問(wèn)題。線(xiàn)上生產(chǎn)環(huán)境的復(fù)雜度,真的不是測(cè)試能夠覆蓋的,必須小心謹(jǐn)慎。
?
所以,不管研究多深入、測(cè)試多仔細(xì)、自信心多爆棚,時(shí)刻對(duì)線(xiàn)上要有敬畏之心,小心駛的萬(wàn)年船。我們的經(jīng)驗(yàn)就是先在非核心的業(yè)務(wù)上用,然后有經(jīng)驗(yàn)后慢慢擴(kuò)展。
?
【做好應(yīng)急,以防萬(wàn)一】
即使我們前面的工作做得非常完善和充分,也不能認(rèn)為就萬(wàn)事大吉了,尤其是剛開(kāi)始使用一個(gè)開(kāi)源項(xiàng)目,運(yùn)氣不好的話(huà)就可能遇到一個(gè)之前全世界的使用者從來(lái)沒(méi)遇到的bug,導(dǎo)致業(yè)務(wù)都無(wú)法恢復(fù),尤其是存儲(chǔ)方面,一旦出現(xiàn)問(wèn)題無(wú)法恢復(fù)可能就是致命的打擊。
?
案例(此案例是聽(tīng)說(shuō)的):某個(gè)業(yè)務(wù)使用了MongoDB,結(jié)果宕機(jī)后部分?jǐn)?shù)據(jù)丟失,無(wú)法恢復(fù),也沒(méi)有其它備份,人工恢復(fù)都沒(méi)辦法,只能接一個(gè)用戶(hù)投訴處理一個(gè),導(dǎo)致DBA和運(yùn)維從此以后都反對(duì)我們用MongoDB,即使是嘗試性的。
?
雖然因?yàn)橐淮喂收暇屯耆磳?duì)嘗試是有點(diǎn)反應(yīng)過(guò)度了,但確實(shí)故障也給我們提了一個(gè)醒:對(duì)于重要的業(yè)務(wù)或者數(shù)據(jù),使用開(kāi)源項(xiàng)目時(shí),最好有另外一個(gè)比較成熟的方案做備份,尤其是數(shù)據(jù)存儲(chǔ)。例如:如果要用MongoDB或者Redis,可以用MySQL做備份存儲(chǔ)。這樣做雖然復(fù)雜度和成本高一些,但關(guān)鍵時(shí)刻能夠救命!
?
改:如何基于開(kāi)源項(xiàng)目做二次開(kāi)發(fā)
?【保持純潔,加以包裝】
當(dāng)我們發(fā)現(xiàn)開(kāi)源項(xiàng)目有的地方不滿(mǎn)足我們的需求的時(shí)候,自然會(huì)有一種去改改的沖動(dòng),但是怎么改是個(gè)大學(xué)問(wèn)。一種方式是投入幾個(gè)人從內(nèi)到外全部改一遍,將其改造成完全符合我們業(yè)務(wù)需求。但這樣做有幾個(gè)比較嚴(yán)重的問(wèn)題:
1??投入太大,一般來(lái)說(shuō),redis這種級(jí)別的開(kāi)源方案,真要自己改,至少要投入2個(gè)人,搞個(gè)1個(gè)月以上
2??失去了跟隨原方案演進(jìn)的能力:改的太多的話(huà),即使原有開(kāi)源項(xiàng)目繼續(xù)演進(jìn),我們也無(wú)法合并了,因?yàn)椴町愄蟆?/p>
?
所以我們的建議是不要改動(dòng)原系統(tǒng),而是要開(kāi)發(fā)輔助系統(tǒng):?監(jiān)控,報(bào)警,負(fù)載均衡,管理等。以Redis為例,如果我們想增加集群功能,不要去改動(dòng)Redis本身的實(shí)現(xiàn),而是增加一個(gè)proxy層來(lái)實(shí)現(xiàn),Twitter的Twemproxy就是這樣做的,而Redis到了3.0后本身提供了集群功能,原有的方案簡(jiǎn)單切換到Redis?3.0即可。詳細(xì)可參考(http://www.cnblogs.com/gomysql/p/4413922.html?)
?
如果實(shí)在想改到原有系統(tǒng),怎么辦呢?我們的建議是直接給開(kāi)源項(xiàng)目提需求或者bug,但弊端就是響應(yīng)比較緩慢,這個(gè)就要看業(yè)務(wù)緊急程度了,如果實(shí)在太急那就只能自己改了,不過(guò)不是太急,建議做好備份或者應(yīng)急手段即可。
?
【發(fā)明你要的輪子】
這點(diǎn)估計(jì)讓很多人大跌眼鏡,怎么講了半天,最后又回到了“重復(fù)發(fā)明你要的輪子”呢?
其實(shí)選與不選開(kāi)源項(xiàng)目,核心還是一個(gè)成本和收益的問(wèn)題,并不是說(shuō)選擇開(kāi)源項(xiàng)目就一定是最優(yōu)的方案,最主要的問(wèn)題是:沒(méi)有完全適合你的輪子!
?
軟件領(lǐng)域和硬件領(lǐng)域最大的不同就是軟件領(lǐng)域沒(méi)有絕對(duì)的工業(yè)標(biāo)準(zhǔn),大家都很盡興,想怎么玩怎么玩,不像硬件領(lǐng)域,你造一個(gè)尺寸與眾不同的輪子,其它車(chē)都用不上,你的輪子工藝再高,質(zhì)量再好也是白費(fèi);軟件領(lǐng)域可以造很多相似的輪子,也基本上能到處用,例如你把緩存從Memcached換成Redis,不會(huì)有太大的問(wèn)題。
?
除此以外,開(kāi)源項(xiàng)目為了能夠大規(guī)模應(yīng)用,考慮的是通用的處理方案,而不同的業(yè)務(wù)其實(shí)差異較大,通用方案并不一定完美適合具體的某個(gè)業(yè)務(wù)。比如說(shuō)Memcached,通過(guò)一致性hash提供集群功能,但是我們的一些業(yè)務(wù),緩存如果有一臺(tái)宕機(jī),整個(gè)業(yè)務(wù)可能就被拖慢了,這就要求我們提供緩存?zhèn)浞莸墓δ?#xff0c;但Memcached又沒(méi)有,而Redis當(dāng)時(shí)又沒(méi)有集群功能,于是我們投入2~4個(gè)人花了大約2個(gè)月時(shí)間基于LevelDB的原理,自己做了一套緩存框架支持存儲(chǔ)、備份、集群的功能,后來(lái)又在這個(gè)框架的基礎(chǔ)上增加了跨機(jī)房同步的功能,很大程度上提升了業(yè)務(wù)的可用性水平。如果完全采用開(kāi)源方案,等開(kāi)源方案來(lái)實(shí)現(xiàn),是不可能這么快速的,甚至都有可能開(kāi)源項(xiàng)目完全就不支持我們的需求。
所以,如果你有錢(qián)有人有時(shí)間,投入人力去重復(fù)發(fā)明完美符合自己業(yè)務(wù)特點(diǎn)的輪子也是很好的選擇!畢竟,土豪們(BAT......等)很多都是這樣做的,否則的話(huà)我們也就沒(méi)有那么多好用的開(kāi)源項(xiàng)目了 :)
來(lái)源:?http://mp.weixin.qq.com/s?__biz=MzA4MjA0MTc4NQ==&mid=401771199&idx=1&sn=68b42a6d3ac66da3b3137fe11930390e#rd
來(lái)自為知筆記(Wiz)
總結(jié)
以上是生活随笔為你收集整理的开源项目使用经验原则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 记录一次centos的双网卡绑定
- 下一篇: 四中方式实现单例模式