微服務中的服務發現

微服務中的服務發現

什么是服務發現

服務發現是微服務架構中的關鍵機制,用于確定各個微服務的地址。例如,在一個 API Server 服務中,我們可能需要調用 User 服務來處理用戶注冊、登錄和信息查詢,也可能需要 Product 服務來獲取商品相關信息。那么,如何發現并訪問這些服務呢?

傳統服務發現方法

最簡單的方式是使用數據庫存儲服務名稱及其對應的地址。每當有新的服務實例啟動時,我們將其地址注冊到數據庫中。客戶端在訪問該服務時,可以從數據庫中查詢到對應的地址并發起請求。

Kitex 框架中,我們通常使用 ETCD 作為服務注冊與發現的數據庫,下面通過一個示例演示如何實現。

在 ETCD 中注冊服務

在服務啟動前,我們需要將其注冊到 ETCD 中,以便其他微服務能夠發現并訪問它:

func kitexInit() (opts []server.Option) {cfg := config.GetConfig()// RegistryAddress為etcd數據庫地址r, _ := etcd.NewEtcdRegistry(cfg.Registry.RegistryAddress)// address為user服務的地址address := cfg.KitexConfig.Address + cfg.KitexConfig.Portaddr, _:= net.ResolveTCPAddr("tcp", address)// 保存server的配置信息。opts = append(opts,server.WithServiceAddr(addr),server.WithRegistry(r),server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: cfg.KitexConfig.Service,},),)return
}func main() {config.InitConfig()   // 初始化配置文件db.InitDB()           // 初始化dbopts := kitexInit()   // 初始化服務配置信息svr := user.NewServer(new(UserServiceImpl), opts...) //創建newservererr := svr.Run() // 開啟server服務,并實時注冊到etcd數據庫中if err != nil {log.Println(err.Error())}
}

這樣,我們就成功開啟了一個服務,并且成功將其注冊到etcd數據庫中。使其他服務可以通過 ETCD 進行發現和訪問。

通過客戶端調用服務

在微服務架構中,我們需要使用客戶端來調用 User 服務,并通過 ETCD 進行服務發現:

func initUserClient() userservice.Client {// 1. 創建 etcd 服務解析器(連接注冊中心)r, err := etcd.NewEtcdResolver(registryAddr)if err != nil {log.Fatalln(r)}// 2. 配置客戶端選項:聲明使用 etcd 作為服務發現源opts := []client.Option{client.WithResolver(r),}// 生命etcd進行服務發現。userClient, err := userservice.NewClient("douyinec.user", opts...)if err != nil {log.Fatalln(err)}return userClient
}

處理多個服務實例的情況

每次調用userClient客戶端時,client會向etcd查詢,微服務地址,并發送請求。如果 etcd 里存儲了多個 user service 的地址(即多個實例部署了 user service),那么 client 會從 etcd 獲取所有可用的 user service 地址,并根據負載均衡策略選擇一個進行調用。

Kitex 默認使用隨機負載均衡,但可以通過 client.WithLoadBalancer() 設定不同的策略,比如輪詢`(Round Robin)、最小連接數(Least Connection)等。

處理服務變更(崩潰或重啟)

如果 User 服務實例不可用了,會發生什么?

  1. User 服務啟動后,會通過etcd.NewEtcdRegistry(...)注冊自身地址到 ETCD
  2. 在運行期間,Kitex 定期向 ETCD 發送心跳,用于維持服務的可用狀態。
  3. 如果 User 服務崩潰或手動關閉:
  • 它將停止發送心跳信號
  • ETCD 發現心跳超時(例如 10s 內未收到心跳)
  • ETCD 自動將該 User 服務實例從注冊列表中移除

如果 User 服務重新啟動到了新的地址,客戶端還能找到它嗎?

客戶端每次請求時都會向 ETCD 查詢最新的 User 服務地址,不會緩存舊的地址。

User 服務重新啟動并注冊到新的地址時,客戶端會自動獲取最新的服務位置。

這樣,無論 User 服務的實例數量如何變化,客戶端始終能夠找到可用的服務實例,實現了動態的服務發現和負載均衡。

k8s中服務發現的方法

Kubernetes(k8s)中,每個應用服務對應一個 Servicek8s通過service進行服務發現,它充當了訪問 Pod 的穩定入口。Service 通過 Endpoint 關聯到具體的 Pod,并按照一定的負載均衡策略將請求路由到后端的 Pod。

Service、Endpoint 與 Pod 的關系

在 Kubernetes 中,

  • Pod 是運行應用程序的最小單位,每個 Pod 可能包含一個或多個容器。
  • Service 提供了一個穩定的訪問入口,它會自動發現符合標簽選擇器(selector)的 Pod,并將請求負載均衡地轉發給它們。
  • Endpoint 記錄了 Service 關聯的 Pod 的實際 IP 和端口。

整個流程如下:

  • Service 負責管理和暴露一組 Pod。
  • Endpoint 維護了當前 Service 關聯的 Pod 列表。
  • kube-proxy 監聽 Service 變更,并基于 Endpoint 配置負載均衡規則。
  • 客戶端訪問 Service 時,kube-proxy 負責將請求轉發給 Endpoint 中的 Pod。

查看當前 Kubernetes 集群中的 Service

我們可以通過kubectl get service -o wide查看當前存在的所有service。實例輸出:

kubectl get service -o wide
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)                       AGE    SELECTOR
kubernetes     ClusterIP      10.43.0.1       <none>           443/TCP                       297d   <none>
manager        NodePort       10.43.196.96    <none>           8090:32545/TCP                191d   app.oam.dev/component=manager
localstorage   NodePort       10.43.183.49    <none>           8189:30621/TCP                191d   app.oam.dev/component=localstorage
scheduler      NodePort       10.43.8.18      <none>           5525:31965/TCP                191d   app.oam.dev/component=scheduler
redis          NodePort       10.43.167.133   <none>           6379:32155/TCP                191d   app.oam.dev/component=redis

其中 redis 服務的 Cluster-IP 10.43.167.133,我們可以繼續查詢其 Endpoint。

查看 Service 關聯的 Endpoints

使用以下命令查看 kubectl get endpoints redis -o wide。實例輸出:

 kubectl get endpoints redis -o wide
NAME    ENDPOINTS         AGE
redis   10.42.0.18:6379   191d

從這里可以看到,redis 服務對應的 Pod 運行在 10.42.0.18:6379

查看 Service 詳細信息

之后通過kubectl describe service redis查看詳情。實例輸出:

IP Families:              IPv4
IP:                       10.43.167.133
IPs:                      10.43.167.133
Port:                     redis  6379/TCP
TargetPort:               6379/TCP
NodePort:                 redis  32155/TCP
Endpoints:                10.42.0.18:6379
Session Affinity:         None
External Traffic Policy:  Local```,

這里,這里的 Endpoints 字段表明,該 Service 的流量被轉發到了 10.42.0.18:6379 上運行的 Pod。其中IP字段標識ServiceClusterIPPort: redis 6379/TCP定義Service 的端口映射。TargetPort標識Service 關聯的 Pod 實際監聽的端口,流量會被轉發到該端口。

Service 的服務發現機制

Kubernetes 主要通過兩種方式實現服務發現:

  1. 環境變量
  • KubernetesPod 啟動時,會為其關聯的 Service 自動創建一組環境變量(處于同一namespaceService),例如 REDIS_SERVICE_HOST=10.43.167.133REDIS_SERVICE_PORT=6379,在同一命名空間中的pod可以通過這些環境變量連接 Service
  1. DNS 解析方式
  • Kubernetes 內置的 CoreDNS 服務會為 Service 自動創建 DNS 記錄。例如,redis 服務的DNS 記錄是 redis.default.svc.cluster.local,集群內部的 Pod 直接訪問 redis:6379 即可連接。其中default是服務所在的命名空間

我們運行ping redis.default.svc.cluster.local,發現返回ip地址10.42.0.18,即redis service的地址。

redis.default.svc.cluster.local被稱為 FQDN(Fully Qualified Domain Name,全限定域名)。

全限定域名信息存儲在 Kubernetes 內部的 CoreDNS 組件中。其中Kubernetes API Server 監聽 Service 資源的創建或刪除。CoreDNS 通過 kube-dns 插件 監聽這些變化,并在內部的 DNS 服務器 里維護這些 Service 的解析記錄。當 Pod 需要訪問 Service,會向 CoreDNS 查詢 xxx.namespace.svc.cluster.localCoreDNS 解析出 ClusterIP 并返回給 Pod,這樣 Pod 就能訪問 Service 了。

Service 的負載均衡原理

當多個 Pod 運行同一個 Service 時,Kubernetes 通過 kube-proxy 進行負載均衡,主要有以下幾種模式:

  • iptables(默認)kube-proxy 使用 iptables 規則將流量隨機轉發到 Endpoints

  • IPVS(更高效):使用 IP Virtual Server 進行流量分發,支持更多的負載均衡策略(如 rr 輪詢、wrr 權重輪詢、lc 最小連接數等)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73166.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73166.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73166.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#與西門子PLC的六大通信庫

C#與西門子PLC的六大通信庫&#xff1a; 一、S7.NET S7.NET是一款開源的S7協議通信庫&#xff0c;支持西門子S7通信。 二、Sharp7 Sharp7與S7.NET一樣&#xff0c;是一款.NET版本的S7通信庫。 三、Snap7 Snap7是一個開源的C通信庫&#xff0c;支持西門子S7通信。 四、Prodave P…

IOS接入微信方法

導入SDK 和配置 SDK 的不做介紹&#xff1b; 1 在IOS 開發者中心 Identifiers 打開‘Associated Domains’ 2 建立一個文件&#xff08;不帶后綴的&#xff09;apple-app-site-association, teamid在 IOS 開發者中心的會員找&#xff0c;appid在 xcode里面找 {"applin…

DHCPv6 Stateless Vs Stateful Vs Stateless Stateful

DHCPv6常見配置模式 在 IPv6 網絡中,DHCPv6 的 Stateless(無狀態)、Stateful(有狀態) 和 Stateless + Stateful(混合模式) 是三種常見的配置模式。它們的主要區別在于客戶端如何獲取 IPv6 地址和其他網絡配置信息(如 DNS 服務器)。 Stateless(無狀態)模式 Statele…

HTTPS協議—加密算法和中間攻擊人的博弈

活動發起人小虛竹 想對你說&#xff1a; 這是一個以寫作博客為目的的創作活動&#xff0c;旨在鼓勵大學生博主們挖掘自己的創作潛能&#xff0c;展現自己的寫作才華。如果你是一位熱愛寫作的、想要展現自己創作才華的小伙伴&#xff0c;那么&#xff0c;快來參加吧&#xff01…

Java替換jar包中class文件

在更新java應用版本的運維工作中&#xff0c;由于一些原因&#xff0c;開發沒辦法給到完整的jar包&#xff0c;這個時候&#xff0c;就可以只將修改后的某個Java類的class文件替換掉原來iar包中的class文件&#xff0c;重新啟動服務即可&#xff1a; 1、將jar包和將要替換的cl…

【UI設計】一些好用的免費圖標素材網站

阿里巴巴矢量圖標庫https://www.iconfont.cn/國內最大的矢量圖標庫之一&#xff0c;擁有 800 萬 圖標資源。特色功能包括團隊協作、多端適配、定制化編輯等&#xff0c;適合企業級項目、電商設計、中文產品開發等場景。IconParkhttps://iconpark.oceanengine.com/home字節跳動…

【10】高效存儲MongoDB的用法

目錄 一、什么是MongoDB 二、準備工作 &#xff08;1&#xff09;安裝MongoDB ?&#xff08;2&#xff09;安裝pymongo庫 三、連接MongoDB 四、指定數據庫 五、指定集合 六、插入數據 &#xff08;1&#xff09; insert 方法 &#xff08;2&#xff09;insert_one(…

MATLAB+Arduino利用板上的按鍵控制板上Led燈

幾年不使用&#xff0c;之前的知識都忘掉了。需要逐步撿起來。 1 熟悉按鍵的使用 2熟悉燈的控制 1 電路 我們將通過 MATLAB 的 Arduino 支持包與 Arduino 板通信&#xff0c;讀取按鍵狀態并控制 LED 燈的亮滅。 按鍵&#xff1a;連接到 Arduino 的數字引腳&#xff08;例如…

《深度學習》——YOLOv3詳解

文章目錄 YOLOv3簡介YOLOv3核心原理YOLOv3改進YOLOv3網絡結構 YOLOv3簡介 YOLOv3&#xff08;You Only Look Once, version 3&#xff09;是一種先進的實時目標檢測算法&#xff0c;由 Joseph Redmon 和 Ali Farhadi 開發。它在目標檢測領域表現出色&#xff0c;具有速度快、精…

【項目設計】網頁版五子棋

文章目錄 一、項目介紹1.項目簡介2.開發環境3.核心技術4.開發階段 二、Centos-7.6環境搭建1.安裝wget工具2.更換軟件源(yum源)3.安裝scl工具4.安裝epel軟件源5.安裝lrzsz傳輸工具6.安裝高版本gcc/g編譯器7.安裝gdb調試器8.安裝git9.安裝cmake10.安裝boost庫11.安裝Jsoncpp庫12.…

在coze工作流中將數據回寫到飛書表格

在coze工作流中將數據回寫到飛書表格

并查集(競賽)

一、模型建立 本質就是一個數組&#xff0c;數組的下標對應節點的編號&#xff0c;數組的值對應對應編號的節點的父節點。規定根節點的父節點是自己。 規定三個集合的根節點分別是1 4 6 二、并查集操作并實現 并查集主要操作&#xff1a;查找一個節點的父節點&#xff0c;判…

Leetcode 刷題筆記1 圖論part04

leetcode 110 字符串接龍 def judge(s1, s2):count 0for i in range(len(s1)):if s1[i] ! s2[i]:count 1return count 1if __name__ __main__:n int(input())begin_str, end_str map(str, input().split())if begin_str end_str:print(0)exit()strlist []for _ in ran…

從擴展黎曼澤塔函數構造物質和時空的結構-7

有了先前關于電荷之間吸引和排斥關系的頻率分析圖&#xff0c;我們可以按照類似的方法&#xff0c;對磁場做一樣的分析&#xff0c;即分析磁體同極相斥&#xff0c;異極相吸的本質。 我們知道上圖得以成立的原因在于磁感線&#xff0c;如下圖所示的排布方式&#xff0c; 磁體的…

AI比人腦更強,因為被植入思維模型【18】萬物系統思維模型

把事物看成鏈&#xff0c;看成網&#xff0c;看成生態。 定義 萬物系統思維模型是一種將宇宙萬物視為一個相互關聯、相互作用的整體系統的思維方式。它強調從系統的角度去認識、分析和解決問題&#xff0c;認為系統中的各個要素之間存在著復雜的相互關系&#xff0c;這些關系不…

Qt-Q_ENUM宏和QMetaEnum類

Q_ENUM是一個宏定義&#xff0c;它的作用是將一個枚舉類型注冊到元對象系統&#xff0c;從而能夠通過QMetaEnum類獲得一些關于enum類型的一些信息&#xff0c;例如獲取enum類型的名稱字符串&#xff0c;enum值和字符串互相轉換&#xff0c;enum類型保存在QVariant中&#xff0c…

MongoDB 配合python使用的入門教程

MongoDB 入門教程 1. 安裝 MongoDB 首先&#xff0c;你需要在你的機器上安裝MongoDB。你可以從 MongoDB官網 下載并安裝 Community 版本。安裝完成后&#xff0c;啟動MongoDB服務。 # 在Linux/Mac上啟動MongoDB mongod# 在Windows上&#xff0c;你可以通過Windows服務啟動Mo…

【云馨AI-大模型】大模型的開發和應用中,Python、PyTorch和vLLM關系概括

說明 1. Python 定位&#xff1a;基礎編程語言。作用&#xff1a;Python 是大模型生態系統的核心語言&#xff0c;幾乎所有深度學習框架&#xff08;如 PyTorch、TensorFlow&#xff09;和工具鏈&#xff08;如 vLLM&#xff09;都通過 Python 接口提供服務。特點&#xff1a…

西門子200smart之modbus_TCP(做主站與第三方設備)通訊

西門子200smart做MODBUS_TCP主站通訊,只有一個指令。設置相關參數即可完成讀寫操作。整 個過程非常復雜,操作非常嚴謹。此次,我們使用匯川EASY系列PLC做從站,完成演示。關于匯川案例的演示,詳見匯川EASY系列之以太網通訊(MODBUS_TCP做從站)-CSDN博客 關于主站和從站的介…

緩存設計模式

緩存設計模式&#xff08;Cache Design Pattern&#xff09;是一種用于存儲和管理頻繁訪問數據的技術&#xff0c;旨在提高系統性能、降低數據庫或后端服務的負載&#xff0c;并減少數據訪問延遲。以下是幾種常見的緩存設計模式&#xff0c;并用 Python Redis 進行示例代碼實現…