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(插件)
某個進程資源消耗(插件)
netstat、ss等相關統計項採集
機器內核配置參數
只要安裝了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.Mutex :Go語言的排它鎖,其他開發語言會不一樣,根據情況使用。此處目的是實現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.Mutex :Go語言的排它鎖,其他開發語言會不一樣,根據情況使用。此處目的是實現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通信模塊之外的內部細節並沒有說分,例如:監控信息如何獲取、如何設置監聽端口、如何設置監聽進程、如何設置、獲取、更新、啓動插件等等。