背景
go-micro給我們提供了一個非常便捷的方式來快速搭建微服務,而且並不需要提前系統了解micro,下面用一個簡單的示例來快速實現一個服務。
創建Proto文件
因為我們要做微服務,那么就一定有服務端和客戶端,這兩個端通過什么格式進行內容傳輸,就涉及到了序列化,比較主流的序列化協議就是JSON和Protobuf,因為Protobuf是以二進制傳輸的,體積比較小,所以傳輸速度也相對較快,今天就以protobuf來進行演示。
下面使用Proto3的語法在protos目錄創建文件greeter.proto
,該文件定義一個名為Greeter
的服務,以及對應的入參和出參。
syntax = "proto3";
package protos;
service Greeter {
rpc Hello (Request) returns (Response) {
};
}
message Request {
string name = 1;
}
message Response {
string greeting = 2;
}
生成Go文件
生成Go文件之前,要先確保本機安裝了protobuf,如果在終端輸入protoc
沒有打印出幫助文檔,那么就是未安裝。
$ protoc
Usage: protoc [OPTION] PROTO_FILES
Parse PROTO_FILES and generate output based on the options given:
-IPATH, --proto_path=PATH Specify the directory in which to search for
imports. May be specified multiple times;
directories will be searched in order. If not
……
可以通過官方文檔提示的命令進行安裝。
go get github.com/micro/protoc-gen-micro/v2
安裝成功之后,通過protoc命令將greeter.proto
文件生成出對應的Go文件。
protoc --proto_path=./protos --micro_out=./protos --go_out=./protos ./protos/greeter.proto
-
--proto_path
是greeter.proto文件所在的路徑 -
--micro_out
是生成.go
文件的所在目錄,該文件被用於創建服務 -
--go_out
是生成.go
文件的所在目錄,該文件被用於做數據序列化傳輸
可以根據需求自定義輸出目錄,我這邊輸出到了protos目錄,現在可以看到protos目錄中生成了兩個文件。
greeter.pb.go
greeter.pb.micro.go
實現服務
因為剛才已經通過protobuf定義了服務的接口,所以接下來需要實現對應的服務。
第一步,實現定義的服務接口
在生成的greeter.pb.micro.go
文件中,可以看到我們greeter.proto
文件中一個名為GreeterHandler
的接口。
type GreeterHandler interface {
Hello(context.Context, *Request, *Response) error
}
我們需要先實現該接口,接下來創建server.go文件,定義結構體Greeter,並實現Hello方法。
type Greeter struct {
}
func (g *Greeter) Hello(context context.Context, req *protos.Request, rsp *protos.Response) error {
rsp.Greeting = "Hello " + req.Name
return nil
}
Hello方法的后兩個參數剛好就是我們前面所生成的greeter.bp.go
文件中定義的Request和Response結構體。在方法內部,將請求參數的Name前面拼接上了Hello
字符串,並且賦值給了Response的Greeting變量。
第二步,初始化服務
我們創建一個名為greeter
的服務。
func main() {
service := micro.NewService(
micro.Name("greeter"),
)
service.Init()
}
調用micro.NewService
方法來創建一個新的服務,該方法的參數是可變參數,可以通過micro中的一系列方法來設置服務的參數,本次示例中只配置服務的名稱,記得在創建完服務后執行service.Init
方法來初始化,micro版本建議使用v2。
第三步,注冊服務到handler
func main() {
service := micro.NewService(
micro.Name("greeter"),
)
service.Init()
err := protos.RegisterGreeterHandler(service.Server(), new(Greeter))
if err != nil {
fmt.Println(err)
}
}
第四步,將服務跑起來
if err := service.Run(); err != nil {
fmt.Println(err)
}
完整代碼如下
package main
import (
"context"
"fmt"
"github.com/micro/go-micro/v2"
)
type Greeter struct {
}
func (g *Greeter) Hello(context context.Context, req *Request, rsp *Response) error {
rsp.Greeting = "Hello " + req.Name
return nil
}
func main() {
service := micro.NewService(
micro.Name("greeter"),
)
service.Init()
err := protos.RegisterGreeterHandler(service.Server(), new(Greeter))
if err != nil {
fmt.Println(err)
}
if err := service.Run(); err != nil {
fmt.Println(err)
}
}
現在將服務端跑起來。
$ go run server.go
2020-03-27 11:28:20 Starting [service] greeter
2020-03-27 11:28:20 Server [grpc] Listening on [::]:63763
2020-03-27 11:28:20 Registry [mdns] Registering node: greeter-8afc1183-a159-4473-a567-c13b83d1d75c
實現客戶端
創建client.go
文件
func main() {
service := micro.NewService(micro.Name("greeter.client"))
service.Init()
greeter := protos.NewGreeterService("greeter", service.Client())
rsp, err := greeter.Hello(context.TODO(), &protos.Request{Name: "pingye"})
if err != nil {
fmt.Println(err)
}
fmt.Println(rsp.Greeting)
}
執行客戶端文件,輸出Hello pingye
,執行成功。
$ go run client.go
Hello pingye
服務注冊到了哪里?
在啟動服務端的時候從終端輸出的信息可以看出,有一個名為greeter
的服務注冊到了Registry
。
2020-03-27 11:28:20 Starting [service] greeter
2020-03-27 11:28:20 Server [grpc] Listening on [::]:63763
2020-03-27 11:28:20 Registry [mdns] Registering node: greeter-8afc1183-a159-4473-a567-c13b83d1d75c
Registry是go-micro的注冊模塊,作用是將服務注冊到某個介質,以方便客戶端使用。注冊模塊默認支持cache、consul、etcd、k8s、mdns、memory等多種介質,默認使用的是mdns。
var (
DefaultRegistry = NewRegistry()
// Not found error when GetService is called
ErrNotFound = errors.New("service not found")
// Watcher stopped error when watcher is stopped
ErrWatcherStopped = errors.New("watcher stopped")
)
mdns主要用於在沒有傳統DNS服務器的情況下,在局域網中實現主機之間的發現與通訊,它遵從DNS協議。
Go語言組件示例開源庫,歡迎star
https://github.com/EnochZg/golang-examples