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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

如何快速构建服务发现的高可用能力

發布時間:2025/3/20 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何快速构建服务发现的高可用能力 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:十眠

背景

注冊中心作為承擔服務注冊發現的核心組件,是微服務架構中必不可少的一環。在 CAP 的模型中,注冊中心可以犧牲一點點數據一致性(C),即同一時刻每一個節點拿到的服務地址允許短暫的不一致,但必須要保證可用性(A)。因為一旦由于某些問題導致注冊中心不可用,或者服務連不上注冊中心,那么想要連接他的節點可能會因為無法獲取服務地址而對整個系統出現災難性的打擊。

一個真實的案例

全篇從一個真實的案例說起,某客戶在阿里云上使用 Kubernetes 集群部署了許多自己的微服務,由于某臺 ECS 的網卡發生了異常,雖然網卡異常很快恢復了,但是卻出現了大面積持續的服務不可用,業務受損。

我們來看一下這個問題鏈是如何形成的?

  • ECS 故障節點上運行著 Kubernetes 集群的核心基礎組件 CoreDNS 的所有 Pod,且低版本 Kubernetes 集群缺少 NodeLocal DNSCache 的特性,導致集群 DNS 解析出現問題。
  • 該客戶的服務發現使用了有缺陷的客戶端版本(Nacos-client 的 1.4.1 版本),這個版本的缺陷就是跟 DNS 有關——心跳請求在域名解析失敗后,會導致進程后續不會再續約心跳,只有重啟才能恢復。
  • 這個缺陷版本實際上是已知問題,阿里云在 5 月份推送了 Nacos-client 1.4.1 存在嚴重 bug 的公告,但客戶研發未收到通知,進而在生產環境中使用了這個版本。
  • 風險環環相扣,缺一不可。

    最終導致故障的原因是服務無法調用下游,可用性降低,業務受損。下圖示意的是客戶端缺陷導致問題的根因:

  • Provider 客戶端在心跳續約時發生 DNS 異常;
  • 心跳線程未能正確地處理這個 DNS 異常,導致線程意外退出了;
  • 注冊中心的正常機制是,心跳不續約,30 秒后自動下線。由于 CoreDNS 影響的是整個 Kubernetes 集群的 DNS 解析,所以 Provider 的所有實例都遇到相同的問題,整個服務所有實例都被下線;
  • 在 Consumer 這一側,收到推送的空列表后,無法找到下游,那么調用它的上游(比如網關)就會發生異常。
  • 回顧整個案例,每一環每個風險看起來發生概率都很小,但是一旦發生就會造成惡劣的影響。服務發現高可用是微服務體系中很重要的一環,當然也是我們時常忽略的點。在阿里內部的故障演練中,這一直是必不可少的一個環節。

    面向失敗的設計

    由于網絡環境的抖動比如 CoreDns 的異常,或者是由于某些因素導致我們的注冊中心不可用等情況,經常會出現服務批量閃斷的情況,但這種情況其實不是業務服務的不可用,如果我們的微服務可以識別到這是一種異常情況(批量閃斷或地址變空時),應該采取一種保守的策略,以免誤推從而導致全部服務出現"no provider"的問題,會導致所有的微服務不可用的故障,并且持續較長時間難以恢復。

    站在微服務角度上考慮,我們如何可以切段以上的問題鏈呢?以上的案例看起來是 Nacos-client 低版本造成的問題,但是如果我們用的是 zookeeper、eureka 等注冊中心呢?我們能拍著胸脯說,不會發生以上的問題嗎?面向失敗的設計原則告訴我們,如果注冊中心掛掉了,或者我們的服務連不上注冊中心了,我們需要有一個方式保證我們的服務正常調用,線上的業務持續不斷。

    本文介紹的是服務發現過程中的高可用的機制,從服務框架層面思考如何徹底解決以上的問題。

    服務發現過程中的高可用原理解析

    服務發現高可用-推空保護

    面向失敗的設計告訴我們,服務并不能完全相信注冊中心的通知的地址,當注冊中心的推送地址為空時候,服務調用肯定會出 no provider 錯誤,那么我們就忽略此次推送的地址變更。

    微服務治理中心提供推空保護能力

    • 默認無侵入支持市面上近五年來的 Spring Cloud 與 Dubbo 框架

    • 無關注冊中心實現,無需升級 client 版本

    服務發現高可用-離群實例摘除

    心跳續約是注冊中心感知實例可用性的基本途徑。但是在特定情況下,心跳存續并不能完全等同于服務可用。
    因為仍然存在心跳正常,但服務不可用的情況,例如:

    • Request 處理的線程池滿

    • 依賴的 RDS 連接異常導致出現大量慢 SQL

    • 某幾臺機器由于磁盤滿,或者是宿主機資源爭搶導致 load 很高

    此時服務并不能完全相信注冊中心的通知的地址,推送的地址中,可能存在一些服務質量低下的服務提供者,因此客戶端需要自己根據調用的結果來判斷服務地址的可用性與提供服務質量的好壞,來定向忽略某些地址。

    微服務治理中心提供離群實例摘除

    • 默認無侵入,支持市面上近五年來的 Spring Cloud 與 Dubbo 框架

    • 無關注冊中心實現,無需升級 client 版本

    • 基于異常檢測的摘除策略:包含網絡異常和網絡異常 + 業務異常(HTTP 5xx)

    • 設置異常閾值、QPS 下限、摘除比例下限

    • 摘除事件通知、釘釘群告警

    離群實例摘除的能力是一個補充,根據特定接口的調用異常特征,來衡量服務的可用性。

    動手實踐

    前提條件

    • 已創建 Kubernetes 集群,請參見創建 Kubernetes 托管版集群 [1]

    • 已開通 MSE 微服務治理專業版,請參見開通?MSE 微服務治理 [2]

    準備工作

    開啟 MSE 微服務治理

    1、開通微服務治理專業版:

  • 單擊開通 MSE 微服務治理 [3]
  • 微服務治理版本選擇專業版,選中服務協議,然后單擊立即開通。關于微服務治理的計費詳情,請參見價格說明 [4]
  • 2、安裝 MSE 微服務治理組件:

  • 在容器服務控制臺 [5] 左側導航欄中,選擇市場?>?應用目錄
  • 應用目錄頁面搜索框中輸入 ack-mse-pilot,單擊搜索圖標,然后單擊組件。
  • 詳情頁面選擇開通該組件的集群,然后單擊創建。安裝完成后,在命名空間 mse-pilotmse-pilot-ack-mse-pilot 應用,表示安裝成功。
  • 3、為應用開啟微服務治理:

  • 登錄?MSE 治理中心控制臺 [6]
  • 在左側導航欄選擇微服務治理中心?> Kubernetes 集群列表
  • Kubernetes 集群列表頁面搜索目標集群,單擊搜索圖標,然后單擊目標集群操作列下方的管理
  • 集群詳情頁面命名空間列表區域,單擊目標命名空間操作列下方的開啟微服務治理
  • 開啟微服務治理對話框中單擊確認
  • 部署 Demo 應用程序

  • 在容器服務控制臺 [5] 左側導航欄中,單擊集群
  • 集群列表頁面中,單擊目標集群名稱或者目標集群右側操作列下的詳情
  • 在集群管理頁左側導航欄中,選擇工作負載?>?無狀態
  • 無狀態頁面選擇命名空間,然后單擊使用 YAML 創建資源
  • 對模板進行相關配置,完成配置后單擊創建。本文示例中部署 sc-consumer、sc-consumer-empty、sc-provider,使用的是開源的 Nacos。
  • 部署示例應用(springcloud)

    YAML:

    # 開啟推空保護的 sc-consumerapiVersion: apps/v1kind: Deploymentmetadata:name: sc-consumerspec:replicas: 1selector:matchLabels:app: sc-consumertemplate:metadata:annotations:msePilotCreateAppName: sc-consumerlabels:app: sc-consumerspec:containers:- env:- name: JAVA_HOMEvalue: /usr/lib/jvm/java-1.8-openjdk/jre- name: spring.cloud.nacos.discovery.server-addrvalue: nacos-server:8848- name: profiler.micro.service.registry.empty.push.reject.enablevalue: "true"image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-consumer-0.1imagePullPolicy: Alwaysname: sc-consumerports:- containerPort: 18091livenessProbe:tcpSocket:port: 18091initialDelaySeconds: 10periodSeconds: 30# 無推空保護的sc-consumer-empty---apiVersion: apps/v1kind: Deploymentmetadata:name: sc-consumer-emptyspec:replicas: 1selector:matchLabels:app: sc-consumer-emptytemplate:metadata:annotations:msePilotCreateAppName: sc-consumer-emptylabels:app: sc-consumer-emptyspec:containers:- env:- name: JAVA_HOMEvalue: /usr/lib/jvm/java-1.8-openjdk/jre- name: spring.cloud.nacos.discovery.server-addrvalue: nacos-server:8848image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-consumer-0.1imagePullPolicy: Alwaysname: sc-consumer-emptyports:- containerPort: 18091livenessProbe:tcpSocket:port: 18091initialDelaySeconds: 10periodSeconds: 30# sc-provider---apiVersion: apps/v1kind: Deploymentmetadata:name: sc-providerspec:replicas: 1selector:matchLabels:app: sc-providerstrategy:template:metadata:annotations:msePilotCreateAppName: sc-providerlabels:app: sc-providerspec:containers:- env:- name: JAVA_HOMEvalue: /usr/lib/jvm/java-1.8-openjdk/jre- name: spring.cloud.nacos.discovery.server-addrvalue: nacos-server:8848image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/demo:sc-provider-0.3imagePullPolicy: Alwaysname: sc-providerports:- containerPort: 18084livenessProbe:tcpSocket:port: 18084initialDelaySeconds: 10periodSeconds: 30# Nacos Server---apiVersion: apps/v1kind: Deploymentmetadata:name: nacos-serverspec:replicas: 1selector:matchLabels:app: nacos-servertemplate:metadata:labels:app: nacos-serverspec:containers:- env:- name: MODEvalue: standaloneimage: nacos/nacos-server:latestimagePullPolicy: Alwaysname: nacos-serverdnsPolicy: ClusterFirstrestartPolicy: Always# Nacos Server Service 配置---apiVersion: v1kind: Servicemetadata:name: nacos-serverspec:ports:- port: 8848protocol: TCPtargetPort: 8848selector:app: nacos-servertype: ClusterIP

    我們只需在 Consumer 增加一個環境變量?profiler.micro.service.registry.empty.push.reject.enable=true,開啟注冊中心的推空保護(無需升級注冊中心的客戶端版本,無關注冊中心的實現,支持 MSE 的 Nacos、eureka、zookeeper 以及自建的 Nacos、eureka、console、zookeeper 等)

    分別給 Consumer 應用增加 SLB 用于公網訪問

    以下分別使用 {sc-consumer-empty} 代表 sc-consumer-empty 應用的 slb 的公網地址,{sc-consumer} 代表 sc-consumer 應用的 slb 的公網地址。

    應用場景

    下面通過上述準備的 Demo 來分別實踐以下場景

    • 編寫測試腳本

    vi curl.sh

    while :doresult=`curl $1 -s`if [[ "$result" == *"500"* ]]; thenecho `date +%F-%T` $resultelseecho `date +%F-%T` $resultfisleep 0.1done
    • 測試,分別開兩個命令行,執行如下腳本,顯示如下

    % sh curl.sh {sc-consumer-empty}:18091/user/rest2022-01-19-11:58:12 Hello from [18084]10.116.0.142!2022-01-19-11:58:12 Hello from [18084]10.116.0.142!2022-01-19-11:58:12 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!

    % sh curl.sh {sc-consumer}:18091/user/rest2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:13 Hello from [18084]10.116.0.142!2022-01-19-11:58:14 Hello from [18084]10.116.0.142!2022-01-19-11:58:14 Hello from [18084]10.116.0.142!2022-01-19-11:58:14 Hello from [18084]10.116.0.142!

    并保持腳本一直在調用,觀察 MSE?控制臺分別看到如下情況


    • 將 coredns 組件縮容至數量 0,模擬 DNS 網絡解析異常場景。

    發現實例與 Nacos 的連接斷開且服務列表為空。

    • 模擬 DNS 服務恢復,將其擴容回數量 2。

    結果驗證

    在以上過程中保持持續的業務流量,我們發現 sc-consumer-empty 服務出現大量且持續的報錯

    2022-01-19-12:02:37 {“timestamp”:“2022-01-19T04:02:37.597+0000”,“status”:500,“error”:“Internal Server Error”,“message”:“com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider”,“path”:"/user/feign"}2022-01-19-12:02:37 {“timestamp”:“2022-01-19T04:02:37.799+0000”,“status”:500,“error”:“Internal Server Error”,“message”:“com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider”,“path”:"/user/feign"}2022-01-19-12:02:37 {“timestamp”:“2022-01-19T04:02:37.993+0000”,“status”:500,“error”:“Internal Server Error”,“message”:“com.netflix.client.ClientException: Load balancer does not have available server for client: mse-service-provider”,“path”:"/user/feign"}

    相比之下,sc-consumer 應用全流程沒有任何報錯

    • 只有重啟了 Provider,sc-consumer-empty 才恢復正常

    相比之下,sc-consumer 應用全流程沒有任何報錯

    后續

    我們當發生推空保護后,我們會上報事件、告警至釘釘群,同時建議配合離群實例摘除使用,推空保護可能會導致 Consumer 持有過多的 Provider 地址,當 Provider 地址為無效地址時,離群實例摘除可以對其進行邏輯隔離,保證業務的高可用。

    保障云上業務的永遠在線,是 MSE 一直在追求的目標,本文通過面向失敗設計的服務發現高可用能力的分享,以及 MSE 的服務治理能力快速構建起服務發現高可用能力的演示,模擬了線上不可預期的服務發現相關異常發生時的影響以及我們如何預防的手段,展示了一個簡單的開源微服務應用應該如何構建起服務發現高可用能力。

    相關鏈接

    [1] 創建 Kubernetes 托管版集群

    https://help.aliyun.com/document_detail/95108.htm#task-skz-qwk-qfb

    [2] 開通?MSE 微服務治理

    https://help.aliyun.com/document_detail/347625.htm#task-2140253

    [3] 開通?MSE 微服務治理

    https://common-buy.aliyun.com/?commodityCode=mse_basic_public_cn

    [4]?價格說明

    ?https://help.aliyun.com/document_detail/170443.htm#concept-2519524?

    [5]?容器服務控制臺

    ?https://cs.console.aliyun.com?

    [6]?MSE 治理中心控制臺

    ?https://mse.console.aliyun.com?

    ?點擊???此處??,前往 MSE 官網查看更多!?

    總結

    以上是生活随笔為你收集整理的如何快速构建服务发现的高可用能力的全部內容,希望文章能夠幫你解決所遇到的問題。

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