<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>

          Go 服務(wù)自動收集線上問題現(xiàn)場

          共 2739字,需瀏覽 6分鐘

           ·

          2022-12-01 11:29

          前言

          對于 pprof,相信熟悉 Go 語言的程序員基本都不陌生,一般線上的問題都是靠它可以快速定位。但是實際項目中,很多時候我們?yōu)榱诵阅芏疾粫_啟它,但是出了問題又要靠它來分析。

          好在 go-zero 已經(jīng)幫我們很好的集成進來了,我們只需要像開關(guān)一樣去開啟、關(guān)閉它即可,這樣我們就可以配合運維監(jiān)控,當(dāng)出現(xiàn) cpu、內(nèi)存等異常情況時候,自動開始開啟收集(比如大半夜你睡的正香的時候),那么第二天可以通過分析當(dāng)時的采樣還原現(xiàn)場,那我們看看 go-zero 是如何做的。

          源碼分析

          我們可以看 go-zero 源碼位置 https://github.com/zeromicro/go-zero/blob/master/core/proc/signals.go

                func?init()?{
          ??go?func()?{
          ????...
          ????signals?:=?make(chan?os.Signal,?1)
          ????signal.Notify(signals,?syscall.SIGUSR1,?syscall.SIGUSR2,?syscall.SIGTERM)

          ????for?{
          ??????v?:=?<-signals
          ??????switch?v?{
          ??????...
          ??????case?syscall.SIGUSR2:
          ????????if?profiler?==?nil?{
          ??????????profiler?=?StartProfile()
          ????????}?else?{
          ??????????profiler.Stop()
          ??????????profiler?=?nil
          ????????}
          ??????...
          ????}
          ??}()
          }

          服務(wù)啟動的時候,go-zero 在 init 初始化了監(jiān)聽信號操作(gracefulStop 也是通過這里通知的,這里不展開講了),可以看到在接收到 syscall.SIGUSR2 信號時候,如果是第一次就開始收集,第二次就停止收集,看到這塊可能瞬間就明白了,我們只需要在服務(wù)器執(zhí)行 kill -usr2 <服務(wù)進程id> 就可以開始收集這個服務(wù)的 pprof 信息了,再執(zhí)行一次就停止了收集,就可以將這些文件導(dǎo)出到本地,使用 go tool pprof 分析。

          一次線上實戰(zhàn)

          我們線上有一個 mq 的服務(wù)監(jiān)控告警,內(nèi)存占用比較高,這時候我打開 grafana 看到服務(wù)內(nèi)存累計占用的確異常,如下圖:

          301e751250e4f0af0b5608608ca78504.webp

          這時候到線上找到這個服務(wù)的服務(wù)器,執(zhí)行了 ps aux | grep xxx_mq,查詢到了這個 mq 服務(wù)的進程 ID 是 21181,我們這時候就可以給這個 xxx_mq 服務(wù)發(fā)送信號收集 pprof 信息:kill -usr2 21181

          第一次執(zhí)行了這個命令后,在對應(yīng)服務(wù)的 access.log 日志中可以看到 enablepprof,當(dāng)我們再次執(zhí)行 kill -usr2 21181access.log 日志中可以看到 disablepprof 信息,這時候代表收集完成了。值得注意的是收集的信息都在 /tmp 文件夾下,以這個服務(wù)名命名的如下:

                -?xxxx-mq-cpu-xxx.pprof
          -?xxxx-mq-memory-xxx.pprof
          -?xxxx-mq-mutex-xxx.pprof
          -?xxxx-mq-block-xxx.pprof
          -?.......

          這時候就可以下載對應(yīng)的 pprof 去本地分析,可以使用 go tool pprof xxxx-mq-memory-xxx.pprof,也可以配合 graphviz 使用 web ui 查看,由于我這邊通過命令行就快速定位了問題,就沒用使用 web ui。

          我使用 go tool pprof xxxx-**-mq-memory-xxx.pprof 然后進入命令行交互,使用 top 30 查看前面占用較高的資源。

          6a893a22c7116d9f4f13d69fa2bb0f37.webp

          前面基本是底層序列化等操作,發(fā)現(xiàn)主要問題集中在紅色框中導(dǎo)致持續(xù)上漲的內(nèi)存,因為業(yè)務(wù)同學(xué)在 mq 中消費完了消息又向下游其他的mq服務(wù)使用 publisher 發(fā)送一個 mq 消息,每次發(fā)送都調(diào)用一個 NewPublisher 然后在 defer close,恰恰這個 mq 服務(wù)又大量消息消費又特別頻繁,導(dǎo)致內(nèi)存不斷上漲,最終解決方案將 NewPublishersvcCtx 中初始化一個 client 就可以了,沒必要每次都要 NewPublisher,世界又恢復(fù)清凈了。

          寫在最后

          想一下 go-zero 給了我們 pprof 開關(guān),讓我們很方便的實現(xiàn)分析問題,但是不是所有問題都是一直存在的,比如半夜突發(fā)內(nèi)存、cpu 過高,早上起來服務(wù)正常了,這怎么排查?所以我們希望如果異常了,能保留問題現(xiàn)場,那我們是不是可以配合運維監(jiān)控實現(xiàn)自動保存問題現(xiàn)場呢?比如內(nèi)存、cpu 連續(xù)超過 80% 指標3分鐘的話,我們就調(diào)用這個開關(guān)收集,之后我們就可以根據(jù)這個文件來分析問題了,這樣就達到自動化了。

          項目地址

          go-zero 微服務(wù)框架:https://github.com/zeromicro/go-zero

          go-zero 微服務(wù)最佳實踐項目:https://github.com/Mikaelemmmm/go-zero-looklook



          推薦閱讀


          福利
          我為大家整理了一份 從入門到進階的Go學(xué)習(xí)資料禮包 ,包含學(xué)習(xí)建議:入門看什么,進階看什么。 關(guān)注公眾號 「polarisxu」,回復(fù)? ebook ?獲??;還可以回復(fù)「進群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。


          瀏覽 14
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  精品久久久久久久久久久久 | 日本特一级免费 | 色综合偷拍 | 欧美亚洲影院 | 国产高清在线视频 |