日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

瓜子二手车在 Dubbo 版本升级、多机房方案方面的思考和实践

發布時間:2024/8/23 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 瓜子二手车在 Dubbo 版本升级、多机房方案方面的思考和实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

隨著瓜子業務的不斷發展,系統規模在逐漸擴大,目前在瓜子的私有云上已經運行著數百個 Dubbo 應用,上千個 Dubbo 實例。瓜子各部門業務迅速發展,版本沒有來得及統一,各個部門都有自己的用法。隨著第二機房的建設,Dubbo 版本統一的需求變得越發迫切。幾個月前,公司發生了一次與 Dubbo 相關的生產事故,成為了公司 基于社區 Dubbo 2.7.3 版本升級的誘因。

接下來,我會從這次線上事故開始,講講我們這段時間所做的 Dubbo 版本升級的歷程以及我們規劃的 Dubbo 后續多機房的方案。

一、Ephermal節點未及時刪除導致provider不能恢復注冊的問題修復

事故背景

在生產環境,瓜子內部各業務線共用一套zookeeper集群作為dubbo的注冊中心。2019年9月份,機房的一臺交換機發生故障,導致zookeeper集群出現了幾分鐘的網絡波動。在zookeeper集群恢復后,正常情況下dubbo的provider應該會很快重新注冊到zookeeper上,但有一小部分的provider很長一段時間沒有重新注冊到zookeeper上,直到手動重啟應用后才恢復注冊。

排查過程

首先,我們統計了出現這種現象的dubbo服務的版本分布情況,發現在大多數的dubbo版本中都存在這種問題,且發生問題的服務比例相對較低,在github中我們也未找到相關問題的issues。因此,推斷這是一個尚未修復的且在網絡波動情況的場景下偶現的問題。

接著,我們便將出現問題的應用日志、zookeeper日志與dubbo代碼邏輯進行相互印證。在應用日志中,應用重連zookeeper成功后provider立刻進行了重新注冊,之后便沒有任何日志打印。而在zookeeper日志中,注冊節點被刪除后,并沒有重新創建注冊節點。對應到dubbo的代碼中,只有在FailbackRegistry.register(url)的doRegister(url)執行成功或線程被掛起的情況下,才能與日志中的情況相吻合。

public void register(URL url) {super.register(url);failedRegistered.remove(url);failedUnregistered.remove(url);try {// Sending a registration request to the server sidedoRegister(url);} catch (Exception e) {Throwable t = e;// If the startup detection is opened, the Exception is thrown directly.boolean check = getUrl().getParameter(Constants.CHECK_KEY, true)&& url.getParameter(Constants.CHECK_KEY, true)&& !Constants.CONSUMER_PROTOCOL.equals(url.getProtocol());boolean skipFailback = t instanceof SkipFailbackWrapperException;if (check || skipFailback) {if (skipFailback) {t = t.getCause();}throw new IllegalStateException("Failed to register " + url + " to registry " + getUrl().getAddress() + ", cause: " + t.getMessage(), t);} else {logger.error("Failed to register " + url + ", waiting for retry, cause: " + t.getMessage(), t);}// Record a failed registration request to a failed list, retry regularlyfailedRegistered.add(url);}}

在繼續排查問題前,我們先普及下這些概念:dubbo默認使用curator作為zookeeper的客戶端,curator與zookeeper是通過session維持連接的。當curator重連zookeeper時,若session未過期,則繼續使用原session進行連接;若session已過期,則創建新session重新連接。而ephemeral節點與session是綁定的關系,在session過期后,會刪除此session下的ephemeral節點。

繼續對doRegister(url)的代碼進行進一步排查,我們發現在CuratorZookeeperClient.createEphemeral(path)方法中有這么一段邏輯:在createEphemeral(path)捕獲了NodeExistsException,創建ephemeral節點時,若此節點已存在,則認為ephemeral節點創建成功。這段邏輯初看起來并沒有什么問題,且在以下兩種常見的場景下表現正常:

  • Session未過期,創建Ephemeral節點時原節點仍存在,不需要重新創建
  • Session已過期,創建Ephemeral節點時原節點已被zookeeper刪除,創建成功
  • public void createEphemeral(String path) {try {client.create().withMode(CreateMode.EPHEMERAL).forPath(path);} catch (NodeExistsException e) {} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e);}}

    但是實際上還有一種極端場景,zookeeper的Session過期與刪除Ephemeral節點不是原子性的,也就是說客戶端在得到Session過期的消息時,Session對應的Ephemeral節點可能還未被zookeeper刪除。此時dubbo去創建Ephemeral節點,發現原節點仍存在,故不重新創建。待Ephemeral節點被zookeeper刪除后,便會出現dubbo認為重新注冊成功,但實際未成功的情況,也就是我們在生產環境遇到的問題。

    此時,問題的根源已被定位。定位問題之后,經我們與 Dubbo 社區交流,發現考拉的同學也遇到過同樣的問題,更確定了這個原因。

    問題的復現與修復

    定位到問題之后,我們便開始嘗試本地復現。由于zookeeper的Session過期但Ephemeral節點未被刪除的場景直接模擬比較困難,我們通過修改zookeeper源碼,在Session過期與刪除Ephemeral節點的邏輯中增加了一段休眠時間,間接模擬出這種極端場景,并在本地復現了此問題。

    在排查問題的過程中,我們發現kafka的舊版本在使用zookeeper時也遇到過類似的問題,并參考kafka關于此問題的修復方案,確定了dubbo的修復方案。在創建Ephemeral節點捕獲到NodeExistsException時進行判斷,若Ephemeral節點的SessionId與當前客戶端的SessionId不同,則刪除并重建Ephemeral節點。在內部修復并驗證通過后,我們向社區提交了issues及pr。

    kafka類似問題issues:https://issues.apache.org/jira/browse/KAFKA-1387

    dubbo注冊恢復問題issues:https://github.com/apache/dubbo/issues/5125

    二、瓜子的dubbo升級歷程

    上文中的問題修復方案已經確定,但我們顯然不可能在每一個dubbo版本上都進行修復。在咨詢了社區dubbo的推薦版本后,我們決定在dubbo2.7.3版本的基礎上,開發內部版本修復來這個問題。并借這個機會,開始推動公司dubbo版本的統一升級工作。

    為什么要統一dubbo版本

  • 統一dubbo版本后,我們可以在此版本上內部緊急修復一些dubbo問題(如上文的dubbo注冊故障恢復失效問題)。
  • 瓜子目前正在進行第二機房的建設,部分dubbo服務也在逐漸往第二機房遷移。統一dubbo版本,也是為dubbo的多機房做鋪墊。
  • 有利于我們后續對dubbo服務的統一管控。
  • dubbo社區目前的發展方向與我們公司現階段對dubbo的一些訴求相吻合,如支持gRPC、云原生等。
  • 為什么選擇dubbo2.7.3

  • 我們了解到,在我們之前攜程已經與dubbo社區合作進行了深度合作,攜程內部已全量升級為 2.7.3 的社區版本,并在協助社區修復了 2.7.3 版本的一些兼容性問題。感謝攜程的同學幫我們踩坑~
  • dubbo2.7.3版本在當時雖然是最新的版本,但已經發布了2個月的時間,從社區issues反饋來看,dubbo2.7.3相對dubbo2.7之前的幾個版本,在兼容性方面要好很多。
  • 我們也咨詢了dubbo社區的同學,推薦升級版本為2.7.3。
  • 內部版本定位

    基于社區dubbo2.7.3版本開發的dubbo內部版本屬于過渡性質的版本,目的是為了修復線上provider不能恢復注冊的問題,以及一些社區dubbo2.7.3的兼容性問題。瓜子的dubbo最終還是要跟隨社區的版本,而不是開發自已的內部功能。因此我們在dubbo內部版本中修復的所有問題均與社區保持了同步,以保證后續可以兼容升級到社區dubbo的更高版本。

    兼容性驗證與升級過程

    我們在向dubbo社區的同學咨詢了版本升級方面的相關經驗后,于9月下旬開始了dubbo版本的升級工作。

  • 初步兼容性驗證
    首先,我們梳理了一些需要驗證的兼容性case,針對公司內部使用較多的dubbo版本,與dubbo2.7.3一一進行了兼容性驗證。經驗證,除dubboX外,dubbo2.7.3與其他dubbo版本均兼容。dubboX由于對dubbo協議進行了更改,與dubbo2.7.3不兼容。
  • 生產環境兼容性驗證
    在初步驗證兼容性通過后,我們與業務線合作,挑選了一些重要程度較低的項目,在生產環境對dubbo2.7.3與其他版本的兼容性進行了進一步驗證。并在內部版本修復了一些兼容性問題。
  • 推動公司dubbo版本升級
    在10月初,完成了dubbo兼容性驗證后,我們開始在各個業務線推動dubbo的升級工作。截止到12月初,已經有30%的dubbo服務的完成了版本升級。按照排期,預計于2020年3月底前完成公司dubbo版本的統一升級。
  • 兼容性問題匯總

    在推動升級dubbo2.7.3版本的過程整體上比較順利,當然也遇到了一些兼容性問題:

    • 創建zookeeper節點時提示沒有權限
      dubbo配置文件中已經配置了zookeeper的用戶名密碼,但在創建zookeeper節點時卻拋出KeeperErrorCode = NoAuth的異常,這種情況分別對應兩個兼容性問題:

      • issues:https://github.com/apache/dubbo/issues/5076
        dubbo在未配置配置中心時,默認使用注冊中心作為配置中心。通過注冊中心的配置信息初始化配置中心配置時,由于遺漏了用戶名密碼,導致此問題。
      • issues:https://github.com/apache/dubbo/issues/4991
        dubbo在建立與zookeeper的連接時會根據zookeeper的address復用之前已建立的連接。當多個注冊中心使用同一個address,但權限不同時,就會出現NoAuth的問題。
      • 參考社區的pr,我們在內部版本進行了修復。
    • curator版本兼容性問題

      • dubbo2.7.3與低版本的curator不兼容,因此我們默認將curator版本升級至4.2.0
      <dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>4.2.0</version> </dependency> <dependency><groupId>org.apache.curator</groupId><artifactId>curator-recipes</artifactId><version>4.2.0</version> </dependency>
      • 分布式調度框架elastic-job-lite強依賴低版本的curator,與dubbo2.7.3使用的curator版本不兼容,這給dubbo版本升級工作帶來了一定阻塞。考慮到elastic-job-lite已經很久沒有人進行維護,目前一些業務線計劃將elastic-job-lite替換為其他的調度框架。
    • openFeign與dubbo兼容性問題
      issues:?https://github.com/apache/dubbo/issues/3990

    dubbo的ServiceBean監聽spring的ContextRefreshedEvent,進行服務暴露。openFeign提前觸發了ContextRefreshedEvent,此時ServiceBean還未完成初始化,于是就導致了應用啟動異常。
    參考社區的pr,我們在內部版本修復了此問題。

    • RpcException兼容性問題
      dubbo低版本consumer不能識別dubbo2.7版本provider拋出的org.apache.dubbo.rpc.RpcException。因此,在consumer全部升級到2.7之前,不建議將provider的com.alibaba.dubbo.rpc.RpcException改為org.apache.dubbo.rpc.RpcException
    • qos端口占用
      dubbo2.7.3默認開啟qos功能,導致一些混部在物理機的dubbo服務升級時出現qos端口占用問題。關閉qos功能后恢復。
    • 自定義擴展兼容性問題
      業務線對于dubbo的自定義擴展比較少,因此在自定義擴展的兼容性方面暫時還沒有遇到比較難處理的問題,基本上都是變更package導致的問題,由業務線自行修復。
    • skywalking agent兼容性問題
      我們項目中一般使用skywalking進行鏈路追蹤,由于skywalking agent6.0的plugin不支持dubbo2.7,因此統一升級skywalking agent到6.1。

    三、dubbo多機房方案

    瓜子目前正在進行第二機房的建設工作,dubbo多機房是第二機房建設中比較重要的一個話題。在dubbo版本統一的前提下,我們就能夠更順利的開展dubbo多機房相關的調研與開發工作。

    初步方案

    我們咨詢了dubbo社區的建議,并結合瓜子云平臺的現狀,初步確定了dubbo多機房的方案。

  • 在每個機房內,部署一套獨立的zookeeper集群。集群間信息不同步。這樣就沒有了zookeeper集群跨機房延遲與數據不同步的問題。
  • dubbo服務注冊時,僅注冊到本機房的zookeeper集群;訂閱時,同時訂閱兩個機房的zookeeper集群。
  • 實現同機房優先調用的路由邏輯。以減少跨機房調用導致的不必要網絡延遲。
  • 同機房優先調用

    dubbo同機房優先調用的實現比較簡單,相關邏輯如下:

  • 瓜子云平臺默認將機房的標志信息注入容器的環境變量中。
  • provider暴露服務時,讀取環境變量中的機房標志信息,追加到待暴露服務的url中。
  • consumer調用provider時,讀取環境變量中的機房標志信息,根據路由策略優先調用具有相同標志信息的provider。
  • 針對以上邏輯,我們簡單實現了dubbo通過環境變量進行路由的功能,并向社區提交了pr。

    dubbo通過環境變量路由pr:?https://github.com/apache/dubbo/pull/5348


    原文鏈接
    本文為阿里云原創內容,未經允許不得轉載。

    總結

    以上是生活随笔為你收集整理的瓜子二手车在 Dubbo 版本升级、多机房方案方面的思考和实践的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。