其他訊息中介軟體及場景應用(下3)

語言: CN / TW / HK

版權宣告:歡迎轉載,但是看在我辛勤勞動的份上,請註明來源:http://blog.csdn.net/yinwenjie(未經允許嚴禁用於商業用途!)                https://blog.csdn.net/yinwenjie/article/details/51516329

目錄(?)[+]

===================================
(接上文:《架構設計:系統間通訊(32)——其他訊息中介軟體及場景應用(下2)》)

5-7、解決方案三:非侵入式方案

以上兩種方案中為了讓業務系統能夠整合日誌採集功能,我們或多或少需要在業務系統端編寫一些程式碼。雖然通過一些程式碼結構的設計,可以減少甚至完全隔離這些程式碼和業務程式碼的耦合度,但是畢竟需要業務開發團隊花費精力對這些程式碼進行維護,業務系統部署時業務對這些程式碼的配置資訊做相應的調整。

這裡我們再為讀者介紹一種非侵入式的日誌採集方案。我們都知道業務系統被訪問時,都會產生一些訪問痕跡。 同樣以“瀏覽商品詳情”這個場景為例,當訪問者開啟一個“商品詳情”頁面時(URL記為A),那麼首先Nginx的access日誌就會有相應的80埠的訪問日誌,如果“商品詳情”的資訊並非全靜態的,那麼接下來業務服務上工作的程式碼還會在Log4j檔案上輸出相應的訪問資訊(如果開發人員使用了Log4j的話)。我們要做的事情就是找一款軟體,將這些日誌資訊收集起來並存放在合適的位置,以便資料分析平臺隨後利用這些資料進行分析工作。

當然為了保證這些日誌資訊中有完整的原始屬性,業務系統的開發人員和運維人員應該事先協調一種雙方都認可的日誌描述格式,
以及日誌檔案的儲存位置和儲存規則等資訊。


5-7-1、Flume介紹

Flume is a distributed, reliable, and available service for 
efficiently collecting, aggregating, and moving large amounts of log 
data. It has a simple and flexible architecture based on streaming data 
flows. It is robust and fault tolerant with tunable reliability 
mechanisms and many failover and recovery mechanisms. It uses a simple 
extensible data model that allows for online analytic application.


以上文字引用來自Apache Flume官網(http://flume.apache.org/)。大意是:Flume是一個分散式的、具有高可靠的、高可用性的用於有效地收集、彙總日誌資料的服務。它的架構基於資料流,簡單靈活。。。我們要介紹的非侵入日誌採集方案,就基於Apache Flume進行實現。

Apache Flume非常非常簡單,並且官方給出的使用者手冊已經足夠您瞭解它的使用方式和工作原理(http://flume.apache.org/FlumeUserGuide.html),所以本文並不會專門介紹Flume的安裝和基本使用,並試著將Flume的使用融入到例項講解中。如果您希望更深入學習Flume的設計實現,筆者還是建立您閱讀Flume的原始碼,在其官網的使用者文件中已經給出了幾個關鍵的實現類,通過這些實現類即可倒查Flume使用的各種設計模式:

圖片.png


5-7-2、方案設計

Flume和業務服務系統在物理伺服器上分別獨立工作,在作業系統層面上是兩個獨立的程序,並沒有任何關聯。Flume只對作業系統上的檔案系統、或者指定的網路埠又或者RPC服務進行資料流監控(Flume中稱之為Source)。當指定的檔案、指定的網路埠或者指定的RPC服務有新的資料產生時,Flume就會按照預先的配置將這些資料傳輸到指定位置(Flume中稱之為Sink)。這個指定位置可以是網路地址、可以是檔案系統還可以是另一個軟體。Source和Sink之間的資料流傳輸通告,稱之為Channel。


圖片.png

上圖來源於Apache Flume官方網站,是一個關於Flume中Source、Sink的例子。在這個例子中,Flume採用一個HTTP Source,用來接收外部傳來的HTTP協議的資料;Flume的Sink端採用HDFS Sink,用來將從Channel中得到的資料寫入HDFS。那麼基於上文介紹的Apache Flume工作特性,我們採用如下思路進行日誌採集方案三的設計:

圖片.png

  • 日誌資料的來源和收集

上圖中業務系統工作在140、141、142三個物理節點上,併產生Log4j檔案。當然您也可以直接使用JBOSS、Tomcat等服務的原生日誌檔案作為日誌資料來源。有的情況下,我們需要對Nginx等代理服務上Http請求情況進行分析,那麼可以使用Nginx的access.log檔案作為日誌資料的源是來源。您還可以根據設計需要,在每一個物理節點上同時監控多個檔案

在140、141、142三個物理節點上,還分別安裝了Apache Flume。他們的工作任務都是一樣的,即從指定的需要監控的日誌檔案中讀取資料變化,通過配置好的Channel送到指定的Sink中。在上圖的設定中既是監控Log4j檔案的變化,通過Channel使用Thrift RPC方式傳輸到遠端伺服器192.168.61.138的6666埠。

  • 日誌資料集中

物理節點192.168.61.138負責收集來自於140、141、142三個物理節點通過Thrift RPC傳輸到6666埠的日誌資料資訊。並且通過Channel傳輸到適當的儲存方案中,這些適當的儲存方案可能是HDFS、可能是某一種MQ還可能是某種物件儲存系統(例如Ceph)、甚至可能就是本地檔案系統。

5-7-3、方案配置過程

  • 192.168.61.140

上文已經說明,192.168.61.140物理節點上Apache Flume的主要任務是監控業務服務的Log4j日誌檔案,當日志文件產生新的資料時,通過Flume中已經配置好的Channel傳送至指定的Sink。配置資訊如下:

agent.sources = s1
agent.channels = c1
agent.sinks = t1

# source ===========================
# log4j.log檔案的變化將作為flume的源
agent.sources.s1.type = exec
agent.sources.s1.channels = c1
agent.sources.s1.command = tail -f /logs/log4j.log

# channel ==================================
# 連線source和sink的通道
agent.channels.c1.type = memory
agent.channels.c1.capacity = 1000

# sink t1 ===================================
# 通過通道送來的資料,將通過 thrift RPC呼叫,送到138節點的6666埠
agent.sinks.t1.type = thrift
agent.sinks.t1.channel = c1
agent.sinks.t1.hostname = 192.168.61.138
agent.sinks.t1.port = 6666


192.168.61.141和192.168.61.142兩個物理節點也承載了業務服務,並且業務服務會將日誌輸出到同樣的Log4j的位置。所以這兩個節點上Apache Flume的配置和以上140物理節點中Apache Flume的配置一致。這裡就不再對另外兩個物理節點的配置進行贅述了。

另外需要注意的是agent.sources.s1.command配置的Linux tail 命令。tail命令可以顯示當前檔案的變化情況,如果您只代有-f引數,即表示從檔案末尾的最後10行開始對檔案的變化情況進行監控。如果這樣配置,那麼當Flume啟動時,就會認為Log4j檔案中已經存在的10行記錄為新收到的日誌資料,造成誤發

要解決這個問題可以使用-n引數,並指定從檔案的最末尾開始監控檔案變化情況:

# 應該使用
tail -f -n 0 /logs/log4j.log

# 注意:tail -f /logs/log4j.log 命令相當於:
# tail -f -n 10 /logs/log4j.log


  • 192.168.61.138

192.168.61.138節點上的Flume,用來收集140-142節點通過Thrift RPC傳來的日誌資料。這些資料收集後,將被138節點上的Flume存放到合適的位置。這些位置可以是HDFS,HBASE、本地檔案系統還可以是Apache Kafka等。

agent.sources = s1
agent.channels = c1
agent.sinks = t1

# thrift ==================
# 使用thrift rpc監聽節點的6666埠,以便接收資料
agent.sources.s1.type = thrift
agent.sources.s1.channels = c1
agent.sources.s1.bind = 0.0.0.0
agent.sources.s1.port = 6666

# sink hdfs ==============
# agent.sinks.t1.type = hdfs
# agent.sinks.t1.channel = c1
# agent.sinks.t1.hdfs.path = hdfs://ip:port/events/%y-%m-%d/%H%M/%S
# agent.sinks.t1.hdfs.filePrefix = events-
# agent.sinks.t1.hdfs.round = true
# agent.sinks.t1.hdfs.roundValue = 10
# agent.sinks.t1.hdfs.roundUnit = minute

# sink=====================
# 為了檢測整個配置是否正確,可先輸出到控制檯
agent.sinks.t1.type = logger
agent.sinks.t1.channel = c1

# channel=================
agent.channels.c1.type = memory
agent.channels.c1.capacity = 1000

上配置檔案中,為了檢視這個採集系統的配置是否成功,我們將在Flume控制檯作為Sink進行輸出。註釋的資訊是HDFS作為Sink的配置。

5-8、解決方案三優化

上一小節的解決方案三中,最薄弱的位置是承擔日誌資料彙總任務的138節點。整個日誌收集主架構中只存在一個這樣的彙總節點,一旦138節點由於各種原因宕機主架構就將崩潰。即使138節點能夠穩定工作,由於138節點同時承擔多個物理節點傳來的資料日誌,那麼它也極有可能成為效能瓶頸。所以我們需要找到一種方案三中薄弱位置的辦法。

5-8-1、Flume支援的高可用模式

還好,Apache Flume為我們提供了非常簡單實用的高可用模式:Load_balance模式和Failover模式。這兩種工作模式都是對多個Sink如何配合工作進行描述:

  • Load_balance模式:

這種工作模式提供了多個sinks負載均衡的能力。Load_balance會維護一個active sinks列表,基於這個列表,使用round_robin(輪詢排程) 或者 random(隨機) 的選擇機制(預設為:round_robin),向sinks集合。基本上這兩種選擇方式已經夠用了,如果您對排程選擇有特別的要求,則可以通過繼承AbstractSinkSelector類來實現自定義的選擇機制。

  • Failover模式:

這種工作模式提供了多個sinks的故障轉移能力。Failover維護了兩個sinks列表,Failover list和Live list,在Failover模式下,Flume會優先選擇優先順序最高的Sink作為主要的傳送目標。當這個Sink連續失敗時Flume會把這個Sink移入Failover list,並且設定一個冷凍時間。在這個冷凍時間之後,Flume又會試圖使用這個Sink傳送資料,一旦傳送成功,這個Sink會被重新移入Live list。

為了保證能夠為資料彙總節點分擔效能壓力,我們使用Load_balance模式進一步演示對資料彙總節點的優化。

5-8-2、使用Load_balance模式

圖片.png

從上圖中可以看到在方案三的優化方法中,我們使用一個新的節點(192.168.61.139)和原有的138節點一起構成一組負載節點,共同承擔日誌資料的彙總任務。那麼前端日誌監控節點(140、141、142三個節點)也需要做相應的配置檔案修改。

5-8-3、Load_balance配置過程

  • 修改192.168.61.140節點

agent.sources = s1
agent.channels = c1
# 設定了兩個sink
agent.sinks = lt1 lt2
agent.sinkgroups = g1

# source ===========================
# 資料來源還是來自於log4j日誌檔案的新增資料
agent.sources.s1.type = exec
agent.sources.s1.channels = c1
agent.sources.s1.command = tail -f -n 0 /log/log4j.log

# sink lt1 ===================================
agent.sinks.lt1.type = thrift
agent.sinks.lt1.channel = c1
agent.sinks.lt1.hostname = 192.168.61.138
agent.sinks.lt1.port = 6666

# sink lt2 ==================================
agent.sinks.lt2.type = thrift
agent.sinks.lt2.channel = c1
agent.sinks.lt2.hostname = 192.168.61.139
agent.sinks.lt2.port = 6666

# channel ==================================
agent.channels.c1.type = memory
agent.channels.c1.capacity = 1000

# sinkgroup ===============================
# 兩個sink:lt1 lt2 設定成一組sink。並使用load_balance模式進行工作
agent.sinkgroups.g1.sinks = lt1 lt2
agent.sinkgroups.g1.processor.type = load_balance
agent.sinkgroups.g1.processor.backoff = true
agent.sinkgroups.g1.processor.selector = random

141和142兩個日誌資料監控節點的配置和140節點的配置一致,所以同樣不再贅述了。

  • 新增192.168.61.139節點

agent.sources = s1
agent.channels = c1
agent.sinks = t1

# thrift==================
agent.sources.s1.type = thrift
agent.sources.s1.channels = c1
agent.sources.s1.bind = 0.0.0.0
agent.sources.s1.port = 6666

# sink=====================
agent.sinks.t1.type = logger
agent.sinks.t1.channel = c1

# channel=================
agent.channels.c1.type = memory
agent.channels.c1.capacity = 1000

新增的139節點上Flume的配置資訊和原有138節點上Flume的配置資訊是一致的。這樣保證了無論日誌資料被髮送到哪一個節點,都能正確進行儲存。

5-9 方案三的侷限性

日誌採集方案三也存在侷限性:這種方案不適合用於開放性日誌採集系統。也就是說,如果您的日誌採集系統需要像“百度站長統計工具”那樣,從設計之初的目標就是要釋出給網際網路上各個站點使用的。那麼這種基於作業系統日誌變化,並採用第三方軟體完成採集過程的架構方案就不適用。

另外,方案三我們使用了Thrift RPC進行網路通訊。這個方式是可以用於真正的生產環境的,但是需要進行更多的配置項指定。以下兩個連結地址是分別是使用thrift作為source和sink時可以使用的配置屬性。

http://flume.apache.org/FlumeUserGuide.html#thrift-source
http://flume.apache.org/FlumeUserGuide.html#thrift-sink

除了Thrift RPC以外,筆者還推薦使用Avro。

6、場景應用——Online遊戲:×××彈道日誌功能

//TODO 這是一個釦子,後續的文章會講到

7、下文介紹

經過《架構設計:系統間通訊(19)——MQ:訊息協議(上)》開始的14篇文章,我們基本上介紹了訊息佇列的基本知識和使用實戰。從下文開始我們轉向ESB企業服務匯流排的知識講解。