導讀:軟件開發領域有一個流行的原則:DRY,Don’t repeat yourself,咱們翻譯過來更形象通俗:不要重複造輪子。開源項目主要目的是共享,其實就是爲了讓你們不要重複造輪子,尤爲是在互聯網這樣一個快速發展的領域,速度就是生命,引入開源項目,能夠節省大量的人力和時間,大大加快業務的發展速度,何樂而不爲呢?
然而現實每每沒有那麼美好,開源項目雖然節省了大量的人力和時間,但帶來的問題也很多,相信絕大部分同窗都踩過開源軟件的坑,小的影響多是宕機半小時,大的問題多是丟失幾十萬數據,甚至災難性的事故是所有數據都丟失。
除此之外,雖然DRY原則擺在那裏,但實際上開源項目反而是最不遵照DRY原則的,重複的輪子好多,尤爲是歪果仁,一看哪一個開源方案不爽,本身就吭哧吭哧搞一個差很少的:你有MySQL,我有PostgreSQL;你有MongoDB,我有Cassandra;你有memcached,我有redis;你有Gson,我有Jackson;你有Angular,我有React。總之放眼望去,其實類似的輪子不少!類似輪子太多,選擇就是讓人頭疼的問題了。
怎麼辦?徹底不用開源項目幾乎是不可能的,咱們須要更加聰明的去選擇和使用開源項目。形象點說:不要重複發明輪子,但要找到合適的輪子!你開的是保時捷,可別找個拖拉機的輪子。
接下來我將根據加入UC,5年與開源項目有關的經歷,總結出一些「如何正確使用開源項目」的經驗和教訓。有的項目是我親身經歷,有的是我接觸到的,有的是我觀察的,其中部分描述細節可能並不徹底準確,你們能夠結合本身的經歷一塊兒探討。
如下內容主要分3個部分進行描述,分別是「選」、「用」、「改」。
聚焦是否知足業務?
咱們在選擇開源項目的時候,一個頭疼的問題就是類似的開源方案較多,並且後面的老是要宣稱比前面的更加牛逼。咱們在選擇的時候有點無所適從,老是會擔憂選擇了A方案而錯過了B方案,或者反過來。這裏咱們的經驗是聚焦因而否知足業務,而不須要過於關注開源方案是否牛逼。
案例:當時嘗試一個社交類業務時,咱們發現了TT(Tokyo Tyrant)這個開源方案,以爲既可以作緩存取代Memcached,又有持久化存儲功能,能夠取代MySQL,很牛逼,很高大上,因而就在業務裏面大量使用了。但後來的使用過程讓人很蛋疼,主要表現爲:
一、不能徹底取代MySQL,所以有兩份存儲,設計的時候每次都要討論和決策。
二、功能上看起來很高大上,但相應的bug也很多,並且有的bug是致命的,例如全部數據不可讀,後來是本身研究源碼寫了一個工具才恢復了部分數據。
三、功能確實牛逼,但須要花費較長時間熟悉各類細節。
後來咱們反思和總結,其實當時的業務Memcached + MySQL徹底可以知足,且你們都熟悉,當時的業務徹底不須要引入TT。
簡單來講:若是你的業務要求1000 TPS,那麼一個20000 TPS 和50000 TPS的方案是沒有區別的。有的人可能會擔憂我TPS不斷上漲怎麼辦?其實不用擔憂,咱們的架構會不斷演進的,等到真的須要這麼高的時候咱們再來架構重構,記住:不要過早優化,過早優化是萬惡之源 —— 《UNIX編程哲學》。
聚焦是否成熟
不少新的開源項目每每都會聲稱本身比之前的項目更加牛逼:性能更高、功能更強、引入更多新概念。看起來都很誘人,但實際上都有意無心的隱藏了一個負面的問題:都更加不成熟!無論多牛逼的程序員寫出來的項目都會有bug,千萬不要覺得做者牛逼就沒有bug,Windows、Linux、MySQL的開發者都是頂級的開發者吧,同樣不少bug。
不成熟的開源項目應用到生產環境,風險極大。輕則宕機,重則宕機後重啓都恢復不了,更嚴重的是數據丟失都找不回了。仍是以上面提到的TT爲例:咱們真的遇到異常斷電後,文件被損壞,重啓也恢復不了的故障,還好當時天天作了備份,因而只能用1天前的數據進行恢復,但當天的數據所有丟失了。後來咱們花費了大量的時間和人力去看源碼,本身寫工具恢復了部分數據,還好這些數據不是金融相關的數據,丟失一部分問題也不大,不然就有大麻煩了。
因此在選擇開源項目的時候,儘可能選擇成熟的開源項目,下降風險。
能夠從如下幾個方面考察是否成熟:
1)版本號:通常建議除非特殊狀況,不然不要選0.X版本的,至少選1.X版本的,版本號越高越好。
2)使用的公司數量:通常開源項目都會把採用了本身項目的公司列在主頁上,公司越大越好,數量越多越好。
3)社區活躍度:看看社區是否活躍,發帖數、回覆數、問題處理速度等。
聚焦運維能力
咱們在選擇開源項目的時候,基本上都是聚焦於技術指標,例如性能、可靠性、功能這些方案,而幾乎不會去關注運維方面的能力。但若是要將方案應用到線上生產環境,運維能力是必不可少的一環,不然一旦出問題,運維、研發、測試都只能乾瞪眼,求菩薩保佑了!
能夠從如下幾個方案去考察運維能力:
1)開源方案日誌是否齊全:有的開源方案日誌只有寥寥啓動中止幾行,出了問題根本沒法排查。
2)開源方案是否有命令行、管理控制檯等維護工具,可以看到系統運行時的狀況。
3)開源方案是否有故障檢測和恢復的能力,例如告警、倒換等。
深刻研究,仔細測試
不少人用開源項目,實際上是完徹底全的「拿來主義」,看了幾個Demo,把程序跑起來就開始部署到線上應用了。就好像看了一下開車指南,知道了方向盤是轉向、油門是加速、剎車是減速,而後就開車上路了,實際上是很是危險的。
案例:咱們有團隊使用了elasticsearch,基本上是拿來就用,倒排索引是什麼不太清楚,配置都是用默認值,跑起來就上線了,結果就遇到節點ping時間太長,剔除異常節點太慢,致使整站訪問掛掉。
案例2:不少團隊最初使用MySQL的時候,也沒有怎麼研究過,常常有業務部門抱怨MySQL太慢了,其實通過定位,發現最關鍵的幾個參數(例如innodb_buffer_pool_size, sync_binlog,innodb_log_file_size等)都沒有配置或者配置錯誤,性能固然會慢。
能夠從以下幾方面進行研究和測試:
1)通讀開源項目的設計文檔或者白皮書,瞭解其設計原理;
2)覈對每一個配置項的做用和影響,識別出關鍵配置項;
3)進行多種場景的性能測試;
4)進行壓力測試,連續跑幾天,觀察cpu、內存、磁盤io等指標波動;
5)進行故障測試:kill,斷電、拔網線、重啓100次以上、倒換等。
當心應用,灰度發佈
假如咱們作了上面的「深刻研究、仔細測試」,發現沒什麼問題,是否就能夠放心大膽的應用到線上了呢?別高興太早,即便你的研究再深刻,測試再仔細,也仍是要當心爲妙,由於再怎麼深刻的研究,再怎麼仔細的測試,都只能下降風險,但不可能徹底覆蓋全部線上場景。
案例:仍是以TT爲例吧,其實咱們在應用以前專門安排一個大牛看源碼、作測試,作了大約1個月,但最後上線仍是遇到各類問題。線上生產環境的複雜度,真的不是測試可以覆蓋的,必須當心謹慎。
因此,無論研究多深刻、測試多仔細、自信心多爆棚,時刻對線上要有敬畏之心,當心駛的萬年船。咱們的經驗就是先在非核心的業務上用,而後有經驗後慢慢擴展。
作好應急,以防萬一
即便咱們前面的工做作得很是完善和充分,也不能認爲就萬事大吉了,尤爲是剛開始使用一個開源項目,運氣很差的話就可能遇到一個以前全世界的使用者歷來沒遇到的bug,致使業務都沒法恢復,尤爲是存儲方面,一旦出現問題沒法恢復可能就是致命的打擊。
案例(此案例是據說的):某個業務使用了MongoDB,結果宕機後部分數據丟失,沒法恢復,也沒有其它備份,人工恢復都沒辦法,只能接一個用戶投訴處理一個,致使DBA和運維今後之後都反對咱們用MongoDB,即便是嘗試性的。
雖然由於一次故障就徹底反對嘗試是有點反應過分了,但確實故障也給咱們提了一個醒:對於重要的業務或者數據,使用開源項目時,最好有另一個比較成熟的方案作備份,尤爲是數據存儲。例如:若是要用MongoDB或者Redis,能夠用MySQL作備份存儲。這樣作雖然複雜度和成本高一些,但關鍵時刻可以救命!
保持純潔,加以包裝
當咱們發現開源項目有的地方不知足咱們需求的時候,天然會有一種去改改的衝動,可是怎麼改是個大學問。一種方式是投入幾我的從內到外所有改一遍,將其改形成徹底符合咱們的業務需求。但這樣作有幾個比較嚴重的問題:
1)投入太大,通常來講,redis這種級別的開源方案,真要本身改,至少要投入2我的,搞1個月以上;
2)失去了跟隨原方案演進的能力:改的太多的話,即便原有開源項目繼續演進,咱們也沒法合併了,由於差別太大。
因此咱們的建議是不要改動原系統,而是要開發輔助系統: 監控,報警,負載均衡,管理等。以Redis爲例,若是咱們想增長集羣功能,不要去改動Redis自己的實現,而是增長一個proxy層來實現,Twitter的Twemproxy就是這樣作的,而Redis到了3.0後自己提供了集羣功能,原有的方案簡單切換到Redis 3.0便可。詳細可參考(http://www.cnblogs.com/gomysql/p/4413922.html )
若是實在想改到原有系統,怎麼辦呢?咱們的建議是直接給開源項目提需求或者bug,但弊端就是響應比較緩慢,這個就要看業務緊急程度了,若是實在太急那就只能本身改了,不過不是太急,建議作好備份或者應急手段便可。
發明你要的輪子
這點估計讓不少人大跌眼鏡,怎麼講了半天,最後又回到了「重複發明你要的輪子」呢?
其實選與不選開源項目,核心仍是一個成本和收益的問題,並非說選擇開源項目就必定是最優的方案,最主要的問題是:沒有徹底適合你的輪子!
軟件領域和硬件領域最大的不一樣就是軟件領域沒有絕對的工業標準,你們都很盡興,想怎麼玩怎麼玩,不像硬件領域,你造一個尺寸不同凡響的輪子,其它車都用不上,你的輪子工藝再高,質量再好也是白費;軟件領域能夠造不少類似的輪子,也基本上能處處用,例如你把緩存從Memcached換成Redis,不會有太大的問題。
除此之外,開源項目爲了可以大規模應用,考慮的是通用的處理方案,而不一樣的業務其實差別較大,通用方案並不必定完美適合具體的某個業務。好比說Memcached,經過一致性hash提供集羣功能,可是咱們的一些業務,緩存若是有一臺宕機,整個業務可能就被拖慢了,這就要求咱們提供緩存備份的功能,但Memcached又沒有,而Redis當時又沒有集羣功能,因而咱們投入2~4我的花了大約2個月時間基於LevelDB的原理,本身作了一套緩存框架支持存儲、備份、集羣的功能,後來又在這個框架的基礎上增長了跨機房同步的功能,很大程度上提高了業務的可用性水平。若是徹底採用開源方案,等開源方案來實現,是不可能這麼快速的,甚至都有可能開源項目徹底就不支持咱們的需求。
因此,若是你有錢有人有時間,投入人力去重複發明完美符合本身業務特色的輪子也是很好的選擇!畢竟,土豪們(BAT、Facebook、Google......等)不少都是這樣作的,不然咱們也就沒有那麼多好用的開源項目了 :)