Open-falcon Agent模塊rpc通信過程


1.Agent模塊內容簡述

在解析Agent模塊通信過程的同時,需要對Agent模塊的內容進行簡單的概述,主要包括以下幾個方面,是支持Agent通信模塊的基礎內容。


1.1 Open-falcon簡述

Open-falcon是小米公司開源的一個企業級運維監控系統,主要使用go語言編寫。總體結構分爲服務端與客戶端,站在使用者的角度上看,可以有非常多個客戶端對應一個服務端。這裏的說的客戶端就是即將要介紹的Agent模塊,包括Agent在監控機器的工作過程,以及Agent與服務端的通信過程。服務端是接收Agent上傳的數據,保存、處理而且展示給相應的運維人員。也可以通過服務端提供的Web界面管理Agent的工作、更新等等。Open-falcon的系統架構比較複雜,Agent主要與HBS心跳服務器以及transfer數據上報模塊進行通信,還包括獲取主機的監控信息等。下圖爲小米監控官方文檔的架構圖。

 


1.2 Agent的系統位置

Agent在運維監控系統的位置具體如下:

 



 

如上圖,整個運維監控系統相當於一個網絡環境,各個主機的Agent位於網絡的末端,使用rpc通信的方式與服務器進行數據通信,包括:HBS心跳服務器、transfer數據轉發。


1.3 Agent的簡單介紹

Agent是一個golang開發的daemon程序,用於自發現的採集單機的各種數據和指標,這些指標包括不限於以下幾個方面,共計200多項指標。

         CPU相關

         磁盤相關

         IO

         Load

         內存相關

         網絡相關

         端口存活、進程存活

         ntp offset(插件)

         某個進程資源消耗(插件)

         netstatss等相關統計項採集

         機器內核配置參數

只要安裝了falcon-agent的機器,就會自動開始採集各項指標,主動上報,不需要用戶在server做任何配置。採集以上監控數據之外,Agent需要通過與服務端的HBS進行心跳連接通信,包括主機信息上報、同步插件、同步監控進程端口等等。falcon-agent,可以在github上找到 : https://github.com/open-falcon/agent


1.4 Agent的通信對象

 Agent的通信對象主要有以下兩個:

a、HBS心跳服務器

Agent按照配置文件說明(默認以一分鐘爲週期)定期給HBS發送心跳連接請求,上報主機存活信息、同步主機監控插件、同步主機監控進程端口等。

b、transfer數據轉發服務

Agent 按照配置文件說明(默認以一分鐘爲週期)定期給transfer發送主機個項監控數據,包括:cpu、磁盤、內存等等。


1.5 Agent的配置文件

Agent的配置文件位於Agent目錄下,命名爲cfg.josn。包括:debug、hostname、ip、plugin、heartbeat、transfer、http、collector、ignore多個選項。其中,heartbeat對應心跳服務器配置,transfer對應數據轉發配置。如下圖,Agent配置文件內容:

         debug爲打開調試模式、hostname填寫主機名字、ip爲主機網絡地址、heartbeat包括:開關,rpc地址端口,連接時間週期,超時時間、transfer類比heartbeat、collector收集網卡信息、ignore爲不監控的項目。




2.Agent模塊通信方式

Agent模塊使用單向同步的rpc通信方式,把數據信息以發送請求的方式推送到服務端,並且返回發送錯誤以及請求響應結果。


2.1 rpc通信方式

Agent模塊推送信息時,使用tcp協議連接rpc服務端,推送數據並且接受服務器返回的響應數據後,關閉rpc連接,等待下一次的通信。正常來說,只有在Agent向HBS服務器請求插件同步、進程端口同步時,服務器纔會返回相應數據,其他的請求只會返回請求狀態,成功或者失敗。


2.2 rpc數據結構

rpc數據結構:SingleConnRpcClient、Call、Client等,這裏只關注SingleConnRpcClient即可,其他的大部分是go語言封裝的rpc通信相關結構體。

struct {
       sync.Mutex
       rpcClient *rpc.Client
       RpcServer string
       Timeout  time.Duration
}



sync.MutexGo語言的排它鎖,其他開發語言會不一樣,根據情況使用。此處目的是實現rpc通信進程與主進程同步,主進程等待rpc通信結束後才繼續往下執行任務。

rpcClient :聲明一個rpc通信的客戶端,用於連接服務端並且發送消息。

RpcServer :聲明一個rpc通信的服務端描述,是rpcClient的通信對象,讀取配置文件。

Timeout   :rpc連接超時,讀取配置文件。

 

3.Agent模塊通信內容採集

Agent模塊通信內容的採集包括:面向HBS心跳服務器內容採集、面向transfer數據傳送服務器內容採集。把採集到的主機存活信息、主機監控數據週期性上報給服務器。


3.1  內容採集相關項目

A、HBS心跳服務器

Agent與心跳服務器的通信有三個方面:主機存活信息、同步進程端口、同步監控插件信息。

主機存活信息:主機名字、主機IP地址、Agent當前版本、插件當前版本內容等信息。



同步進程端口:向HBS服務器發送當前Agent主機名字與一個校驗和,第一次發送一個空的校驗和,HBS服務器每次返回一個校驗和,並且保存爲當前檢驗和,下一次發送當前檢驗和。



同步監控插件:向HBS服務器發送當前Agent主機名字,等待HBS返回插件列表,並且處理插件列表,此處理過程在Agent模塊通信內容處理體現。



 可信IP地址:此功能暫時不考慮

B、transfer數據傳送服務

 Agent傳送到transfer的主機監控數據包括如下幾個方面:

        機器負載信息, cpu.idle/load.1min//mem.memfree.percent/df.bytes

        硬件信息,比如功耗、風扇轉速、磁盤是否可寫服務監控數據,比如某個接口每分鐘調用的次數,latency等等

        數據庫、HBase、Redis、Openstack等開源軟件的監控指標,具體信息如下:


CPU相關採集項,計算方法:通過採集/proc/stat來得到,大家可以參考sar命令的統計輸出來理解。

cpu.idle:Percentage of time that the CPU or CPUs were idle and the system didnot have an outstanding disk I/O request.

cpu.busy:與cpu.idle相對,他的值等於100減去cpu.idle。

cpu.guest:Percentage of time spent by the CPU or CPUs to run a virtualprocessor.

cpu.iowait:Percentage of time that the CPU or CPUs were idle during which thesystem had an outstanding disk I/O request.

cpu.irq:Percentage of time spent by the CPU or CPUs to service hardwareinterrupts.

cpu.softirq:Percentage of time spent by the CPU or CPUs to service softwareinterrupts.

cpu.nice:Percentage of CPU utilization that occurred while executing at theuser level with nice priority.

cpu.steal:Percentage of time spent in involuntary wait by the virtual CPU orCPUs while the hypervisor was servicing another virtual processor.

cpu.system:Percentage of CPU utilization that occurred while executing at thesystem level (kernel).

cpu.user:Percentage of CPU utilization that occurred while executing at theuser level (application).

cpu.cnt:cpu核數。

cpu.switches:cpu上下文切換次數,計數器類型。

 

磁盤相關採集項,計算方法:先讀取/proc/mounts拿到所有掛載點,然後通過syscall.Statfs_t拿到blocks和inode的使用情況。每個metric都會附加一組tag描述,類似mount=$mount,fstype=$fstype,其中$mount是掛載點,比如/home,$fstype是文件系統,比如ext4。

df.bytes.free:磁盤可用量,int64

df.bytes.free.percent:磁盤可用量佔總量的百分比,float64,比如32.1

df.bytes.total:磁盤總大小,int64

df.bytes.used:磁盤已用大小,int64

df.bytes.used.percent:磁盤已用大小佔總量的百分比,float64

df.inodes.total:inode總數,int64

df.inodes.free:可用inode數目,int64

df.inodes.free.percent:可用inode佔比,float64

df.inodes.used:已用的inode數據,int64

df.inodes.used.percent:已用inode佔比,float64

 

megacli工具輸出,使用 megacli 工具讀取 RAID 相關信息,每個metric都會附件一組tag描述,用來標明所屬PD或者 VD,PD格式爲PD=Enclosure_ID:SLOT_ID,比如PD=32:0表明第一塊磁盤 ,VD=0 表明第一個邏輯磁盤。

sys.disk.lsiraid.pd.Other_Error_Count

sys.disk.lsiraid.pd.Predictive_Failure_Count

sys.disk.lsiraid.pd.Drive_Temperature

sys.disk.lsiraid.pd.Firmware_state:如果值不爲0,則此物理磁盤出現問題

sys.disk.lsiraid.vd.cache_policy:如果值不爲0,表示此邏輯磁盤緩存策略和設置不符

sys.disk.lsiraid.vd.state: 如果值不爲0,表示此邏輯磁盤出現問題


SMART工具輸出,使用smartctl 工具讀取磁盤 SMART 信息,目前所有指標僅作爲數據收集,不一定意味磁盤損壞(只是表示概率變大),每個metric都會有一組tag描述,表明盤符,例如device=/dev/sda。

sys.disk.smart.Reallocated_Sector_Ct

sys.disk.smart.Spin_Retry_Count

sys.disk.smart.Reallocated_Event_Count

sys.disk.smart.Current_Pending_Sector

sys.disk.smart.Offline_Uncorrectable

sys.disk.smart.Temperature_Celsius

 

分區讀寫監控,測試所有已掛載分區是否可讀寫,每個metric都會有一組tag描述,表示掛載點,比如mount=/home

sys.disk.rw:如果值不爲0,表明此分區讀寫出現問題


IO相關採集項,計算方法:每秒採集一次/proc/diskstats,計算差值,都是計數器類型的。每個metric都會有一組tag描述,形如device=$device,用來表示具體的設備,比如sda1、sdb。用戶可以參考iostat的幫助文檔來理解具體的metric含義。

disk.io.ios_in_progress:Number of actual I/O requestscurrently in flight.

disk.io.msec_read:Total number of ms spent by all reads.

disk.io.msec_total:Amount of time during which ios_in_progress >= 1.

disk.io.msec_weighted_total:Measure of recent I/O completiontime and backlog.

disk.io.msec_write:Total number of ms spent by all writes.

disk.io.read_merged:Adjacent read requests merged in a single req.

disk.io.read_requests:Total number of reads completedsuccessfully.

disk.io.read_sectors:Total number of sectors read successfully.

disk.io.write_merged:Adjacent write requests merged in a single req.

disk.io.write_requests:total number of writes completedsuccessfully.

disk.io.write_sectors:total number of sectors writtensuccessfully.

disk.io.read_bytes:單位是byte的數字

disk.io.write_bytes:單位是byte的數字

disk.io.avgrq_sz:下面幾個值就是iostat -x 1看到的值

disk.io.avgqu-sz

disk.io.await

disk.io.svctm

disk.io.util:是個百分數,比如56.43,表示56.43%


機器負載相關採集項,計算方法:讀取/proc/loadavg,都是原始值類型的:

load.1min

load.5min

load.15min


內存相關採集項

計算方法:讀取/proc/meminfo 中的內容,其中的mem.memfree是free+buffers+cached,mem.memused=mem.memtotal-mem.memfree。用戶具體可以參考free命令的輸出和幫助文檔來理解每個metric的含義。

mem.memtotal:內存總大小

mem.memused:使用了多少內存

mem.memused.percent:使用的內存佔比

mem.memfree

mem.memfree.percent

mem.swaptotal:swap總大小

mem.swapused:使用了多少swap

mem.swapused.percent:使用的swap的佔比

mem.swapfree

mem.swapfree.percent


網絡相關採集項,計算方法:讀取/proc/net/dev的內容,每個metric都附加有一組tag,形如iface=$iface,標明具體那個interface,比如eth0。metric中帶有in的表示流入情況,out表示流出情況,total是總量in+out,支持的metric如下:

net.if.in.bytes

net.if.in.compressed

net.if.in.dropped

net.if.in.errors

net.if.in.fifo.errs

net.if.in.frame.errs

net.if.in.multicast

net.if.in.packets

net.if.out.bytes

net.if.out.carrier.errs

net.if.out.collisions

net.if.out.compressed

net.if.out.dropped

net.if.out.errors

net.if.out.fifo.errs

net.if.out.packets

net.if.total.bytes

net.if.total.dropped

net.if.total.errors

net.if.total.packets

 

端口採集項,計算方法,通過ss -ln,來判斷指定的端口是否處於listen狀態。原始值類型,值要麼是1:代表在監聽,要麼是0,代表沒有在監聽。每個metric都附件一組tag,形如port=$port,$port就是具體的端口。

net.port.listen


機器內核配置

kernel.maxfiles: 讀取的/proc/sys/fs/file-max

kernel.files.allocated:讀取的/proc/sys/fs/file-nr第一個Field

kernel.files.left:值=kernel.maxfiles-kernel.files.allocated

 kernel.maxproc:讀取的/proc/sys/kernel/pid_max


ntp採集項,使用 ntpq-pn 獲取本機時間相對於 ntp 服務器的 offset。

sys.ntp.offset: 本機偏移時間,單位爲ms,值過大或者爲0則表明有異常,需要報警


進程監控,proc.num:判斷某個進程的數目,這裏需要分兩個場景,一種是根據進程的名字來判定,比如name=sshd;另外一種是根據cmdline來判定,比如Java的應用進程名可能都是java,根據第一種情況沒法做區分,此時可以配置cmdline,如cmdline=./falcon_agent-c./cfg.ini進程資源監控

process.cpu.all:進程和它的子進程使用的sys+user的cpu,單位是jiffies

process.cpu.sys:進程和它的子進程使用的sys cpu,單位是jiffies

process.cpu.user:進程和它的子進程使用的user cpu,單位是jiffies

process.swap:進程和它的子進程使用的swap,單位是page

process.fd:進程使用的文件描述符個數

process.mem:進程佔用內存,單位byte


ss命令輸出

ss.orphaned

ss.closed

ss.timewait

ss.slabinfo.timewait

ss.synrecv

ss.estab

本節內容來自於open-falcon對linux運維基礎採集項的說明。


3.2  內容採集數據結構

A、HBS心跳服務器

Agent與心跳服務器的通信有三個方面:主機存活信息、同步進程端口、同步監控插件信息。

主機存活信息:主機名字、主機IP地址、Agent當前版本、插件當前版本內容等信息。



使用rpc通信發送以上信息後,返回rpc通信結果,發送失敗寫入日誌,成功與否,進入下一次通信週期再次發送。發送源代碼如下:



time.Sleep(interval)是通信週期,interval來自於配置文件。


同步進程端口:向HBS服務器發送當前Agent主機名字與一個校驗和,第一次發送一個值爲nil的校驗和,HBS服務器每次返回一個校驗和,並且保存爲當前檢驗和,下一次發送當前檢驗和。



發送HBS請求後,Agent等待HBS返回同步端口的信息,並且保存到BuiltinMetricResponse結構體當中,用於後續的處理

           


BuiltinMetricResponse結構體包括多個BuiltinMetric結構體,BuiltinMetric保存單個端口或者進程的信息。



          

具體函數源碼如下:

         


Agent獲取到進程端口信息後,處理操作將在Agent模塊通信內容處理說明。

同步監控插件:向HBS服務器發送當前Agent主機名字,等待HBS返回插件列表,並且處理插件列表,此處理過程在Agent模塊通信內容處理體現。



注意:這哪即使使用了AgentHeartbeatRequest結構體封裝RPC通信請求,但是同步插件的操作沒有發送Checksum字符串,區別同步進程端口,具體過程體現在源代碼當中。

                   


AgentPluginsResponse結構用於接收保存HBS返回的插件列表,等待後續處理。

具體源代碼如下:

                


可信IP地址:此功能暫時不考慮

RPC通信相關結構體

定義一個RPC通信結構體,封裝rpcClient客戶端結構體

               


sync.MutexGo語言的排它鎖,其他開發語言會不一樣,根據情況使用。此處目的是實現rpc通信進程與主進程同步,主進程等待rpc通信結束後才繼續往下執行任務。

rpcClient :聲明一個rpc通信的客戶端,用於連接服務端並且發送消息。

RpcServer :聲明一個rpc通信的服務端描述,是rpcClient的通信對象,讀取配置文件。

Timeout   :rpc連接超時,讀取配置文件。

go語言中rpc.Client的原型如下

             


聲明兩個RPC通信客戶端結構體用於HBS、transfer的通信。

             


B、transfer數據傳送服務器

Agent發送給transfer服務器的監控數據包括多個項目,每個項目有多個指標。Agent的收集器把監控數據週期性讀取到內存中,拼接好之後發送給服務器。在收集器裏定義一個用於綜合管理主機監控數據的結構體:Mappers


Interval是從配置文件讀過來的超時時間,Fs 是一個函數指針數組,保存多個函數指針。Mappers結構體內初始化了四個方面的監控數據包括:機器負載信息、硬件信息、服務器監控信息、開源軟件監控指標。即Mappers中已經規定包含四個FuncsAndInterval,每個FuncsAndInterval中有一個Fs,Fs是一個model.MetricValue結構體數組指針,四個Fs內容如下:

a、AgentMetrics,CpuMetrics,NetMetrics,KernelMetrics,LoadAvgMetrics,MemMetrics,DiskIOMetrics,IOStatsMetrics,NetstatMetrics,ProcMetrics,UdpMetrics

b、DeviceMetrics

c、PortMetrics,SocketStatSummaryMetrics

d、DuMetrics

具體初始化代碼如下:



上面每一個Metrics是一個函數,每個函數讀取相關標籤的監控信息,讀取標籤信息重新封裝model.MetricValue結構體並且返回。



如下是MetricValue結構體原型:



最後,把各個MetricValue結構體返回一個[]*model.MetricValue結構體指針數組。示例:CpuMetrics



CpuMetrics是Fs: []func() []*model.MetricValue中的成員,同時也是一個函數,收集器循環遍歷得到CpuMetrics,執行上面的函數內容,獲取相關的監控信息,傳遞給GaugeValue(),調用NewMetricValue()重新封裝MetricValue結構體,在CpuMetrics函數結束返回包含多個MetricValue的[]*model.結構體指針數組。

如下爲GaugeValue()函數原型:



metric對應cpu.idle、cpu.busy、cpu.user等標籤,val 是當前標籤的值,其他的暫時保持默認。至於,標籤對應的監控信息獲取方法就不再展開解析了。

如下圖,是Agent發送數據到transfer服務器的數據結構一個整體概覽,Mappers裏面四個FuncsAndInterval都有各自的Fs,可以看成Mappers裏面有四個Fs,而Fs裏面封裝了跟多的Metrics,這些Metrics指向一項獲取各個監控指標的函數,該函數也是返回[]*model.MetricValue類型,保存着各個model.MetricValue結構體內容。    



CpuMetrics包括idle, busy, user, nice, system, iowait, irq, softirq, steal, guest,switches等model.MetricValue。

具體採集信息過程源碼如下:

      


Collect()爲主函數所調用,Collect()爲每一個FuncsAndInterval創建一個collect(int64(v.Interval), v.Fs)來處理所對應的Fs,Fs中包含多個model.MetricValue,而這些model.MetricValue又是一個函數,讀取相應項目的監控信息,每一個項目裏面又有多個標籤,每一個標籤都是一個model.MetricValue,後來把全部的model.MetricValue都放到了一個[]func() []*model.MetricValue裏面發送出去。

      


 

4.Agent模塊通信交互過程

該模塊主要描述通信過程的概述,包括:監控數據上報的過程、主機存活狀態的上報、主機進程端口的同步、主機插件信息的同步。也是劃分爲兩個部分說明。


4.1  模塊交互簡述

交互過程主要是Agent向服務器發送RPC消息,等待服務器返回結果,並且進行處理,而下面的通信交互過程並不是全部都要處理返回結果。

A、HBS心跳服務器

主機存活信息

使用RPC通信,週期性發送主機存活報告,檢驗發送消息結果,發送出錯完成寫日誌操作,發送成功與否進入下一次發送週期,等待消息發送。

同步進程端口

使用RPC通信,週期性發送Agent.BuiltinMetricsHBS心跳連接請求,包括主機名與一個校驗和。校驗和的初始值爲”nil”,HBS響應心跳連接,返回進程端口信息、校驗和、時間戳。進程端口信息存儲起來等待處理,校驗和保存起來用於下一次心跳連接請求。時間戳保存起來,用於下一次時間校驗,若下一次HBS相應的時間戳比當前時間戳小,直接跳過當前週期,不做進程端口信息處理。同時,校驗和沒有發生改變是不做任何進程端口信息處理。因爲校驗和沒有發生改變,意味着進程端口信息也沒有發生改變。進程端口信息處理結束後,進入下一個通信週期。

同步監控插件

使用RPC通信,週期性發送Agent.MinePluginsHBS心跳連接請求,包含當前主機名。HBS響應心跳連接,返回監控插件信息、時間戳。監控插件信息保存起來等待後續處理,時間戳保存起來,用於下一次時間校驗,若下一次HBS相應的時間戳比當前時間戳小,直接跳過當前週期,不做監控插件信息處理。監控插件信息處理結束後,進入下一個通信週期。

B、transfer數據傳送服務器

使用RPC通信,週期性發送Transfer.Update信息,包含一個Mapperers中的全部項目中標籤的主機監控信息,讀到每一個標籤重新封裝到一個項目當中。然後,發送主機監控信息,檢驗發送消息結果,發送出錯完成寫日誌操作,發送成功與否進入下一次發送週期,等待消息發送。


4.2 交互數據結構

數據結構統一在Agent模塊通信內容採集中體現。


5.Agent模塊通信內容處理

Agent模塊通信內容的處理主要針對:服務器返回給Agent的響應信息,特別是同步信息的處理。


5.1  內容處理相關項目

A、HBS心跳服務器

主機存活信息

沒有相關信息的處理

同步進程端口

處理進程信息或者處理端口信息或者獲取某個目錄的大小(例如:log目錄是否發生改變)。

同步監控插件

處理監控插件的信息,由服務器下發的插件信息與本地的插件信息作比較,然後處理插件信息。

B、 transfer數據傳送服務器

沒有相關信息的處理

該節建議參考Agent源碼以及Agent源碼解釋視頻。


5.2 內容處理數據結構

數據結構統一在Agent模塊通信內容採集中體現。具體數據處理過程如下:

A、 HBS心跳服務器

主機存活信息

沒有內容處理,只是出錯時完成寫日誌操作。

同步進程端口

a、net.port.listen:端口信息,根據下發的端口號,設置需要監控端口的值。從結構體BuiltinMetricResponseresp中查找是否存在net.port.listen,找到則添加到需要監控端口之中。



b、du.bs:監控目錄大小,從結構體BuiltinMetricResponseresp中查找是否存在du.bs,找到則添加到需要監控端口之中。



c、proc.num:進程數量(當前進程名字存在進程的個數),從結構體BuiltinMetricResponseresp中查找是否存在proc.num,找到則添加到需要監控端口之中。



 

resp保存HBS服務器返回的進程端口信息。

           


最後調用函數,更新進程端口信息,代碼如下圖:

 


更新端口信息:g.SetReportPorts(ports)

更新進程信息:g.SetReportProcs(procs)

更新監控目錄:g.SetDuPaths(paths)


其中更新進程信息根據進程名字與進程命令進行分類,兩種tag不能同時出現。

 

同步監控插件

如下是插件信息的結構體:這裏只關心FilePath 插件的路徑

        

      

Agent把HBS服務器返回的插件保存在結構體AgentPluginsResponse  resp裏面:



Plugins存放了HBS返回的全部插件路徑。然後列出全部插件,獲取到真實的插件名字,最後更新插件。

           


 

B、transfer數據傳送服務器

沒有內容處理,只是出錯時完成寫日誌操作。


6.Agent模塊通信過程總結

6.1 通信過程總結

本文檔基本完成了Agent模塊RPC通信的過程,包括Agent的簡單介紹、通信方式、通信內容採集、通信交互過程以及通信內容的處理。不論是否存在疑問,都需要參考官方文檔以及Agent源碼解讀,本文檔只是加快了解Agent通信過程的腳步,並不是全部。


6.2 其他補充說明

a、沒有處理IP白名單,open-falcon功能已經穩定不再需要後門調試,而且這樣做非常不安全。

b、 具體Agent升級相關操作並沒有做說明,具體關聯應該不大。

b、Agent通信模塊之外的內部細節並沒有說分,例如:監控信息如何獲取、如何設置監聽端口、如何設置監聽進程、如何設置、獲取、更新、啓動插件等等。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章