分佈式系統關注點(21)——構建「易測試」系統的「六脈神劍」

若是第二次看到個人文章,歡迎關注個人我的原創公衆號「跨界架構師」哦~

每週五11:45 按時送達。 固然了,也會時不時加個餐~


這篇是「分佈式系統理論」系列的第20篇。提早預告一下,後面還有一篇文章,這個系列就結束了。html

在以前,核心的概念都講的差很少了。前面Z哥帶你已經聊過了「數據一致性」、「高可用」、「易擴展」、「高性能」主題下的一些實踐思路。程序員

這篇講怎麼構建一個「易測試」的系統。sql


做爲一位開發人員,可能一聽到測試就想關掉這篇文章了。那我只能說too young,too naive。數據庫

做爲關注我這個號的「跨界者「們,你不能將本身的邊界劃的太清楚,特別在當下這個變化愈來愈快、適者生存的時代。要活的像「水」同樣,與所處的環境結合的更緊密。bash

除此以外,測試工做並非單單測試人員的事,開發人員是否是編寫了一個易測試的系統也相當重要。服務器


在Z哥我過去的幾年coding經驗中,總結了六點認爲有助於構建出一個易測試的系統建議,在這裏分享給你。微信


第一點,分層。分層其實除了以前聊到的「易擴展」以外,對於測試工做的進行也是有很大幫助,規模越大的系統越是如此。架構

腦子裏想象一下,一條業務線比如一根管道,每一次的業務操做會經歷整根管道的流轉最終到達終點。框架

每每不少時候,其實咱們已經定位到了問題可能產生的範圍,可是因爲項目沒有作好分層,致使每一次的測試工做不得不「從頭開始」。這是多麼痛苦的一件事。分佈式

作好分層只要記住一個概念就行,「高內聚低耦合」。具體能夠參考以前的文章,文末放連接。


第二點,無狀態。前面的文章裏說過,知足無狀態的功能點意味着能夠動態的進行擴容而不用考慮「狀態丟失」問題。其實同時它也支持了一種測試場景,就是「容量規劃」。

爲了支撐業務的不斷髮展以及不按期舉行的大型活動,咱們須要清楚的知道,到底部署多少臺機器爲宜。

固然,你也能夠選擇拍腦殼的方式進行,儘可能多加一些就行了。但這不是一個科學的方法,也容易形成更多的浪費。

進行容量規劃的過程就比如經過水龍頭裝水到一組杯子裏。好比,你如今的要求是1分鐘裝入3L水,那麼經過不斷的調整杯子的數量和大小,理想狀況是剛恰好達到這個要求爲宜。

若是此時支持無狀態,那麼整個過程當中水龍頭一直開着就行了,你只要專心調整杯子的數量和大小就行。作好無狀態具體也能夠參考以前的文章,文末放連接。


第三點,避免硬編碼,儘可能配置化。可能你一看到那些龐雜的配置項就頭疼,可是不得不說,配置對於測試工做的開展是有很大幫助的。

反而用「眼不見爲淨」的方式,硬編碼到邏輯代碼中是「掩耳盜鈴」的辦法。

特別是如下這些用途的變量,儘可能放到配置中去,不然每次配置的變動都須要從新打包編譯代碼,是多麼麻煩的一件事情。

  • 容量類的配置

  • 次數類的配置

  • 開關類的配置

  • 時間類的配置

這些類型的配置之間的共同點是,沒有永遠正確、永遠合理的配置。你要根據你當前的需求,不斷的調整他們。

若是能夠引入一個集中式的配置中心就更好了,這樣能夠不用一個個登錄服務器去修改配置。


第四點,依賴注入。若是你平時常常編寫單元測試的話,對這個應該感覺頗深。由於支持依賴注入的代碼,更容易編寫單元測試。

但它的價值還不止於此,隨着系統規模愈來愈大,對於直接在生產環境進行故障演練需求越迫切,由於這才足夠真實。

可是又要求不能對正常的業務數據產生影響,怎麼作?那就只能單獨準備演練數據,而後寫入到單獨的數據庫中。

這個時候,依賴注入就起做用了。咱們能夠將載入數據源的地方設計成支持依賴注入的,如此一來,你就能夠靈活的切換到不一樣的數據源,進行故障演練。

public interface IDataSource{
    public string getName(int id);
}
​
public class DataSourceMysql implements IDataSource{
    public string getName(int id){
        // 從正常的數據庫裏中獲取數據。
    }
}
​
public class DataSourceDrill implements IDataSource{
public string getName(int id){
        // 從故障演練的數據庫裏中獲取數據。
    }
}
​
public class UserBLL{
    private IDataSource _database;
    public UserBLL(IDataSource database){
        _database = database;
    }
    
    public void MethodA(int id){
        // do something...
        
        var name = _database.getName(id);
        
        // do something...
    }
}
​
//如下是調用的時候
new UserBLL(new DataSourceMysql()).MethodA(id);  //處理的是正常數據
new UserBLL(new DataSourceDrill()).MethodA(id);  //處理的是演練數據複製代碼


第五點,打日誌。測試工做最終作的好很差,看的是數據,是結果。這就意味着,對一個系統要求是「可觀測」的。

一個系統的運行過程怎麼來觀測呢?就是經過各個地方的打日誌。

以前據說過一個自嘲的段子,說咱們中國程序員在硅谷爲何混的沒印度人好,就是由於沒人家日誌打的多。說明咱們不少時候都在靠「直覺」作事,但直覺會常常翻車~

怎麼打好日誌?主要就是2個事情,「梳理」和「歸類」。先梳理羅列一下各個打日誌的地方,而後經過「目的」進行「歸類」。

好比你是想以應對方式來歸類的話,日誌能夠分爲立刻處理,按期處理,按期關注,過後排查等等。

你想以重要程度來歸類的話,就是嚴重錯誤、錯誤、警告、普通訊息等等。

【Fault】2019-05-24 09:01:07.669 | xxxxxx
【Error】2019-05-24 09:01:07.679 | xxxxxx
【Warning】2019-05-24 09:01:07.689 | xxxxxx
【Info】2019-05-24 09:01:07.699 | xxxxxx
...複製代碼

記住,不要過度吝嗇你的磁盤空間,那點錢不值得你用更多排查問題的時間去換


第六點,接口版本化,而且向前兼容。用戶規模越大的系統,越不能用一刀切的方式發佈,須要像一滴水滴到紙上同樣,緩慢的進行蔓延,進行更新。這其實也是一種試探性的測試方式。

版本管理怎麼進行呢?首先你得要有一個版本管理中心,管理着不一樣版本之間的依賴關係。好比如下這樣。

其次,你要有一個集中式的分發請求的地方。好比網關或者一些服務治理解決方案。

而後,在程序往下游系統發起請求的時候,將本身的版本號在消息頭中帶給網關或者服務治理框架。由他們經過上面的這個依賴關係表,路由到指定版本的服務節點上去。

除了這個以外,你的接口實現邏輯上還須要向前兼容,不然請求是路由過來了,處理不了仍是白搭。



總結一下,今天沒有寫什麼技術性的東西,主要就是一些思路上的東西。其實,哪怕你的程序不具備「易測試性」,並不會阻礙測試工做的進行。但這並不意味着,它不重要。

你不重視它,它也不重視你,更容易給你找麻煩。誰都不但願天天都在修bug,你說是吧?

相關文章:


做者:Zachary

出處:www.cnblogs.com/Zachary-Fan…


若是你喜歡這篇文章,能夠點一下左側的「大拇指」哦~。

這樣能夠給我一點反饋。: )

謝謝你的舉手之勞。


▶關於做者:張帆(Zachary,我的微信號:Zachary-ZF)。堅持用心打磨每一篇高質量原創。本文首發於公衆號:「跨界架構師」(ID:Zachary_ZF)。<-- 點擊後閱讀熱門文章

按期發表原創內容:架構設計丨分佈式系統丨產品丨運營丨一些思考。

若是你是初級程序員,想提高但不知道如何下手。又或者作程序員多年,陷入了一些瓶頸想拓寬一下視野。歡迎關注個人公衆號「跨界架構師」,回覆「技術」,送你一份我長期收集和整理的思惟導圖。

若是你是運營,面對不斷變化的市場一籌莫展。又或者想了解主流的運營策略,以豐富本身的「倉庫」。歡迎關注個人公衆號「跨界架構師」,回覆「運營」,送你一份我長期收集和整理的思惟導圖。

相關文章
相關標籤/搜索