<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用 golang gopacket 實現(xiàn)進程級流量監(jiān)控

          共 2622字,需瀏覽 6分鐘

           ·

          2021-11-03 16:56

          如何分析某服務(wù)器上哪個進程的流量多 ? 猜不少人都有類似的需求, 社區(qū)里已經(jīng)有 c 寫的 nethogs 工具, 該工具很方便的獲取流量較高的 TOP N 進程列表。

          既然有 nethogs 工具,為什么還需要用 goalng 來實現(xiàn)一遍 ?主要是 nethogs 不夠靈活,沒有開放接口供其他程序調(diào)用。對的,我們現(xiàn)在就需要這類接口。當(dāng)然,不是每個公司都有這類需求,大家通常都是當(dāng)流量異常時,登上去分析下異常流量。

          代碼

          項目名為 go-netflow, 代碼已經(jīng)提交到 github。

          地址為 https://github.com/rfyiamcool/go-netflow,有興趣的可以看看,記得點 star 哈。

          從設(shè)計到流量測試完畢,用了差不多 兩天半 的時間。go-netflow 的接口方面還算完善,最少滿足了我們?nèi)萜髟茍F隊及 sre 的需求。但他的 cli 終端部分很是簡陋,有興趣的同學(xué)可以幫忙提交 pr。

          實現(xiàn)

          像 promethues, openfalcon 這類開源監(jiān)控軟件,通過 /proc/net/snmp/proc/net/netstat 獲取連接和流量信息。

          • /proc/net/snmp 文件只是提供了主機各層的IP、ICMP、ICMPMsg、TCP、UDP詳細(xì)數(shù)據(jù)
          • /proc/net/netstat 文件提供了主機的收發(fā)包數(shù)、收包字節(jié)數(shù)據(jù)。

          這兩個文件只能看到主機級別的信息,沒法實現(xiàn)進程級別的流量采集。

          但是我們可以從其他路子來實現(xiàn)細(xì)粒度的進程級別的流量監(jiān)控。??

          通過 /proc/net/tcp/proc/net/udp 文件,我們可以拿到 tcp及udp 的四元組和 inode 信息。通過 /proc/{pid}/fd/ 可以拿到 pid 及 socket inode文件描述符的映射關(guān)系。

          那么怎么流量從哪里獲取?抓包,類似 tcpdump 這類使用 pcap 來抓包。

          這里詳細(xì)的說下,基于 pcap 的進程流量統(tǒng)計的實現(xiàn).

          1. 啟動階段掃描 /proc/net/tcp/proc/{pid}/fd/{socket inode}。構(gòu)建三個緩存hashmap
          • connInodesMap, 定義了 tcp 連接和 inode 號 的對應(yīng)關(guān)系。
          • inodePidMap, 定義了 inode 和 進程 pid 號 的對應(yīng)關(guān)系。
          • processMap,存放了進程的基本信息, 最近15秒的流量緩存及流量統(tǒng)計結(jié)果。
          使用 google 提高的 gopacket 庫包進行抓包, 拿到的數(shù)據(jù)往一個 channel 里面懟,如果隊列滿,則直接拋棄,可以理解為采樣。這個 channel 可以多協(xié)程消費,建議就一個消費者。從 channel 里拿到 packet 結(jié)構(gòu)對象,抽取解析為 ipLayer 和 tcpLayer 兩個層,從 ipLayer 獲取源和目標(biāo)的ip地址,從 tcpLayer 獲取源和目的端口號。通過 地址:源端口_目標(biāo)地址:目標(biāo)端口從 connInodeMap 里獲取 inode 索引號, 再通過 inode 到 inodePidMap 獲取 pid 進程號,再用 pid 到 processMap 里獲取進程對象,然后進行進出流量的累加計算。

          上面說的正常的流程,如果在 pcap 捕獲流量時期,有新的連接和新的進程創(chuàng)建了,那么就會拿不到對應(yīng)的 inode 或者 pid 信息。所以,需要定時重新掃描那幾個元數(shù)據(jù)文件,然后對這幾個緩存 map 進行增減處理。把暫未找到進程的 packet ,放到一個 ringbuffer 緩存里,每次定時掃描完 /proc 元數(shù)據(jù)后,再嘗試計算 ringbuffer 里的緩存。

          注意的幾個點:

          /proc 的那個幾個元數(shù)據(jù)不能使用 inotify 來監(jiān)聽,只能是定時掃描或者利用你通知來被動更新。udp也是同理,這里就不復(fù)述了。

          如何判斷是進出流量?

          如果 src.ip 是本地的ip地址,那么就是出流量,src.ip 不是本地ip地址,那么肯定就是進流量了。go-netflow 在啟動階段就需要獲取本地的ip地址列表。

          如何監(jiān)聽多個網(wǎng)卡

          google golang gopacket 庫默認(rèn)只能 openlive 一個網(wǎng)卡,沒找到可以 openlive 多個設(shè)備網(wǎng)卡的相關(guān)方法。平時我們用 tcpdump 抓包時,可以通過 -i any 匹配多個網(wǎng)卡。那么在 gopacket 如何實現(xiàn)多個設(shè)備網(wǎng)卡監(jiān)聽?實例化多個 openlive 實例不就行了,我居然還還提了 issue 詢問該問題,當(dāng)然沒人回復(fù)我了。

          如何限定 cpu/mem 占用資源

          tcpdump 在大流量網(wǎng)關(guān)下是相當(dāng)消耗 cpu 資源的,netflow 里做了一些簡單的限制,不是同步處理全量的包,而是扔到隊列中異步處理,如果隊列滿了,則直接丟棄。通過簡單的 atomic 計數(shù)器來進行限制處理的包數(shù)。

          但難免還是有意外造成 cpu 資源大量占用,如何限定 cpu 資源?

          這里直接使用 linux cgroups 來限定cpu及mem資源,new netflow 對象時可以傳入 cgroups 的參數(shù)。cpu為核數(shù),可以為 0.5 ,也就是僅占用一個 cpu core 的 50% 資源。mem 是限定的內(nèi)存量,單位是 MB,默認(rèn)為0,及為不限制。

          WithLimitCgroup(cpu?float64,?mem?int)

          寫入pcap文件

          netflow支持pcap文件的寫入,后面可通過 tcpdumpwireshark 來讀取 netflow 寫入的pcap文件。

          超時機制

          netflow 限定了默認(rèn)超時時間為 5 分鐘,當(dāng)超過 5 分鐘后會關(guān)閉所有設(shè)備的監(jiān)聽。這么做主要為了避免長時間運行忘了關(guān)閉,尤其是通過 netflow 接口來進行抓包的。

          效果

          a2d33d4937729d9547b949fd1b66c16a.webpimg

          優(yōu)化

          go-netflow 還是有一些優(yōu)化空間的, 內(nèi)存方面可以針對一些對象做復(fù)用, 使用 sync.pool 減少新對象的創(chuàng)建。CPU的開銷主要在 google gopacket 調(diào)用上, cgo 的調(diào)用一點也不便宜, 暫時沒有好的方法來優(yōu)化。另外, 進程的流量監(jiān)控?zé)o需太細(xì)致,粗粒度采樣足夠了。


          大家覺得文章對你有些作用!如果想賞錢,可以用微信掃描下面的二維碼,感謝! 另外再次標(biāo)注博客原地址 ?xiaorui.cc

          f1e27aa1ed780625f4e368eae397876a.webp

          瀏覽 99
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美a片在线看 | 欧美三级欧美一级 | 青青草a国产v | 三级草逼 | 超碰自拍 |