1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        如何欺騙 Go Mod ?

        共 5525字,需瀏覽 12分鐘

         ·

        2021-09-02 20:32

        最近在做 prometheus 生態(tài)的 cortex 優(yōu)化工作,遇到一個比較坑的 go mod 的問題,這里分享一下。

        在正式展開這個話題之前,需要簡單的介紹下 cortex 和 thanos 這兩個項目。

        Prometheus 的局限性

        說到業(yè)務(wù)開發(fā)基本上都離不開監(jiān)控系統(tǒng),Prometheus 做為云原生的寵兒,以優(yōu)秀的設(shè)計,靈活的使用方式,以優(yōu)異成績從 CNCF 順利畢業(yè),也是很多公司做監(jiān)控的首選。

        但是呢,Promethues 也有其自身局限性,其中影響最大的就是其數(shù)據(jù)的高可用方案和集群方案。監(jiān)控也是業(yè)務(wù)系統(tǒng)的重中一環(huán),不能因為監(jiān)控系統(tǒng)宕機(jī)導(dǎo)致報警無法及時發(fā)出。

        Prometheus 官方也有提出聯(lián)邦方案來解決集群問題,但是這個方案極其復(fù)雜而且很多問題還是解決不了,于是就造就了另外兩個 CNCF 的沙箱項目:cortex 和 thanos。這兩個項目都是為了解決 Promethues 的集群,高可用的。

        由于這兩個項目要解決問題的目的是一致的,所以就會出現(xiàn)很多功能都是可以相互復(fù)用的,于是有趣的事情就發(fā)生了。

        cortex

        話說因為某些的需求,不得已需要更改下 thanos 的相關(guān)代碼。我本地調(diào)試的時候?qū)?cortex 依賴的 thanos 給 replace 了一下。

        replace github.com/thanos-io/thanos => /Users/hhf/goproject/cortex/thanos

        再等我編譯的時候,就編譯不過了

        # github.com/sercand/kuberesolver
        ../../../go/pkg/mod/github.com/sercand/[email protected]+incompatible/builder.go:108:82: undefined: resolver.BuildOption
        ../../../go/pkg/mod/github.com/sercand/[email protected]+incompatible/builder.go:163:32: undefined: resolver.ResolveNowOption

        這就讓人很無奈,別著急,我們看看這個 kuberesolver 是被誰依賴的。

        先看下被 replace 之前:

        ? go mod graph| grep kuberesolver
        github.com/weaveworks/[email protected] github.com/sercand/[email protected]+incompatible
        github.com/weaveworks/[email protected] github.com/sercand/[email protected]+incompatible
        github.com/weaveworks/[email protected] github.com/sercand/[email protected]+incompatible
        github.com/weaveworks/[email protected] github.com/sercand/[email protected]+incompatible
        github.com/weaveworks/[email protected] github.com/sercand/[email protected]+incompatible
        github.com/weaveworks/[email protected] github.com/sercand/[email protected]+incompatible
        github.com/thanos-io/[email protected] github.com/sercand/[email protected]+incompatible

        可以看到正常版本下,[email protected] 被 thanos 所依賴,[email protected] 被 weaveworks 所依賴。

        replace 之后

        ? go mod graph| grep kuberesolver
        github.com/weaveworks/[email protected] github.com/sercand/[email protected]+incompatible

        是不是很神奇,[email protected] 這個版本竟然消失了。由于 kuberesolver 的 v2.1.0 和 v2.4.0 是不兼容的,所以導(dǎo)致 replace 之后就無法編譯了。

        Gomod replace 語義

        其實這并不神奇,這個涉及到 Go mod 的 replace 語義,不過也是很容易讓人忽略的特性。

        replace directives:(https://golang.org/ref/mod#go-mod-file-replace)

        replace directives only apply in the main module’s go.mod file and are ignored in other modules. See Minimal version selection for details.

        其實很簡單,replace 只對主模塊(也就是你的當(dāng)前項目)是生效的??梢宰鋈缦碌目偨Y(jié):

        • 主模塊的 replace 對于被依賴的模塊是不生效的
        • 被依賴的模塊的 go.mod 的 replace 對主模塊也是不生效的

        所以,當(dāng) replace 之后,cortex 依賴的 thanos 的 replace 是不生效的。我們理一下依賴樹:

        • 主模塊 cortex => require github.com/weaveworks/common v0.0.0-20210419092856-009d1eebd624
        • weaveworks => requre github.com/sercand/kuberesolver v2.1.0+incompatible
        • 于是整體上 kuberesolver 就只有了 v2.1.0 了

        這個邏輯是跟 gomod 的 replace 語義是吻合的,也就是 replace 之后編譯不過是正確的。

        欺騙 gomod

        那就更加神奇了,為何 cortex 直接 require thanos 就能編譯成功,按照 gomod replace 語義來說,這也是編譯不過的才是正確的。

        因為根據(jù)文檔我們知道,replace 僅僅作用于主模塊,脫離了主模塊是一律不生效的,這個是毋庸置疑的。

        我做了個實驗放在了 https://github.com/georgehao/gomodtestmain ,有興趣的可以試一下,這個能驗證 gomod 是遵循 gomod replace 語義 和 MVS (最小版本選擇)算法的。

        問題基本陷入了僵局,我們?nèi)绾纹凭帜兀?/p>

        繼續(xù)使用 go mod graph 功能,來查看 cortex 依賴的 thanos 的依賴樹。

        github.com/thanos-io/[email protected] gopkg.in/[email protected]
        github.com/thanos-io/[email protected] github.com/Azure/[email protected]
        github.com/thanos-io/[email protected] k8s.io/[email protected]
        github.com/thanos-io/[email protected] gopkg.in/[email protected]
        github.com/thanos-io/[email protected] go.uber.org/[email protected]
        github.com/thanos-io/[email protected] go.elastic.co/apm/module/[email protected]
        ....
        github.com/thanos-io/[email protected] github.com/gogo/[email protected]

        由于這個依賴樹太長(700多行),我就不貼了,基本上也能看出來,cortex 依賴了 thanos N 多個版本,其中在最后一個版本中的 go.mod 中我們發(fā)現(xiàn)了一個有意思的東西:

        require (
          github.com/sercand/kuberesolver v2.4.0+incompatible // indirect

        也就是鬧了半天,由于 thanos 某個很古老的版本的 gomod require [email protected],讓 gomod 誤以為 cortex 依賴的 thanos 依然是 require 了 [email protected] 了。雖然 thanos 早就改成了 repace kuberesolver,但也就讓 cortex 順利編譯過去了。

        這算不算 gomod 的 bug 呢?

        為什么 cortex 會依賴 thanos 這么多版本呢?這就要回到開篇說的 cortex 和 thanos 功能復(fù)用的問題了。

        目前 cortex 和 thanos 這個兩個項目,基本上是這么依賴的:

        cortex 1.9.0 -> thanos v0.19.1-0.20210729154440-aa148f8fdb28
        thanos v0.19.1-0.20210729154440-aa148f8fdb28 -> cortex v1.8.1-0.20210422151339-cf1c444e0905
        cortex v1.8.1-0.20210422151339-cf1c444e0905 -> thanos v0.13.1-0.20210401085038-d7dff0c84d17
        ....

        cortex 與 thanos 之間的相互引用,就像俄羅斯套娃一樣,簡直就是 gomod 的噩夢。go mod replace 語義,竟然讓這兩個套娃給破解了。

        如何解決

        對應(yīng)如何cortex replace thanos 的問題,其實知道問題的根本所在,解決起來就很簡單了,有兩種方式吧:

        1. 由于 gomod MVS 算法,我們直接在主項目 cortex 中指定 kuberesolver 的版本為 v2.4.1
        2. 方案 1 僅對于向下兼容的項目比較適用,如果某項目沒有這個責(zé)任心的話,這么做可能是會出問題的,所以比較直接的解決辦法,直接修改 thanos 的 go.mod, 將 thanos 的所依賴的 kuberesolver 從 replace 挪到 require 中


        推薦閱讀



        福利

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


        瀏覽 90
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            97大香蕉视频 | 天堂a√8蜜桃 | 欧美激情偷拍 | ass中国年轻少妇pic精品 | 激情A片久久久久久app下载 | 一级干操小逼网站 | 欧美一级在线免费 | 婷婷中文字幕 | 91农村站街老熟女露脸 | 亚洲AV综合在线观看 |