案例|服務化架構系統監控難題解決方案

原文網址連接:http://url.cn/kVjUVOjava

衆所周知,系統監控一直是擁有複雜IT架構的企業所面臨的一個重要問題,而這也並非每家企業都可以輕鬆解決的技術挑戰。OPPO做爲一家國際智能終端設備及移動互聯網服務供應商,推出過多款外觀精細、功能可靠的智能手機產品,其品牌知名度也一直名列前茅。但實際上OPPO公司與其餘快速發展的現代企業同樣面臨着本身的IT挑戰,而更加不爲人知的,則是其品牌背後一樣出色的IT團隊與信息化支持能力。
web

OPPO後端系統規模近幾年快速發展,系統重構之後採用了服務化的架構,各系統之間耦合下降,開發效率獲得了很大的提高。然而在服務化帶來了好處的同時,難於監控的問題也一併出現。因爲服務之間調用關係錯綜複雜,接口出現問題,多個系統報錯,所以很難定位真正的故障源頭。整個請求調用鏈就像一個黑盒子,沒法跟蹤請求的整個調用路徑,發現性能瓶頸點。
shell

爲了解決這些問題,OPPO公司自行開發了一套監控系統,並結合第三方監控系統,造成了從App請求開始到後端處理過程的完整監控體系。OPPO監控系統的簡稱爲OMP(OPPO Monitor Platform),歷時半年開發,分爲兩期上線,如今已全面接入OPPO線上項目。
數據庫

三大理由決定自主研發
後端

之因此選擇自主研發監控系統,主要是考慮到三方面的緣由:定製化需求、易用性、以及開發成本低。
緩存

首先,在對比以後發現現有的開源監控軟件沒法知足OPPO 的需求。對於監控系統來講最核心的一條需求,就是要可以監控每一個App請求的完整調用鏈,從App發起請求,到後端的負載均衡接入、API Server、微服務調用、緩存、消息隊列、數據庫訪問時間等。系統架構微服務化之後,服務跟蹤和服務調用鏈監控尤其重要,不然系統故障及性能瓶頸就很難排查了。
安全

爲了打通用戶請求的完整調用鏈,須要在API框架、RPC框架、緩存操做、數據庫操做、隊列消費等代碼埋點,以及高性能處理和存儲系統,而目前的開源軟件沒法知足需求,各大公司也所以纔開發了本身的監控平臺。因爲服務調用跟蹤功能跟開發框架深度關聯,各公司選用的框架並不相同,因此業界鮮有相似開源的產品。
服務器

第二個緣由是考慮到權限及一體化管理界面的需求。監控平臺不只僅面向運維人員,開發人員、運營人員、測試人員也須要常用。例如根據監控平臺採集到JVM Young GC/Full GC次數及時間、耗時Top 10線程堆棧等信息,常常查看監控平臺,開發、測試人員即可以評估代碼質量,排除隱患。
網絡

監控平臺面向用戶衆多,安全性及權限管理要求較高,同時須要一體化的管理界面,簡潔易用,而組合多個開源軟件,權限和管理便捷性很難知足需求。
架構

第三,監控系統的開發難度比較低。自行研發的監控平臺雖有千般好處,可是若是開發的難度太大,以致於沒法持續的投入,那也是沒有意義的。基於Sigar、kafka、Flume、HBase、Netty等技術,開發高性能、可伸縮的系統難度實際上並不大,須要投入的資源不須要不少。

六項目標內容實現線上應用全面監控

OMP的最終目標是提供一體化的監控系統,在同一套管理界面及權限體系之下,對線上應用系統進行多維度的監控。OMP現階段主要監控內容包括:主機性能指標監控、中間件性能指標監控、服務調用鏈實時監控、接口性能指標監控、日誌實時監控、業務指標實時監控。

主機性能指標監控方面的開源軟件很是多,好比Zabbix、Cacti等。主要採集主機的CPU負載、內存使用率、各網卡的上下行流量、各磁盤讀寫速率、各磁盤讀寫次數(IOPS)、各磁盤空間使用率等。

藉助開源的Sigar庫,能夠輕鬆採集主機信息,爲了保證整個監控系統體驗的一致性,以及系統擴展性、穩定性的要求,咱們沒有直接採用Zabbix等開源監控系統,而是本身開發Agent程序,部署在主機上採集信息。

Sigar(System Information Gatherer And Reporter),是一個開源的工具,提供了跨平臺的系統信息收集的API。核心由C語言實現的,能夠被如下語言調用: C/C++、Java 、Perl 、NET C# 、Ruby 、Python 、PHP 、Erlang 。

Sigar能夠收集的信息包括:

  • CPU信息,包括基本信息(vendor、model、mhz、cacheSize)和統計信息(user、sys、idle、nice、wait);

  • 文件系統信息,包括Filesystem、Size、Used、Avail、Use%、Type;

  • 事件信息,相似Service Control Manager;

  • 內存信息,物理內存和交換內存的總數、使用數、剩餘數;RAM的大小;

  • 網絡信息,包括網絡接口信息和網絡路由信息;

  • 進程信息,包括每一個進程的內存、CPU佔用數、狀態、參數、句柄;

  • IO信息,包括IO的狀態,讀寫大小等;

  • 服務狀態信息;

  • 系統信息,包括操做系統版本,系統資源限制狀況,系統運行時間以及負載,JAVA的版本信息等。

對於中間件性能指標監控,目前根據業務使用中間件的狀況來看,主要採集的中間件包括Nginx、MySQL、MongoDB、Redis、Memcached、JVM、Kafka等。實現方式爲部署獨立的採集服務器,經過中間件的java客戶端執行狀態查詢命令,解析出相應的性能指標,採集的部分指標以下表所示:

JVM

堆內存、永久代內存、老年代內存、線程CPU時間、線程堆棧、Yong GC、Full GC

MySQL

慢查詢、QPS、TPS、鏈接數、空間大小、表鎖、行鎖…

Redis

QPS、命中率、鏈接數、條目數、佔用內存…

Memcached

QPS、命中率、佔用內存、條目數、鏈接數…

Nginx

每秒請求數、鏈接數、keepalive鏈接數、持久鏈接利用率…


系統架構微服務化之後,服務調用錯綜複雜,出了問題或性能瓶頸,每每很難定位。因此服務調用鏈實時監控極爲重要。

服務調用鏈監控是從一個App發起請求開始,分析各環節耗時及錯誤狀況,包括負載均衡接入、API Server耗時、微服務調用耗時、緩存訪問耗時、數據庫訪問耗時、消息隊列處理耗時等,以及各環節的錯誤信息,便於跟蹤性能瓶頸及錯誤。

因爲服務調用量巨大,同時便於管理員查看,監控系統不能存儲全部請求的調用鏈,主要存儲如下幾種請求:

  • 週期內最慢Top 1000請求:經過分析最慢的top 1000請求,能夠判斷主要的性能瓶頸環節,好比數據庫訪問,或者調用第三方公司接口耗時過多。

  • 採樣請求:根據設置採樣比例,隨機選取部分請求,存儲請求的調用鏈。

  • 關鍵字:知足關鍵字規則,存儲請求的調用鏈。

接口性能指標監控,主要監控接口的可用性和響應時間,由內部監控和外部監控兩部分組成:

  • 外部監控:外部監控由第三方公司負責,分爲兩種,一是App中埋點,採集真實的業務請求性能指標。二是經過第三方公司部署在各地的採集點,主動監控接口在各地區的可用性和性能指標。外部監控只能監控負載均衡器對外的最終接口服務地址的可用性和性能指標,若是要監控機房內部接口服務器,則須要機房內部部署第三方公司的Agent,這樣會帶來很是大安全風險,因此機房內部節點監控由內部監控完成。

  • 內部監控:內部監控採用OMP,監控負載均衡層後面的接口服務器的可用性和性能指標,及時發現異常節點,同時OMP根據異常緣由,回調業務系統提供的恢復URL,嘗試恢復系統。

應用產生的日誌分散在各應用服務器當中,因爲安全管理很是嚴格,開發人員查看線上系統的日誌很是不方便,同時日誌內容匹配關鍵字須要發送告警通知相關人員。OMP將日誌統一採集存儲到Elastic Search集羣,實現日誌檢索。OMP日誌實時監控主要包括以下功能:

  • 日誌實時在線查看:監控平臺能夠實時查看日誌文件的內容,效果相似tail –f 命令,同時屏蔽內容中的敏感信息(如密碼等);

  • 日誌全文檢索:全文檢索日誌內容及高亮顯示;

  • 關聯日誌查看:查看日誌產生時刻,日誌所屬應用關聯組件和應用的日誌;

  • 關鍵字告警:用戶本身定義告警規則,符合匹配規則發送郵件和短信通知。

最後一項監控內容,是業務指標實時監控。除了監控系統主動採集的信息,還有業務層指標須要進行監控,如週期內訂單數量、第三方數據同步結果等。這些業務層的指標數據,由各業務系統負責採集,而後上報到監控系統,監控系統完成圖表展示及告警通知。

四大方面詳解OPM系統設計

首先來了解一下OPM的系統體系架構,以下圖所示:

  • 中間件採集器:獨立部署多臺中間件性能指標採集器,經過Zookeeper實現故障轉移和任務分配。中間件採集器經過中間件的Java客戶端執行狀態查詢命令,解析命令結果獲得性能指標,因爲狀態查詢獲得的是最新累計值,採集器還負責計算週期內的均值、最大值、最小值等週期數據。中間件採集將採集到的數據實時上報到接收器集羣。

  • Agent監控代理:Agent監控代理部署在各服務器上,實時採集服務器的日誌文件內容、CPU負載、內存使用率、網卡上下行流量、磁盤讀寫速率、磁盤讀寫次數(IOPS)等。Agent採集到的數據實時上報到接收器集羣,對於日誌文件,爲防止阻塞,上傳過程還須要作流控和丟棄策略。

  • 代碼埋點:代碼埋點主要採集服務調用鏈數據,經過封裝的緩存訪問層、數據庫訪問層、消息隊列訪問層,以及分佈式服務框架(RPC),得到服務調用鏈耗時和錯誤信息。代碼埋點採集數據本機暫存,一分鐘合併上報一次到接收器集羣。

  • 業務指標上報:業務指標由各業務系統負責採集,上報到接收器集羣,上報週期和策略由各業務決定。

  • 接收器集羣:OPPO自研的Data Flow組件,架構參考Flume,內部包括輸入、通道、輸出三部分,將接收到的數據輸出到Kafka隊列,後文將做詳細介紹。

  • Kafka消息隊列:因爲監控數據容許丟失和重複消費,因此選擇高性能的Kafka作爲消息隊列,緩衝消息處理。

  • 消息處理集羣:消息處理集羣訂閱Kafka主題,並行處理消息,處理告警規則、發送通知、存儲到HBase和ES。

  • Hbase:HBase存儲指標類數據,管理控制檯經過查詢HBase生成實時圖表。

  • Elastic Search:存儲日誌內容,實現日誌全文檢索。

OPPO Data Flow實現了數據流配置和管理,設計參考Flume,內部包括Source(輸入)、通道(Channel)、輸出(Sink)三部分,通道是一個隊列,具有緩衝數據的功能。之因此不採用Flume,主要考慮以下幾個緣由:

  • Flume提供了良好的SourceàchannelàSink框架,但具體的Source、Sink須要本身去實現,以兼容oppo線上使用軟件版本,以及優化的參數配置。

  • Flume資源佔用較大,不適合做爲Agent部署在業務服務器

  • Flume配置文件採用properties方式,不如xml配置直觀,更不能管理界面來配置。

  • Flume管理界面不友好,不能查看輸入、輸出的實時流量圖表以及錯誤數量。

參考Flume 的設計思想,OPPO Data Flow是更易管理、配置更便捷的數據流工具。使用開源軟件,並不僅是拿來就用這一種方式,學習其設計精華,從而進一步改進也是一種方式。

實際上,Agent監控代理、中間件採集器、接收器集羣都是OPPO Data Flow組件,組合不一樣的Source和Sink。Source、Sink採用OSF服務框架開發,實現Agentà接收器的自動發現、負載均衡及故障轉移功能。

輸入(Source)

通道(Channel)

輸出(Sink)

Agent監控代理

TailFileSource

CPUSource

MemorySource

NetworkSource

DiskSource

MemoryChannel

HttpSink

中間件採集器

NginxSource

MySqlSource

MongoDBSource

RedisSource

JvmSource

MemcachedSource

MemoryChannel

HttpSink

接收器

HttpSource

FileChannel

KafkaSink


下圖爲Data Flow內嵌管理界面,能夠查看數據流量和錯誤信息,點擊名稱能夠查看歷史流量。

服務調用鏈是監控的重點,核心的核心,爲了打通服務調用鏈,OPPO開發了OSF(OPPO Service Framework)分佈式服務框架,並對緩存、數據庫、消息隊列操做進行封裝埋點,目的是透明的實現服務調用跟蹤。實現方式以下:

  • 在App請求的入口生成惟一requestID,放入ThreadLocal

  • 緩存訪問層代碼埋點,從ThradLocal取出requestID,記錄緩存操做耗時

  • 數據庫訪問層代碼埋點,從ThradLocal取出requestID,記錄數據庫操做耗時

  • 調用其它微服務 (RPC),將requestID傳遞到下一個微服務,微服務將接收到的requestID存入ThreadLocal,微服務內部的緩存、數據庫操做一樣記錄requestID操做耗時及錯誤信息。

  • 消息隊列寫入、消費代碼埋點,傳遞requestID,記錄消息消費耗時。

調用鏈數據龐大,沒法全量存儲,監控系統將週期內最慢Top1000請求,採樣的部分請求以及符合關鍵字規則請求的服務調用鏈存儲在HBase中,管理控制檯能夠快速分析查看。

分佈式服務框架是打通服務調用鏈的關鍵。開源的Dubbo應用普遍,考慮到Dubbo版本較長時間沒有更新(有些Dubbo依賴庫已經跟開發生態的其餘開源組件版本衝突)、代碼量較大,並且服務治理能力較弱,很難徹底掌控Dubbo的全部細節,而前文提到的OPPO自行開發的分佈式服務框架OSF,代碼精簡知足核心需求,與監控系統深度集成。

OSF實現微服務RPC調用requestID的傳遞,記錄每一個服務的調用耗時及錯誤信息,框架每分鐘彙總上報微服務調用耗時及錯誤信息到監控平臺。

OSF主要特性以下:

  • 支持RESTFul協議,容器支持Tomcat、Netty、JDK Http Server;

  • 支持TCP二進制協議,容器支持Netty;

  • 支持HTTP/2協議,測試中;

  • 支持Protobuf、JProtobuf、Kryo、FST、MessagePack、Jackson、GSON、Hessian序列化實現。

由消費方決定序列化方式:

  • 註冊中心基於MySQL,同時提供推送、client拉取兩種方式,保證服務發現可靠性;

  • 註冊中心提供HTTP API,支持多語言、移動設備;

  • 支持多數據中心部署;

  • I/O線程與工做線程池分離,提供方忙時當即響應client重試其它節點。

從可靠性及伸縮性角度來看,主要包括如下內容:

  • 接收器:接收器的輸入採用OSF RESTFul協議開發,經過註冊中心,client可以自動發現接收器節點的變化,經過client實現負載均衡及故障轉移,從而保證接收器的可靠性、伸縮性。

  • 中間件採集器:中間件採集器經過zookeeper選舉Master,由Mater來分配採集任務,採集器節點變化,選舉的Master從新分配採集任務,這樣任意增減採集器節點,都能從新平衡採集任務,保證採集任務的持續可靠運行。

  • 消息處理:因爲多個節點均分同一個kafka topic的消息而且實現高可用比較困難,OMP預先定義了若干個kafka topic,消息處理節點經過zookeeper選舉Master,由Master來分配Topic數量,當某個消息處理節點宕機,該節點負責的topic轉移到其餘節點繼續處理。

  • Agent監控代理:服務器上shell腳本按期檢查Agent狀態,不可用時自動重啓Agent,同時OMP維持與Agent之間的心跳消息,超過3個週期沒有收到Agent的心跳消息,OMP發送告警通知相關人員處理。

從OPPO的自主研發監控系統的實踐案例來看,一切應當從業務需求出發,目的是解決業務遇到的問題。面對開源軟件的選擇,要有所「爲」,有所「不爲」。業界有不少成熟的開源軟件,也有一些比較大膽的設計思想可供借鑑,但開源軟件並非拿過來就能用好這麼簡單的,選擇的原則可「管」可「控」。一個開源軟件,若是不能「掌控」,不夠簡單,那就不如不用,本身用土辦法也許反而會更好,出了問題至少還能想一想應急的辦法。一樣要具有「管理」性,否則黑盒子般運行,內心沒底,那做爲IT管理人員來講就睡不安心了。

本文做者羅代均 ,現就任於OPPO基礎技術團隊,從事監控平臺、服務框架等基礎技術開發工做。2005年畢業後,前後主導過通訊、移動金融、應用商店、PaaS平臺等領域多個產品系統設計開發、項目管理工做。本文由做者受權由InfoQ公衆平臺獨家首發。

相關文章
相關標籤/搜索