Golang 語言怎麼使用 go-micro 和 gin 開發微服務?
大家好,我是 frank。
歡迎大家點擊上方藍色文字「Golang 語言開發棧」關注公衆號。
設爲星標,第一時間接收推送文章。
文末掃碼,和大家一起學 Golang 語言。
01
介紹
Go Micro 是一個分佈式系統開發框架。Go Micro 提供了分佈式系統開發的核心需求,包括 RPC 和事件驅動的通信。Gin 是一個用 Golang 編寫的 web 框架。本文首先介紹怎麼使用 go-micro 和 go-grpc 構建微服務,然後再介紹怎麼集成 gin 和 go-micro。我們使用的 go-micro 版本是 v1.18.0,golang 版本是 v1.13,gin 版本是 v1.7.2。
02
使用 go-micro 和 go-grpc 構建微服務
在我們開始使用 go-micro 之前,我們還需要提前做一些準備工作。安裝 protoc、protoc-gen-go 和 protoc-gen-micro,關於如何安裝,讀者朋友們可以參閱官方文檔,我們在之前的文章中也介紹過,限於篇幅,本文不再贅述。
其實,我們可以使用 Go Micro 工具集以命令的方式快速生成模板文件,但是因爲本文我們不準備介紹工具集的相關內容,所以我們使用手動創建文件的方式。
下面我們正式開始介紹如何構建服務,包括服務端服務和客戶端服務。
服務端
服務端代碼目錄:
├── go.mod
├── go.sum
├── handler
│ └── user
│ └── user.go
├── main.go
└── proto
└── user
├── user.pb.go
├── user.pb.micro.go
└── user.proto
構建服務端服務,分爲以下幾個步驟:
-
編寫 protobuf 文件
第一步是編寫 protobuf 文件,一般會將不同 package 的 protobuf 文件存放在單獨的文件目錄中。
文件路徑:
proto/user/user.proto
syntax = "proto3"; package user; service User { rpc Login(LoginRequest) returns (LoginResponse) {} } message LoginRequest { string email = 1; string password = 2; } message LoginResponse { string username = 1; }
閱讀上面這段代碼,我們在定義的
user.proto
文件中,創建了一個 rpc 服務。 -
生成文件
第二步是生成文件,使用命令:
protoc --proto_path=. --micro_out=. --go_out=. user.proto
執行以上命令,將會自動生成兩個文件,分別是
user.pb.go
和user.micro.go
。閱讀
user.micro.go
文件,可以發現在該文件中已經自動生成了客戶端和服務端的代碼。 -
編寫 handler
第三步是編寫服務端的 handler 代碼。
文件路徑:
handler/user/user.go
type User struct{} func (u *User) Login(ctx context.Context, req *protoUser.LoginRequest, rsp *protoUser.LoginResponse) error { if req.Email != "gopher@88.com" || req.Password != "123456" { rsp.Username = "Sorry " + req.Email return nil } rsp.Username = "Welcome " + req.Email return nil }
-
定義服務端服務
第四步是定義服務端服務,需要注意的是,這裏使用的是 grpc。在
main.go
文件中編寫如下代碼:文件路徑:
main.go
func main() { // 創建服務 service := grpc.NewService( micro.Name("go.micro.srv.demo"), micro.Version("v0.0.0"), micro.RegisterTTL(time.Second * 10), micro.RegisterInterval(time.Second * 5), ) // 註冊處理器 err := protoUser.RegisterUserHandler(service.Server(), new(user.User)) if err !=nil { log.Fatal(err) } // 運行服務 if err = service.Run(); err != nil { log.Fatal(err) } }
完成以上 4 個步驟,我們就已經實現了服務端 rpc 服務,接下來,我們開始編寫客戶端代碼。
客戶端
客戶端代碼目錄:
├── go.mod
├── go.sum
├── main.go
├── proto
│ └── user
│ ├── user.pb.go
│ ├── user.pb.micro.go
│ └── user.proto
└── router
├── router.go
└── v1
└── user.go
構建客戶端服務,分爲以下幾個步驟:
-
拷貝 proto 文件和生成文件
第一步是拷貝服務端的 proto 文件和生成文件,目的是爲了保證服務端和客戶端的類型一致性。
-
定義客戶端服務
第二步是定義客戶端:
文件路徑:
router/v1/user.go
func NewUserClient() protoUser.UserService { // 創建服務 service := grpc.NewService() // 創建客戶端 userClient := protoUser.NewUserService("go.micro.srv.demo", service.Client()) return userClient }
-
rpc 調用遠程服務的方法
第三步是 rpc 調用遠程服務的方法:
文件路徑:
router/v1/user.go
client := NewUserClient() // rpc 調用遠程服務的方法 resp, err := client.Login(context.TODO(), &protoUser.LoginRequest{Email: param.Email, Password: param.Password}) if err != nil { fmt.Println(err) }
完成以上 3 步,我們就已經基本編寫完客戶端的代碼。
03
gin 和 go-micro 集成
接下來,我們介紹如何集成 gin 和 go-micro,該部分代碼也是在客戶端中,共需要兩個步驟。
-
創建路由
文件路徑:
router/router.go
func NewRouter() *gin.Engine { r := gin.New() userControllerV1 := new(v1.User) // 路由分組 v1 := r.Group("/v1") { v1.Use(gin.Logger(), gin.Recovery()) userV1 := v1.Group("/user") { userV1.POST("/login", userControllerV1.Login) } } return r }
-
啓動(監聽)服務
文件路徑:
main.go
func main() { r := router.NewRouter() server := &http.Server{ Addr: ":8080", Handler: r, ReadTimeout: time.Second * 10, WriteTimeout: time.Second * 10, MaxHeaderBytes: 1 << 20, } if err := server.ListenAndServe(); err != nil { log.Fatal(err) } }
至此,我們已經完成了集成 gin 和 go-micro,啓動服務端服務和客戶端服務後,我們就可以使用以下命令進行 cURL 測試:
curl --location --request POST 'http://127.0.0.1:8080/v1/user/login' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "gopher@88.com",
"password": "123456"
}'
04
總結
本文我們主要介紹怎麼使用 go-micro 和 go-grpc 構建微服務,和怎麼集成 gin 和 go-micro,並沒有介紹 gin 和 go-micro 的使用方法,如果讀者朋友們還不瞭解 gin 和 go-micro,建議先閱讀 gin 和 go-micro 官方文檔,也可以參考公衆號之前推送的關於 gin 的文章。
參考資料:
https://github.com/asim/go-micro
https://gin-gonic.com/zh-cn/docs/introduction/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/xCFsKMHSlBG4ao1FM98n2w