當前位置:
首頁 > 知識 > 微服務日誌的七種最佳實踐

微服務日誌的七種最佳實踐

微服務架構是一種全新的應用結構,它能夠幫助您通過松耦合的系統,開發、測試、部署和發布彼此相互獨立的各種服務。因此微服務背後的理念是:將大型系統分解成多個獨立的小部分。

通常情況下,每個服務都能通過HTTP的端點與其他服務交互。它們在隱藏技術棧細節的同時,會暴露自己的契約(contract)給其對應的消費者(consumer)角色。例如:服務A可以在調用服務B的同時,也去調用服務C,而只要整個請求鏈是完整的,那麼服務A就能夠對發起請求的客戶端做出響應。

微服務架構能夠給我們的系統帶來很多方面的好處,其主要能力包括:使用不同的技術棧、獨立地進行部署、一次只解決一個小問題等。但是,由於它在通信和管理上的複雜性,一般使用微服務的成本會比較高。而且在一個或多個服務出現問題時,微服務會變得更加複雜。如果沒有掌握良好的、且有意義的日誌的話,你都無法回答諸如:哪個服務、為什麼、和在什麼情況下失敗了等問題。

老實說,我本人最憎恨那些由於糟糕的日誌策略,所導致的一些「未知」的系統錯誤。下面我們和您分享一些,自己在與微服務打交道時總結出的七種最佳實踐。

1.用唯一性ID來關聯各個請求

請回想一下我們上面提到的服務A、B、C之間的請求調用鏈。在實踐中,我們應當給每一個調用分配一個唯一性的ID,以便標識出每一個請求。

設想您正在記錄每個服務的訪問與錯誤日??志。如果您發現在服務B上有錯誤,那麼您就能知道該錯誤是來自於服務A、還是服務C。

如果錯誤信息足夠詳細的話,您也許不必去重現錯誤。但是多數情況並非如此,您必須通過正確的方式,將各個服務(如服務B)中的所有請求進行錯誤重現。因此,如果您發現了某個與之相關聯的請求,那麼您只需要在日誌中尋找出它所對應的ID便可。

隨後,您可以順藤摸瓜地從系統中將那些主要請求的某個部分,從服務的全量日誌中截取出來。接著,您就可以知道是哪項服務的主請求花費了最多的時間。其可能性包括:可能是某項服務使用到了緩存、或是某項服務不止一次調用了其他服務、以及其他有趣的細節。

2.在響應中包含唯一性ID

微服務的用戶可能會不止一次地碰到同一個錯誤。面對這樣的情況,您應該乘機對客戶端可能接收到的響應進行編碼,以便它能夠將一個唯一性的ID,連同與該錯誤相關的任何其他有用的信息都傳遞出來。當然,這個唯一性的ID完全可以和我們在上面所提到的相關請求保持一致。


微服務日誌的七種最佳實踐

打開今日頭條,查看更多精彩圖片


因此,在響應的有效載荷中包含與請求相關的唯一性ID,將有助於您和您的客戶更迅速地發現各類問題。同時,您也可以獲悉請求日期、時間和其他細節上的參數,以便您能夠更好地理解自己所碰到的問題。另外,您還可以將請求的ID,添加到諸如「請聯繫服務管理員,並報告該問題。」之類的常見補充性錯誤信息之中,以便深入了解到底是什麼原因引起該錯誤,進而防止它在未來再次發生。

3.發送日誌到集中的位置

在此,讓我們假設您已經對各種有用的日誌信息進行了分類。下一步,我們就需要將各類日誌發送到一個集中化的位置。

試想一下:如果您每次都需要登錄到各個相互單獨的伺服器上,以來讀取不同的日誌信息,那麼您將不得不花費更多的時間去試圖關聯這些問題。這遠不如您登錄到某一個位置,並一站式地訪問到所有的日誌,以定位問題。

此外,您的系統通常會隨著時間的推移,而變得日趨複雜,而各項微服務的數量也會節節攀升。同時,您的各種服務可能會分處不同的伺服器或提供商,這都會讓形勢變得更為複雜。

因此,集中式存放日誌正在成為業界的常規方法,特別是當您的服務工作在雲端、容器、或其他混合環境之中,而某些伺服器可能會在無任何通知的情況下下線的時候。例如,在出現異常錯誤,或是內存的消耗水平已經達到100%時,某些容器就會被終止運行。

您可以在伺服器中斷之前,通過設置代理,每五分鐘推/拉一次日誌,來解決此類問題。您也可以在伺服器上配置一個cronjob(定時任務)、sidecar container、或是一個與其他進程共享的文件位置,來集中化各種日誌。為了避免日誌被篡改,您還可以自行構建一套解決方案,具體請參見鏈接:https://blog.scalyr.com/2017/11/log-management-need/。

可見,將所有服務的日誌都集中到一處,會有助於您更容易、且有效地定位各種關聯問題。

4.結構化您的日誌數據

在具體實踐中,我們很難為所有的日誌數據預先定義好格式。有些日誌可能需要比其他日誌更多的欄位,相反這些欄位可能會對那些不需要的日誌來說不但多餘、而且浪費位元組數。

微服務架構是通過使用不同的技術堆棧,來解決此類問題的。不過,這會影響每個服務的日誌格式。例如:某一個服務可能是用逗號來分隔不同的欄位,而其他日誌則使用的是管道或命名空間。

上述方法顯然比較複雜。因此,我們可以通過將自己的日誌數據構建成一套標準的格式,如:JavaScript Object Notation(JSON),來簡化解析日誌的過程。JSON允許您擁有多層次的數據。在必要的時候,您可以在單個日誌的事件中獲取更多的語義信息。

同時,此法也使得對於特定日誌格式的解析更加直接。通過對數據採取結構化,就算您的日誌里有各種不同的欄位,其格式也會變得更加標準。籍此,您也可以在集中化的位置上創建各種搜索,例如:檢索包含有500條及以上,「HTTP_CODE」欄位的日誌信息。可以說,使用結構化的日誌方式既能讓您的微服務日誌實現標準化,又不失靈活性。

5.為每個請求添加上下文


微服務日誌的七種最佳實踐


通常情況下,如果系統能夠提供足夠的信息,那麼我們就能夠更好地了解針對某個問題的上下文請求,更快地發現該問題的根本原因。不過,給各種日誌添加上下文,也會在代碼層面上產生一些重複性的工作,因為在您所需要的許多日誌事件中,已經包含了諸如日期和時間等通用數據信息。因此在我們的代碼中,應當只記錄那些重要的消息、並涉及到一些特定的領域,以使得日誌看起來簡單明了。

您可能會想到各種五花八門的數據需要被記錄,但是讓我們通過如下的列表,來告訴您哪些才是真正需要記錄的具體特定領域吧。

  • 日期和時間。當然,如果能夠保證讀取日誌的人都在同一時區的話,您大可不必一律採用UTC(世界標準時間)的格式。
  • 堆棧錯誤。您可以將異常對象作為參數傳遞給自己的日誌庫。
  • 服務的名稱或代碼,這樣您就可以根據微服務來區分不同的日誌。
  • 發生錯誤的函數、類或文件名,這樣您就省去了跟蹤問題出處的時間。
  • 與外部服務交互的各種名稱,例如:您可以獲悉是哪個進程在調用資料庫時出現了問題。
  • 伺服器和客戶端請求的IP地址。這些信息將有助於發現那些不健康的伺服器、或識別出DDoS類攻擊。
  • 應用程序的用戶代理,以便您能判斷是哪些瀏覽器或用戶碰到了問題。
  • 通過HTTP代碼來獲取錯誤的更多語義。這些代碼將有助於創建各類警報。

可見,為每個請求添加上下文,能夠節省您對系統進行排障的時間。

6.將日誌存儲到本地

將日誌存儲到本地,似乎聽起來和我們前面說的「發送日誌到集中的位置」有些矛盾,其實則不然。最初我是將各種日誌,直接通過HTTP請求的方式發送到別處的。但是我屢次發現這些流量傳輸佔用掉了我大量的出站帶寬,以至於影響到了其他更為重要的微服務調用。

因此,我們需要對日誌的外發和本地存儲有所取捨。最終,我之所以選擇了本地存儲,是因為這樣有助於從應用程序中分離日誌、並減少上下文的切換。針對資料庫,您可以採取將應用程序與其日誌區分不同存儲卷的方式。

例如:亞馬遜的AWS就一個選項,用戶可以使用一種稱為Elastic File System(EFS)的服務,去掛載某個卷。其功能類似於網路附屬存儲(network-attached storage,NAS)。那麼,您可以按需輾轉到另一台伺服器上,掛載相同容量的卷,然後將各種日誌轉發到那個集中的位置上。

簡單說來,我們可以使用Docker容器,來實現將所有應用程序的日誌都發送到相同的位置。然後匯總、過濾和轉發這些日誌的存儲庫,到其他進程或服務那裡。

7.記錄重要且有意義的數據,有備無患

如果您是剛開始接觸微服務的日誌問題,那麼上述最佳實踐可能會對你比較「無感」。但是,只要您足夠細心,在持續使用了微服務一段時間之後,您就可以通過對現有日誌信息和方式的評估,逐漸摸索出哪些才是您可以用來發現和解決奇怪問題的有用信息。

同時,在記錄和積累了足夠多的日誌數據之後,您還可以伺機採用自動化的警報方式,以節約您通過讀取大量日誌來定位問題的時間。當然,自動化警報也能夠幫助您以一種積極主動方式,限制各種錯誤向所有用戶處蔓延。

總之,集中化日誌信息,是微服務錯誤分析的必備手段。而為日誌添加足夠多的上下文信息,則能夠更好地分辨出那些是有用的日誌,那些是無用的信息。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

php全局異常處理
oracle11g 拆分字元串的詳細技巧

TAG:程序員小新人學習 |