1. 什麼是go micro
1.1 go micro作用
它是一個可插入的RPC框架,用於在Go中編寫微服務。開箱即用,您將收到:
- 服務發現: 應用程式自動註冊到服務發現系統
- 負載平衡: 客戶端負載平衡,用於平衡服務例項之間的請求
- 同步通訊: 提供請求 / 響應傳輸層。
- 非同步通訊: 內建釋出 / 訂閱功能。
- 訊息編碼: 基於訊息的內容型別頭的編碼 / 解碼。
- RPC 客戶機/伺服器包: 利用上述功能並公開介面來構建微服務
1.2 go micro架構組成
Go 微體系結構可以描述為三層堆疊
頂層由客戶端-伺服器模型和服務抽象組成。
- 伺服器: 用於編寫服務的構建塊
- 客戶端: 提供了向服務請求的介面。
底層由以下型別的外掛組成:
- 代理: 為非同步釋出/訂閱通訊提供訊息代理的介面。
- 編解碼器: 用於編碼/解碼訊息。支援的格式包括 json,bson,protobuf,msgpack 等。
- 登錄檔: 提供服務發現機制(預設為 Consul)
- 選擇器: 建立在登錄檔上的負載平衡抽象。它允許使用諸如隨機,輪循,最小康等演算法來 “選擇” 服務。
傳輸 - 服務之間同步請求 / 響應通訊的介面。 Go Micro
還提供了Sidecar
等功能。這使您可以使用Go
以外的語言編寫的服務
Sidecar提供服務註冊,gRPC編碼/解碼和HTTP處理程式。它支援多種語言。
2. go micro入門
最簡單的用法大概如下,結合net/http
標準庫監聽路由
package main
import (
"github.com/micro/go-micro/web"
"net/http"
)
func main() {
server := web.NewService(web.Address(":8081")) // 路由
server.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello go micro"))
})
_ = server.Run()
}
也可以整合第三方web框架作為路由
- 比如
gin
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/micro/go-micro/web"
)
func main() {
// 使用gin作為路由
r := gin.Default()
r.GET("/user", func(c *gin.Context) {
c.String(http.StatusOK, "user api")
})
server := web.NewService(
web.Address(":8081"), // 埠
web.Metadata(map[string]string{"protocol": "http"}), // 元資訊
web.Handler(r)) // 路由
_ = server.Run()
}
3. 結合consul進行服務註冊/發現
微服務裡最重要的關鍵一步就是服務註冊
常用的有consul、etcd、zookeeper、eureka
我們這裡使用consul
3.1 consul的安裝
這裡直接使用docker安裝
docker run -d --name=cs -p 8500:8500 consul agent -server -bootstrap -ui -client 0.0.0.0
然後再訪問埠8500,如下現實安裝成功
3.2 服務註冊程式碼示例
github.com/micro/go-micro/registry/consul
上面這個在1.14.0版本之後刪除了,要用這個github.com/micro/go-plugins/registry/consul
,或者換成etcd作為註冊中心
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/web"
"github.com/micro/go-plugins/registry/consul"
)
func main() {
// 新增consul地址
cr := consul.NewRegistry(
registry.Addrs("127.0.0.1:8500"))
// 使用gin作為router
router := gin.Default()
router.GET("/user", func(c *gin.Context) {
c.String(http.StatusOK, "user api")
})
// 初始化go micro
server := web.NewService(
web.Name("productService"), // 當前微服務服務名
web.Registry(cr), // 註冊到consul
web.Address(":8081"), // 埠
web.Metadata(map[string]string{"protocol": "http"}), // 元資訊
web.Handler(router)) // 路由
_ = server.Run()
}
把上述程式碼執行起來,再去consul
介面檢視,發現productService
服務新增成功
然後把程式碼停掉,再去consul
介面檢視,productService
就沒了,非常方便
3.2 服務發現程式碼示例
package main
import (
"fmt"
"log"
"github.com/micro/go-micro/client/selector"
"github.com/micro/go-micro/registry"
"github.com/micro/go-plugins/registry/consul"
)
func main() {
// 1.連線到consul
cr := consul.NewRegistry(registry.Addrs("127.0.0.1:8500"))
// 2.根據service name獲取對應的微服務列表
services, err := cr.GetService("productService")
if err != nil {
log.Fatal("cannot get service list")
}
// 3.使用random隨機獲取其中一個例項
next := selector.Random(services)
svc, err := next()
if err != nil {
log.Fatal("cannot get service")
}
fmt.Println("[測試輸出]:", svc.Id, svc.Address, svc.Metadata)
}
然後使用goland先啟動服務註冊中的productService
的微服務,再啟動服務發現中的程式碼。
服務發現將會輸出如下,服務發現成功: