最近因為要用到 go-micro,所以在學習微服務相關的內容,這一篇是記錄 micro 的搭建過程。
micro 提供了一個 runtime,在使用 go-micro 之前需要先安裝它。有以下幾種方式安裝
原始碼
go get github.com/micro/micro/v2
這種方式我裝不上,不是網路的原因,不知道哪裡有衝突。。。
docker
docker pull micro/micro
二進位制
# MacOS
curl -fsSL https://raw.githubusercontent.com/micro/micro/master/scripts/install.sh | /bin/bash
# Linux
wget -q https://raw.githubusercontent.com/micro/micro/master/scripts/install.sh -O - | /bin/bash
# Windows
powershell -Command "iwr -useb https://raw.githubusercontent.com/micro/micro/master/scripts/install.ps1 | iex"
推薦使用這種方式下載安裝,把編譯好的二進位制包新增到環境變數就能直接使用了。不想用指令碼安裝可以在 github 的 release 頁面下載
https://github.com/micro/micro/releases
測試一下
現在已經安裝好 micro 了,測試一下。
micro web
輸出
$ micro web
2020-07-05 04:24:16 file=http/http.go:90 level=info service=web HTTP API Listening on [::]:8082
2020-07-05 04:24:16 file=v2@v2.9.1/service.go:200 level=info service=web Starting [service] go.micro.web
2020-07-05 04:24:16 file=grpc/grpc.go:864 level=info service=web Server [grpc] Listening on [::]:26449
2020-07-05 04:24:16 file=grpc/grpc.go:697 level=info service=web Registry [mdns] Registering node: go.micro.web-b76a12a1-5226-429f-9633-ce304f179657
現在訪問localhost:8082
就可以檢視 micro 的 web 頁面了。
protoc 是 protobuf 的編譯器,而 protobuf 是一種用來傳輸資料的格式,類似 json、xml 這些。
protoc 下載地址
https://github.com/protocolbuffers/protobuf/releases
下載好之後,bin 資料夾中有個 protoc 的可執行檔案,把這個也新增到環境變數。(可以直接把它放到已經新增了環境變數的資料夾下就可以了,可以避免電腦裡寫滿了各種環境變數,並且常用工具放到一個資料夾也方便管理)
還有個 protoc-gen-go 也需要放進去,可以用下面的方式下載。
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
example
現在讓我們寫一個 demo 來練習一下。
一共有三個檔案,server.go
,client.go
,greeter.proto
greeter.proto
syntax = "proto3";
package protos;
service Greeter {
rpc Hello (Request) returns (Response){};
}
message Request {
string name = 1;
}
message Response {
string greeting = 2;
}
server.go
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 := RegisterGreeterHandler(service.Server(), new(Greeter))
if err != nil {
fmt.Println(err)
}
if err := service.Run(); err != nil {
fmt.Println(err)
}
}
client.go
package main
import (
"context"
"fmt"
"github.com/micro/go-micro/v2"
)
func main() {
service := micro.NewService(micro.Name("greeter.client"))
service.Init()
greeter := NewGreeterService("greeter", service.Client())
rsp, err := greeter.Hello(context.TODO(), &Request{Name: "Zaun pianist"})
if err != nil {
fmt.Println(err)
}
fmt.Println(rsp.Greeting)
}
強烈建議使用 go mod 來管理依賴,專案更新速度很快,百度上的很多教程都不行了,安裝過程各種錯誤
這是我的 mod 檔案
module hello
go 1.14
require (
github.com/golang/protobuf v1.4.0
github.com/micro/go-micro/v2 v2.9.1
google.golang.org/protobuf v1.22.0
)
注意,我的 greeter.proto 和 server.go、client.go 檔案是放在同一個資料夾下面的
編譯greeter.proto
protoc --micro_out=. --go_out=. greeter.proto
編譯完成之後,會生成兩個 go 原始碼檔案:
greeter.pb.go
greeter.pb.micro.go
執行
現在可以執行 server 了,這裡因為 client 和 server 是放在同一個資料夾,也就是同一個包中,兩個都有 main 函式,所以不能用 go run ./
,至於為什麼要加上另外兩個,這個是 go 語言編譯器的要求,必須要指明編譯所需要用到的檔案。
go run server.go greeter.pb.go greeter.pb.micro.go
可以用 micro 來檢視當前正在執行的微服務
micro list services
也可以在 web 端檢視
micro web
如果沒有出錯,這個時候是可以看到服務已經註冊成功了。
$ micro list services
go.micro.web
greeter
測試
現在可以執行客戶端來測試一下了
go run client.go greeter.pb.go greeter.pb.micro.go
我在測試的時候出了問題,服務已經註冊好了,但是 client 去呼叫的時候,缺返回了
{"id":"go.micro.client","code":408,"detail":"context deadline exceeded","status":"Request Timeout"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x28 pc=0xeef454]
檢查一下服務的資訊
micro get service greeter
$ micro get service greeter
service greeter
version latest
ID Address Metadata
greeter-5d86321e-86f2-41a6-8230-f015466bf791 10.198.75.60:51395 broker=http,protocol=grpc,registry=mdns
,server=grpc,transport=grpc
Endpoint: Greeter.Hello
Request: {
message_state MessageState {
no_unkeyed_literals NoUnkeyedLiterals
do_not_compare DoNotCompare
do_not_copy DoNotCopy
message_info MessageInfo
}
int32 int32
unknown_fields []uint8
name string
}
Response: {
message_state MessageState {
no_unkeyed_literals NoUnkeyedLiterals
do_not_compare DoNotCompare
do_not_copy DoNotCopy
message_info MessageInfo
}
int32 int32
unknown_fields []uint8
greeting string
}
注意看裡面的 IP 地址,註冊到了 10.198.xx 去了,因此才會報錯???
因此在註冊服務的時候,指定 IP 地址
go run server.go greeter.pb.go greeter.pb.micro.go --server_address=localhost:8888
這個時候再用 client 呼叫就不會出錯了。
$ go run client.go greeter.pb.go greeter.pb.micro.go
Hello Zaun pianist
本作品採用《CC 協議》,轉載必須註明作者和本文連結