consul服務注冊與發現(go)-學習筆記

參考博客

1、服務實例接口與默認實現

type ServiceInstance interface {// 獲取服務實例的唯一IDGetInstanceId() string// 獲取服務IDGetServiceId() string// 獲取服務實例的主機名或IP地址GetHost() string// 獲取服務實例的端口號GetPort() int// 判斷服務實例是否使用HTTPSIsSecure() bool// 獲取服務實例的元數據(鍵值對形式)GetMetadata() map[string]string
}type DefaultServiceInstance struct {InstanceId stringServiceId  stringHost       stringPort       intSecure     boolMetadata   map[string]string
}// 構造函數
func NewDefaultServiceInstance(serviceId string, host string, port int, secure bool,metadata map[string]string, instanceId string) (*DefaultServiceInstance, error) {// 如果沒有傳入 IP 則獲取一下,這個方法在多網卡的情況下,并不好用if len(host) == 0 {localIP, err := util.GetLocalIP()if err != nil {return nil, err}host = localIP}//若instanceId為空,自動生成“服務ID-時間戳-隨機數(1000-9999)”if len(instanceId) == 0 {instanceId = serviceId + "-" + strconv.FormatInt(time.Now().Unix(), 10) + "-" + strconv.Itoa(rand.Intn(9000)+1000)}return &DefaultServiceInstance{InstanceId: instanceId, ServiceId: serviceId, Host: host, Port: port, Secure: secure, Metadata: metadata}, nil
}func (serviceInstance DefaultServiceInstance) GetInstanceId() string {return serviceInstance.InstanceId
}func (serviceInstance DefaultServiceInstance) GetServiceId() string {return serviceInstance.ServiceId
}func (serviceInstance DefaultServiceInstance) GetHost() string {return serviceInstance.Host
}func (serviceInstance DefaultServiceInstance) GetPort() int {return serviceInstance.Port
}func (serviceInstance DefaultServiceInstance) IsSecure() bool {return serviceInstance.Secure
}func (serviceInstance DefaultServiceInstance) GetMetadata() map[string]string {return serviceInstance.Metadata
}

2、定義服務注冊和剔除的方法

type ServiceRegistry interface {Register(serviceInstance cloud.ServiceInstance) boolDeregister()
}

具體實現:

import ("errors""fmt""github.com/hashicorp/consul/api""strconv""unsafe"
)type consulServiceRegistry struct {// 服務實例緩存(服務ID->實例ID->實例)serviceInstances     map[string]map[string]cloud.ServiceInstance//Consul客戶端client               api.Client//當前本地服務實例localServiceInstance cloud.ServiceInstance
}func (c consulServiceRegistry) Register(serviceInstance cloud.ServiceInstance) bool {// 創建注冊到consul的服務到registration := new(api.AgentServiceRegistration)registration.ID = serviceInstance.GetInstanceId()registration.Name = serviceInstance.GetServiceId()registration.Port = serviceInstance.GetPort()var tags []stringif serviceInstance.IsSecure() {tags = append(tags, "secure=true")} else {tags = append(tags, "secure=false")}if serviceInstance.GetMetadata() != nil {var tags []stringfor key, value := range serviceInstance.GetMetadata() {tags = append(tags, key+"="+value)}registration.Tags = tags}registration.Tags = tagsregistration.Address = serviceInstance.GetHost()// 增加consul健康檢查回調函數check := new(api.AgentServiceCheck)schema := "http"if serviceInstance.IsSecure() {schema = "https"}check.HTTP = fmt.Sprintf("%s://%s:%d/actuator/health", schema, registration.Address, registration.Port)check.Timeout = "5s"check.Interval = "5s"check.DeregisterCriticalServiceAfter = "20s" // 故障檢查失敗30s后 consul自動將注冊服務刪除registration.Check = check// 注冊服務到consulerr := c.client.Agent().ServiceRegister(registration)if err != nil {fmt.Println(err)return false}//初始化服務實例緩存結構//若未初始化,服務ID-實例ID-實例if c.serviceInstances == nil {c.serviceInstances = map[string]map[string]cloud.ServiceInstance{}}//獲取特定服務的實例集合//從外層map中查詢該服務ID對應的內層mapservices := c.serviceInstances[serviceInstance.GetServiceId()]//初始化空實例集合//處理首次注冊情況,創建新的內層map,用處存儲該服務的實例集合if services == nil {services = map[string]cloud.ServiceInstance{}}//添加當前實例到集合services[serviceInstance.GetInstanceId()] = serviceInstance//更新外層緩存	//確保外層map中服務ID對應內層map是最新版本	c.serviceInstances[serviceInstance.GetServiceId()] = services//記錄當前實例c.localServiceInstance = serviceInstancereturn true
}// deregister a service
func (c consulServiceRegistry) Deregister() {//檢查服務實例緩存是否初始化if c.serviceInstances == nil {return}//從緩存中獲取當前服務ID對應的實例集合(實例ID->實例對象)services := c.serviceInstances[c.localServiceInstance.GetServiceId()]//檢查實例集合是否存在if services == nil {return}//從本地緩存移除當前實例delete(services, c.localServiceInstance.GetInstanceId())//清空服務記錄if len(services) == 0 {delete(c.serviceInstances, c.localServiceInstance.GetServiceId())}//從Consul注銷服務_ = c.client.Agent().ServiceDeregister(c.localServiceInstance.GetInstanceId())//重置當前實例記錄c.localServiceInstance = nil
}// new a consulServiceRegistry instance
// token is optional
func NewConsulServiceRegistry(host string, port int, token string) (*consulServiceRegistry, error) {if len(host) < 3 {return nil, errors.New("check host")}if port <= 0 || port > 65535 {return nil, errors.New("check port, port should between 1 and 65535")}config := api.DefaultConfig()config.Address = host + ":" + strconv.Itoa(port)config.Token = tokenclient, err := api.NewClient(config)if err != nil {return nil, err}return &consulServiceRegistry{client: *client}, nil
}

在這里插入圖片描述
測試用例:

func TestConsulServiceRegistry(t *testing.T) {//初始化Consul注冊中心客戶端host := "127.0.0.1"port := 8500registryDiscoveryClient, _ := extension.NewConsulServiceRegistry(host, port, "")//獲取本地IP地址ip, err := util.GetLocalIP()if err != nil {t.Error(err)}//創建服務實例信息serviceInstanceInfo, _ := cloud.NewDefaultServiceInstance("go-user-server", "", 8090,false, map[string]string{"user":"zyn"}, "")//注冊服務實例
registryDiscoveryClient.Register(serviceInstanceInfo)r := gin.Default()// 健康檢測接口,其實只要是 200 就認為成功了r.GET("/actuator/health", func(c *gin.Context) {c.JSON(200, gin.H{"message": "pong",})})err = r.Run(":8090")if err != nil{registryDiscoveryClient.Deregister()}
}

3、服務發現

  • 獲取所有的服務列表
  • 獲取指定的服務的所有實例信息

接口定義:

type DiscoveryClient interface {/*** Gets all ServiceInstances associated with a particular serviceId.* @param serviceId The serviceId to query.* @return A List of ServiceInstance.*/GetInstances(serviceId string) ([]cloud.ServiceInstance, error)/*** @return All known service IDs.*/GetServices() ([]string, error)
}

具體實現:

type consulServiceRegistry struct {serviceInstances     map[string]map[string]cloud.ServiceInstanceclient               api.ClientlocalServiceInstance cloud.ServiceInstance
}func (c consulServiceRegistry) GetInstances(serviceId string) ([]cloud.ServiceInstance, error) {//查詢指定服務catalogService, _, _ := c.client.Catalog().Service(serviceId, "", nil)//若查詢到服務實例if len(catalogService) > 0 {//轉換Consul數據到標準格式result := make([]cloud.ServiceInstance, len(catalogService))for index, sever := range catalogService {s := cloud.DefaultServiceInstance{InstanceId: sever.ServiceID,ServiceId:  sever.ServiceName,Host:       sever.Address,Port:       sever.ServicePort,Metadata:   sever.ServiceMeta,}result[index] = s}return result, nil}return nil, nil
}
//返回服務名稱列表
func (c consulServiceRegistry) GetServices() ([]string, error) {//查詢所有服務services, _, _ := c.client.Catalog().Services(nil)result := make([]string, unsafe.Sizeof(services))index := 0for serviceName, _ := range services {result[index] = serviceNameindex++}return result, nil
}// new a consulServiceRegistry instance
// token is optional
func NewConsulServiceRegistry(host string, port int, token string) (*consulServiceRegistry, error) {if len(host) < 3 {return nil, errors.New("check host")}if port <= 0 || port > 65535 {return nil, errors.New("check port, port should between 1 and 65535")}config := api.DefaultConfig()config.Address = host + ":" + strconv.Itoa(port)config.Token = tokenclient, err := api.NewClient(config)if err != nil {return nil, err}return &consulServiceRegistry{client: *client}, nil
}

測試用例:

func TestConsulServiceDiscovery(t *testing.T) {host := "127.0.0.1"port := 8500token := ""registryDiscoveryClient, err := extension.NewConsulServiceRegistry(host, port, token)if err != nil {panic(err)}t.Log(registryDiscoveryClient.GetServices())t.Log(registryDiscoveryClient.GetInstances("go-user-server"))
}

結果:

consul_service_registry_test.go:57: [consul go-user-server      ] <nil>consul_service_registry_test.go:59: [{go-user-server-1602590661-56179 go-user-server 127.0.0.1 8090 false map[user:zyn]}] <nil>

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

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

相關文章

【AI】prompt engineering

prompt engineering ## prompt engineering ## prompt engineering ## prompt engineering 一、定義 Prompt 工程&#xff08;Prompt Engineering&#xff09;是指在使用語言模型&#xff08;如 ChatGPT、文心一言等&#xff09;等人工智能工具時&#xff0c;設計和優化輸入提…

Python 字典和集合(常見的映射方法)

本章內容的大綱如下&#xff1a; 常見的字典方法 如何處理查找不到的鍵 標準庫中 dict 類型的變種set 和 frozenset 類型 散列表的工作原理 散列表帶來的潛在影響&#xff08;什么樣的數據類型可作為鍵、不可預知的 順序&#xff0c;等等&#xff09; 常見的映射方法 映射類型…

對抗Prompt工程:構建AI安全護欄的攻防實踐

大語言模型的開放性與自然語言交互特性使其面臨前所未有的Prompt工程攻擊威脅。本文通過分析2021-2023年間157個真實越獄案例&#xff0c;揭示語義混淆、上下文劫持、多模態組合三重攻擊路徑的技術原理&#xff0c;提出融合動態意圖拓撲分析&#xff08;DITA&#xff09;、對抗…

STL c++ list——模擬實現

結點類的模擬實現 list是一個帶頭雙向循環鏈表 因需要實現一個節點類&#xff0c;其中包含哨兵位&#xff08;用來標識位置&#xff09;&#xff0c;節點信息&#xff08;val數據&#xff0c;prev后指針&#xff0c;next后指針&#xff09; template<class T> struct …

ORM、Mybatis和Hibernate、Mybatis使用教程、parameterType、resultType、級聯查詢案例、resultMap映射

DAY21.1 Java核心基礎 ORM Object Relationship Mapping 對象關系映射 面向對象的程序到—關系型數據庫的映射 比如java – MySQL的映射 ORM框架就是實現這個映射的框架 Hibernate、Mybatis、MybatisPlus、Spring Data JPA、Spring JDBC Spring Data JPA的底層就是Hiber…

【學習自用】配置文件中的配置項

server.port服務器端口&#xff0c;常被用于指定應用程序運行時所監聽的端口號spring.datasource.url用于配置數據源的數據庫連接URLspring.datasource.username用于指定連接數據庫的用戶名spring.datasource.password用于配置數據源時設置數據庫連接密碼的屬性mybatis.mapper-…

使用protobuf編譯提示無法打開包括文件: ‘absl/log/absl_log.h’: No such file or directory

問題原因 Protobuf 依賴 Abseil&#xff1a; Protobuf 3.20 版本開始依賴 Abseil&#xff0c;但你的系統未正確安裝或配置 Abseil。 頭文件路徑未包含&#xff1a; 編譯器找不到 absl/log/absl_log.h&#xff0c;可能是因為 Abseil 未正確安裝或未在項目中設置包含路徑。 …

Spring AI Alibaba 文檔檢索使用

一、文檔檢索 (Document Retriever)簡介 1、核心概念 文檔檢索&#xff08;DocumentRetriever&#xff09;是一種信息檢索技術&#xff0c;旨在從大量未結構化或半結構化文檔中快速找到與特定查詢相關的文檔或信息。文檔檢索通常以在線(online)方式運行。 DocumentRetriever通…

前端面試核心知識點整理:從 JavaScript 到 Vue 全解析

一、JavaScript 異步編程核心:Promise 與 async/await 1. Promise 深度解析 定義:Promise 是處理異步操作的對象,代表一個異步操作的最終狀態(成功 / 失敗)。三種狀態: pending(進行中):初始狀態,異步操作未完成。fulfilled(已成功):異步操作成功,調用 resolve …

音視頻(四)android編譯

前言 前面已經講了在windows上應用了&#xff0c;這章主要講述android上編譯 1&#xff1a;環境 git 如果失敗 直接跑到相應網站 手動下載 ubuntu22.* android ndk r21e download:https://developer.android.google.cn/ndk/downloads/index.html?hluk 為什么用這個&#xff0…

【kind管理腳本-3】腳本函數說明文檔 —— 便捷使用 kind 創建、刪除、管理集群腳本

下面是一份詳細的說明文檔&#xff0c;介紹該腳本的功能、用法及各部分的含義&#xff0c;供您參考和使用&#xff1a; Kind 集群管理腳本說明文檔 此腳本主要用于管理 Kind&#xff08;Kubernetes IN Docker&#xff09;集群&#xff0c;提供創建、刪除、導出 kubeconfig、加…

【計算機行業發展與重塑】

計算機行業正經歷前所未有的變革&#xff0c;AI技術的爆發式發展與產業升級的深度融合&#xff0c;正在重塑行業格局與就業市場。以下從行業趨勢、AI的核心價值、就業需求三個維度展開分析。 一、行業趨勢&#xff1a;AI驅動下的多極增長 AI成為核心引擎 生成式AI的突破&#…

(高頻SQL50題)1667. 修復表中的名字

問題 表&#xff1a; Users ------------------------- | Column Name | Type | ------------------------- | user_id | int | | name | varchar | ------------------------- user_id 是該表的主鍵(具有唯一值的列)。 該表包含用戶的 ID 和名字…

基于人工智能的醫學影像關聯分析:利用潛在空間幾何混雜因素校正法|文獻速遞-深度學習醫療AI最新文獻

Title 題目 AI-based association analysis for medical imaging using latent-spacegeometric confounder correction 基于人工智能的醫學影像關聯分析&#xff1a;利用潛在空間幾何混雜因素校正法 01 文獻速遞介紹 人工智能&#xff08;AI&#xff09;已成為各個領域的…

開源免費虛擬化軟件PVE功能介紹

Proxmox VE&#xff08;PVE&#xff09;提供了一個基于 Web UI&#xff08;管理界面&#xff09;的虛擬化管理平臺&#xff0c;用戶可以通過瀏覽器管理 虛擬機&#xff08;VM&#xff09;、容器&#xff08;LXC&#xff09;、存儲、網絡、備份、用戶權限等。 一、PVE Web 界面…

新球體育比分狀態監控

文章目錄 目標分析監控邏輯代碼目標分析 網頁監控地址:aHR0cHM6Ly9saXZlLnRpdGFuMDA3LmNvbS9pbmRleDJpbjEuYXNweD9pZD0x 監控邏輯 比分等數據主要是依賴JS加載得到,通過ajax后端進行渲染 代碼 # -*- coding: utf-8 -*-import warnings warnings.filterwarnings(ignore) f…

【lodash的omit函數詳解 - 從入門到精通】

lodash的omit函數詳解 - 從入門到精通 小白視角&#xff1a;什么是omit&#xff1f; omit在英文中意為"忽略"或"省略"。在編程中&#xff0c;它就是從一個對象中刪除不需要的屬性&#xff0c;返回一個新對象。 // 原始對象 const person {name: "…

軟考筆記9——數據庫技術基礎

第九章節——數據庫技術基礎 數據庫技術基礎 第九章節——數據庫技術基礎一、基本概念1. 數據庫與數據庫系統2. 數據庫的三級模式2.1 內模式2.2 概念模式2.3 外模式2.4 數據庫的兩級映射2.5 數據庫設計的基本步驟 二、數據模型1. 基本概念2. E-R模型2.1 實體2.2 聯系2.3 屬性 3…

Django分頁教程及示例

推薦超級課程: 本地離線DeepSeek AI方案部署實戰教程【完全版】Docker快速入門到精通Kubernetes入門到大師通關課AWS云服務快速入門實戰目錄 完整代碼示例:結論Django的分頁模塊允許你將大量數據分割成更小的塊(頁面)。這對于以可管理的方式顯示項目列表,如博客文章或產品…

int 與 Integer 的區別詳解

1. 本質區別 特性intInteger類型基本數據類型&#xff08;Primitive&#xff09;包裝類&#xff08;Wrapper Class&#xff09;存儲位置棧&#xff08;或作為對象成員在堆中&#xff09;堆&#xff08;對象實例&#xff09;默認值0null&#xff08;可能導致 NullPointerExcept…