golang使用服務發現系統consul
本文的完整程式碼見 https://github.com/changjixiong/goNotes/tree/master/consulnotes ,如果文中沒有顯示連結說明連結在被轉發的時候被幹掉了,請搜尋找到原文閱讀。
consul是什麼
"Consul is a distributed, highly available, datacenter-aware, service discovery and configuration system. It can be used to present services and nodes in a flexible and powerful interface that allows clients to always have an up-to-date view of the infrastructure they are a part of."
引用一段網上對consul文件的翻譯(http://consul.la/intro/what-is-consul)
Consul有多個元件,但是整體來看,它是你基礎設施中用於發現和配置服務的一個工具。它提供如下幾個關鍵功能:
* 服務發現: Consul的某些客戶端可以提供一個服務,例如api或者mysql,其它客戶端可以使用Consul去發現這個服務的提供者。使用DNS或者HTTP,應用可以很容易的找到他們所依賴的服務。
* 健康檢查: Consul客戶端可以提供一些健康檢查,這些健康檢查可以關聯到一個指定的服務(服務是否返回200 OK),也可以關聯到本地節點(記憶體使用率是否在90%以下)。這些資訊可以被一個操作員用來監控叢集的健康狀態,被服務發現元件路由時用來遠離不健康的主機。
* 鍵值儲存: 應用可以使用Consul提供的分層鍵值儲存用於一些目的,包括動態配置、特徵標記、協作、leader選舉等等。通過一個簡單的HTTP API可以很容易的使用這個元件。
* 多資料中心: Consul對多資料中心有非常好的支援,這意味著Consul使用者不必擔心由於建立更多抽象層而產生的多個區域。
Consul被設計為對DevOps群體和應用開發者友好,他非常適合現代的、可伸縮的基礎設施。
範例
網上關於consul的文件及使用說明有很多,然而卻缺少關於使用的範例,接下來的內容將用一個範例來演示如何找到可服務的節點。完整的程式碼見https://github.com/changjixion ... notes
假設在一個系統中,節點A需要訪問某種服務,該服務有N個節點可提供服務,這些節點位於服務叢集groupB,節點A只需要連線上groupB中的任一節點即可獲得服務。
啟動consul
consul提供開發模式用於啟動單節點服務供開發除錯用,執行命令consul agent -dev 啟動consul,輸出的資訊中有一行
Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)
顯示了consul執行引數,通過網址http://127.0.0.1:8500/ui/#/dc1/nodes可以檢視節點與服務
註冊服務並新增健康檢查
下面的程式碼將向consul註冊一個服務
import (
"fmt"
"log"
"net/http"
consulapi "github.com/hashicorp/consul/api"
)
func consulCheck(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "consulCheck")
}
func registerServer() {
config := consulapi.DefaultConfig()
client, err := consulapi.NewClient(config)
if err != nil {
log.Fatal("consul client error : ", err)
}
checkPort := 8080
registration := new(consulapi.AgentServiceRegistration)
registration.ID = "serverNode_1"
registration.Name = "serverNode"
registration.Port = 9527
registration.Tags = []string{"serverNode"}
registration.Address = "127.0.0.1"
registration.Check = &consulapi.AgentServiceCheck{
HTTP: fmt.Sprintf("http://%s:%d%s", registration.Address, checkPort, "/check"),
Timeout: "3s",
Interval: "5s",
DeregisterCriticalServiceAfter: "30s", //check失敗後30秒刪除本服務
}
err = client.Agent().ServiceRegister(registration)
if err != nil {
log.Fatal("register server error : ", err)
}
http.HandleFunc("/check", consulCheck)
http.ListenAndServe(fmt.Sprintf(":%d", checkPort), nil)
}
consulapi.DefaultConfig()的原始碼顯示預設採用的是http方式連線"127.0.0.1:8500",前文中顯示consul開發模式預設提供的http服務是在127.0.0.1:8500,在實際使用中需要設定為實際的引數。
consulapi.AgentServiceCheck中的HTTP指定了健康檢查的介面地址即127.0.0.1:8080/check,consulCheck函式響應這個介面呼叫,返回200狀態碼及一段字串"consulCheck",健康檢查還有其他幾種方式,具體可以參考官方文件。
consulapi.AgentServiceCheck中的DeregisterCriticalServiceAfter指定檢查不通過後多長時間登出本服務,這裡設定為30秒。
向consul註冊的服務地址為127.0.0.1:9527,以下是在127.0.0.1:9527上提供的echo服務。
ln, err := net.Listen("tcp", "0.0.0.0:9527")
if nil != err {
panic("Error: " + err.Error())
}
for {
conn, err := ln.Accept()
if err != nil {
panic("Error: " + err.Error())
}
go EchoServer(conn)
}
服務啟動後,訪問http://127.0.0.1:8500/ui/#/dc1/nodes 會發現 "2 services",點開後會在頁面上看到serverNode 127.0.0.1:9527,表明服務資訊已經註冊。以下資訊顯示健康檢查通過。
HTTP GET http://127.0.0.1:8080/check: 200 OK Output: consulCheck
使用服務
服務使用方client通過以下程式碼向consul查詢可用的服務(忽略錯誤處理)
client, err := consulapi.NewClient(consulapi.DefaultConfig())//非預設情況下需要設定實際的引數
...
services, err = client.Agent().Services()
...
if _, found := services["serverNode_1"]; !found {
log.Println("serverNode_1 not found")
continue
} //查詢名為serverNode_1的服務
查詢到服務後連線服務併傳送資料
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", service.Address, service.Port))
...
client先啟動,服務後啟動,然後服務關閉,執行日誌如下:
serverNode_1 not found
get: EchoServerHello World, 001
get: EchoServerHello World, 002
...
get: EchoServerHello World, 008
Read Buffer Error: EOF
dial tcp 127.0.0.1:9527: getsockopt: connection refused
dial tcp 127.0.0.1:9527: getsockopt: connection refused
...
dial tcp 127.0.0.1:9527: getsockopt: connection refused
serverNode_1 not found
serverNode_1 not found
服務啟動前提示serverNode_1沒找到,服務啟動後資料互動正常,服務關閉後consul尚未登出服務client提示服務無法連線,稍後consul登出了失效的服務,client顯示服務沒有找到。
使用場景設想
假設一個網路遊戲有N個副本服務節點提供服務,在生產執行期間,有的節點可能故障,有些節點可能負載過高,有些節點可能故障後自行回覆需要能重新上線提供服務。通過consul系統可以隨時讓閘道器伺服器或者邏輯伺服器獲取可用的副本服務節點並將請求轉發到該節點,保持副本服務的高效可用。
其他型別的服務也可以採用同樣的方式進行水平擴充套件。進一步的,可以在負載高的時候啟動新節點,在負載低的時候關閉部分節點,在雲伺服器上實現這些非常方便,並且由於是按使用計費,通過負載增加或關閉節點也可以避免雲伺服器資源的浪費從而降低費用。
一點問題
服務註冊時設定檢查失敗後30秒登出服務,實際執行中大約80秒才登出服務,原因待查。
相關文章
- golang consul-grpc 服務註冊與發現GolangRPC
- Go | Go 使用 consul 做服務發現Go
- .Net Core微服務——服務發現:Consul(一)微服務
- .Net Core微服務——服務發現:Consul(二)微服務
- consul服務註冊與服務發現的巨坑
- .NET Core HttpClientFactory+Consul實現服務發現HTTPclient
- Consul服務治理發現學習記錄
- Spring cloud(2)-服務發現(Eureka,Consul)SpringCloud
- 04-Consul服務註冊與發現
- 微服務Consul系列之服務註冊與發現微服務
- go-micro使用Consul做服務發現的方法和原理Go
- 使用Java和Consul實現服務配置管理Java
- Ocelot整合Consul實現api閘道器與服務發現API
- 微服務Consul系列之服務部署、搭建、使用微服務
- .Net 6 使用 Consul 實現服務註冊與發現 看這篇就夠了
- consul 作為服務註冊與發現和配置中心
- 我是服務的執政官-服務發現和註冊工具consul簡介
- 基於Golang的微服務——ConsulGolang微服務
- 18.基於Consul的服務發現和ConsulManager管理
- Spring Cloud(二) Consul 服務治理實現SpringCloud
- 學習搭建 Consul 服務發現與服務網格-有豐富的示例和圖片
- 基於Docker + Consul + Nginx + Consul-template的服務負載均衡實現DockerNginx負載
- SpringCloud使用Consul時,服務登出的操作方式SpringGCCloud
- 基於Docker + Consul + Registrator的服務註冊與發現叢集搭建Docker
- 微服務註冊發現配置中心-consul微服務
- Api閘道器Kong整合Consul做服務發現及在Asp.Net Core中的使用APIASP.NET
- ECTS——使用 Golang 開發的分散式定時任務管理系統Golang分散式
- 用C#開發Windows服務監控系統使用C#Windows
- golang實現基於redis和consul的可水平擴充套件的排行榜服務範例GolangRedis套件
- .Net Core微服務入門全紀錄(二)——Consul-服務註冊與發現(上)微服務
- (十四)spring cloud微服務分散式雲架構-服務註冊與發現(Eureka、Consul)SpringCloud微服務分散式架構
- 用 Golang 實現百萬級 Websocket 服務GolangWeb
- golang實現的長連線服務Golang
- 使用Systemctl命令來管理系統服務
- linux系統服務(systemctl)的使用Linux
- Nodejs 使用 ZooKeeper 做服務發現NodeJS
- [翻譯]微服務設計模式 - 5. 服務發現 - 服務端服務發現微服務設計模式服務端
- Golang服務端面經Golang服務端