天天看點

go-micro V2 從零開始(一)使用micro工具自動生成項目前言一、Go-Micro是什麼?二、第一個微服務 hello-service三、服務調用 hello-cli總結支援一下

本文相關代碼:gitee

文章目錄

  • 前言
  • 一、Go-Micro是什麼?
    • 1.go-micro簡介
    • 2.go-micro的主要功能
    • 3.go-micro通信流程
  • 二、第一個微服務 hello-service
    • 1.安裝micro
    • 2.自動生成代碼
    • 3.項目結構
    • 4.protobuf
    • 5.啟動服務
  • 三、服務調用 hello-cli
  • 總結
  • 支援一下

前言

由于go語言和go-micro架構疊代迅速,我在學習go-micro架構查詢資料時,經常因為過時的資料遇到莫名其妙的錯誤。是以我決心根據自己的實踐與摸索,編寫一個适合go-micro V2版本切實可用的go-micro開發指南,重點記錄開發的流程和各類問題的解決方案。希望這份筆記能夠幫助以後的自己,和所有看到它的朋友實作以下目标:

  1. 順利搭建一個目前版本下被反複驗證可行的go-micro系統
  2. 通過一系列插件引入對go-micro架構全貌有大緻了解
  3. 在筆記中快速檢索到go-micro架構的各種搭建問題解決方案

注意:本章主要是使用micro工具自動生成第一個微服務,并用用戶端調用它,不會詳細講解其中的代碼,具體代碼邏輯以及如何手寫項目,請看第二章。

一、Go-Micro是什麼?

以下内容摘抄自:http://www.topgoer.com

1.go-micro簡介

Go Micro是一個插件化的基礎架構,基于此可以建構微服務,Micro的設計哲學是可插拔的插件化架構

在架構之外,它預設實作了consul作為服務發現(2019年源碼修改了預設使用mdns),通過http進行通信,通過protobuf和json進行編解碼

2.go-micro的主要功能

服務發現: 自動服務注冊和名稱解析。服務發現是微服務開發的核心。當服務A需要與服務B通話時,它需要該服務的位置。預設發現機制是多點傳播DNS(mdns),一種零配置系統。您可以選擇使用SWIM協定為p2p網絡設定八卦,或者為彈性雲原生設定設定consul

負載均衡: 基于服務發現建構的用戶端負載均衡。一旦我們獲得了服務的任意數量執行個體的位址,我們現在需要一種方法來決定要路由到哪個節點。我們使用随機散列負載均衡來提供跨服務的均勻分布,并在出現問題時重試不同的節點

消息編碼: 基于内容類型的動态消息編碼。用戶端和伺服器将使用編解碼器和内容類型為您無縫編碼和解碼Go類型。可以編碼任何種類的消息并從不同的用戶端發送。用戶端和伺服器預設處理此問題。這包括預設的protobuf和json

請求/響應: 基于RPC的請求/響應,支援雙向流。我們提供了同步通信的抽象。對服務的請求将自動解決,負載平衡,撥号和流式傳輸。啟用tls時,預設傳輸為http / 1.1或http2 Async

Messaging: PubSub是異步通信和事件驅動架構的一流公民。事件通知是微服務開發的核心模式。啟用tls時,預設消息傳遞是點對點http / 1.1或http2

可插拔接口: Go Micro為每個分布式系統抽象使用Go接口,是以,這些接口是可插拔的,并允許Go Micro與運作時無關,可以插入任何基礎技術 插件位址:https://github.com/micro/go-plugins

3.go-micro通信流程

Server監聽用戶端的調用,和Brocker推送過來的資訊進行處理。并且Server端需要向Register注冊自己的存在或消亡,這樣Client才能知道自己的狀态

Register服務的注冊的發現,Client端從Register中得到Server的資訊,然後每次調用都根據算法選擇一個的Server進行通信,當然通信是要經過編碼/解碼,選擇傳輸協定等一系列過程的

如果有需要通知所有的Server端可以使用Brocker進行資訊的推送,Brocker 資訊隊列進行資訊的接收和釋出

二、第一個微服務 hello-service

開始第一個項目前,請先使用

go version

指令檢視您的語言版本,因為截至發文時(2020.9.10) go-micro 依賴的部分包尚未适配go1.15版本,是以本教程建議在go1.14+版本中運作。

同時考慮到國内的網絡環境,請確定

go env

GO111MODULE=on

且配置了正确的依賴代理服務(推薦

GOPROXY=https://goproxy.io

)。

1.安裝micro

這裡需要說明一下,我們微服務使用的架構叫

go-micro

,他将被內建到我們的項目中。

同時,官方還為我們提供了另一個叫

micro

的項目,他是一個官方工具包,主要是通過編譯後的可執行檔案為我們開發提供各種幫助,這裡我們安裝的就是

micro

工具包:

go get github.com/micro/micro/v2
           

安裝完成後可以執行

micro help

看到如下資訊表示已經安裝成功:

NAME:
   micro - A microservice runtime
   Use `micro [command] --help` to see command specific help.
USAGE:
   micro [global options] command [command options] [arguments...]
VERSION:
   latest
COMMANDS:
   server      Run the micro server
   以下省略...

           

2.自動生成代碼

實際上,通過閱讀幫助文檔不難發現,

micro

本身也是一個微服務,後續我們會講到他的更多作用,這裡我們重點講如何使用micro自動生成我們自己的微服務代碼。

執行如下指令:

# 首先進入到項目目錄,這裡我以我自己的go項目目錄為例
cd go-workspace

# 調用micro生成代碼
# 預設情況下Micro生成的代碼會放到GOPATH/src中,通過配置--gopath=false可以選擇在目前目錄下
micro new --gopath=false hello
           

3.項目結構

代碼生成後,micro會輸出大量項目資訊,我們觀察這段資訊。

首先是項目結構,可以看到micro為我們建立了一個

hello

檔案夾,并在裡面寫入了一個完整的

go mod

項目:

Creating service go.micro.service.hello in hello

.
├── main.go						#程式入口
├── generate.go
├── plugin.go
├── handler						#服務的主要處理邏輯,(僅僅是)類似java spring項目的service
│   └── hello.go
├── subscriber					#消息處理邏輯
│   └── hello.go
├── proto						#存放proto檔案,并生成相關業務代碼
│   └── hello
│       └── hello.proto
├── Dockerfile					#docker鏡像配置檔案
├── Makefile					#若幹make指令幫助我們自動化管理項目
├── README.md
├── .gitignore
└── go.mod
           

這裡補充說明一下,為了照顧大多數讀者,本教程盡量不會使用make指令,但還是建議 win環境的朋友自行搜尋MinGW的安裝和配置,因為這東西用過你就知道真香。

如果你安裝完mingw-get-setup在執行install的時候發現總是下載下傳逾時,請用USB将手機4G網共享給電腦,有奇效,當然梯子效果更佳。

4.protobuf

Protobuf是一種平台無關、語言無關、可擴充且輕便高效的序列化資料結構的協定,可以用于網絡通信和資料存儲。在go-micro中,官方雖然也支援json格式資料傳輸,但預設是protobuf。

這種格式相對json有兩個弊端:

  • 首先,protobuf有一定學習成本,好在日常使用隻需要參考自動代碼中

    hello.proto

    的格式學會定義接口和參數即可(熟練後強烈建議進一步深入學習)
  • 其次,需要安裝不少的工具,go-micro官方也是考慮到這一點,是以在代碼生成文檔的最後詳細列出了工具安裝步驟(考慮到不同版本問題,請務必使用你的控制台中看到的指令,一下内容僅供參考)
# 首先要下下載下傳protoc協定的編解碼器,下載下傳安裝後放在任意`path`路徑下一邊被指令行調用
# 我一般會把他放在 GOPATH/bin 目錄下
download protoc zip packages (protoc-$VERSION-$PLATFORM.zip) and install:

visit https://github.com/protocolbuffers/protobuf/releases

# 接下來是下載下傳三個go語言的proto包,用于生成對應go語言的micro代碼
download protobuf for micro:

go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
go get github.com/micro/micro/v2/cmd/protoc-gen-micro

# 最後是進入到你建立的項目中,通過proto檔案生成micro代碼
compile the proto file hello.proto:

cd hello
# 沒有make的win環境朋友可以直接複制執行makefile檔案裡面的指令,效果是一樣的:
# protoc --proto_path=. --micro_out=Mproto/imports/api.proto=github.com/micro/go-micro/v2/api/proto:. --go_out=Mproto/imports/api.proto=github.com/micro/go-micro/v2/api/proto:. proto/hello/hello.proto
#這一步先不要着急執行,往下看(重要的話說三遍)
#這一步先不要着急執行,往下看(重要的話說三遍)
#這一步先不要着急執行,往下看(重要的話說三遍)
make proto	
           

如果你不聽話,直接執行了,會發現程式順利執行,隻是有一條警告資訊:

2020/09/10 11:01:43 WARNING: Missing 'go_package' option in "proto/hello/hello.p
roto",
please specify it with the full Go package path as
a future release of protoc-gen-go will require this be specified.
See https://developers.google.com/protocol-buffers/docs/reference/go-generated#p
ackage for more information.
           

這裡,我們需要預處理一下

hello.proto

檔案,在最上面加入一行資訊:

go-micro V2 從零開始(一)使用micro工具自動生成項目前言一、Go-Micro是什麼?二、第一個微服務 hello-service三、服務調用 hello-cli總結支援一下

這行資訊用于指定生成代碼所屬的包路徑,因為我們将代碼生成在

hello.proto

同目錄下,是以包路徑使用

proto/hello

,如果你的項目想把生成的go檔案放在其他路徑,則根據實際情況填寫。

完成修改後,執行

make proto

或者完整的生成指令:

> protoc --proto_path=. --micro_out=Mproto/imports/api.proto=github.com/micro/go-m
icro/v2/api/proto:. --go_out=Mproto/imports/api.proto=github.com/micro/go-micro/
v2/api/proto:. proto/hello/hello.proto
           

這裡官方寫法比較冗長,如果是目前目錄下可以簡寫為

protoc --proto_path=. --micro_out=. --go_out=. proto/hello/hello.proto

注意,其中的

--go_out

--micro_out

參數指定了生成檔案的輸出路徑,應與上一步我們修改的

go_package

保持一緻。

5.啟動服務

至此,所有代碼都已經生成完畢,理論上

go mod tidy && go run main.go

就可以愉快的跑起來了。

> go run main.go
2020-09-10 11:30:29  file=[email protected]/service.go:200 level=info Starting [service] go.micro.service.hello
2020-09-10 11:30:29  file=grpc/grpc.go:864 level=info Server [grpc] Listening on [::]:60662
2020-09-10 11:30:29  file=grpc/grpc.go:881 level=info Broker [http] Connected to 127.0.0.1:60663
2020-09-10 11:30:29  file=grpc/grpc.go:697 level=info Registry [mdns] Registering node: go.micro.service.hello-3b9e045d-6db0-47a5-9504-743b4d9175ba
2020-09-10 11:30:29  file=grpc/grpc.go:730 level=info Subscribing to topic: go.micro.service.hello
           

根據日志資訊,會發現架構幫我們啟動了

  • 服務:

    go.micro.service.hello-3b9e045d-6db0-47a5-9504-743b4d9175ba

  • 服務發現:

    mdns

  • 基于

    grpc

    的Server服務:

    60662

  • 基于

    http

    的Broker服務:

    60663

  • 訂閱消息服務,主題:

    go.micro.service.hello

你可以在另一個指令行視窗執行

micro list services

指令,可以看到我們的服務

go.micro.service.hello

已經被注冊:

> micro list services
go.micro.service.hello
micro.http.broker
           

如果你看到如下報錯,是由于第三方庫相容性造成的。這個問題困擾了我很久,但是在我寫文時,已經被官方最新版解決:

# github.com/coreos/etcd/clientv3/balancer/picker
F:\go\pkg\mod\github.com\coreos\[email protected]+incompatible\clientv3\balancer\picker\err.go:37:44: undefined: balancer.PickOptions
F:\go\pkg\mod\github.com\coreos\[email protected]+incompatible\clientv3\balancer\picker\roundrobin_balanced.go:55:54: undefined: balancer.PickOptions
# github.com/coreos/etcd/clientv3/balancer/resolver/endpoint
F:\go\pkg\mod\github.com\coreos\[email protected]+incompatible\clientv3\balancer\resolver\endpoint\endpoint.go:114:78: undefined: resolver.BuildOption
F:\go\pkg\mod\github.com\coreos\[email protected]+incompatible\clientv3\balancer\resolver\endpoint\endpoint.go:182:31: undefined: resolver.ResolveNowOption
# github.com/micro/go-micro/transport/quic
F:\go\pkg\mod\github.com\micro\[email protected]\transport\quic\quic.go:54:12: q.s.Close undefined (type quic.Session has no field or method Close)
F:\go\pkg\mod\github.com\micro\[email protected]\transport\quic\quic.go:121:3: unknown field 'IdleTimeout' in struct literal of type quic.Config
           

在 go.mod 檔案中添加以下兩行 replace 解決編譯問題

replace google.golang.org/grpc => google.golang.org/grpc v1.26.0
replace github.com/lucas-clemente/quic-go => github.com/lucas-clemente/quic-go v0.14.1
           

三、服務調用 hello-cli

如上所述,我們已經啟動了第一個go-micro微服務hello,怎麼調用他呢?我們可以建立一個

hello-cli.go

檔案:

package main

import (
	"context"
	"github.com/micro/go-micro/v2"
	"github.com/micro/go-micro/v2/client"
	pb "hello/proto/hello"
	"log"
)

func main() {
	// 這裡以HelloService預設提供的Call接口調用為例示範服務的調用
	// 可以看到他的調用就像調用本地方法一樣,go-micro為我們隐藏了背後的服務注冊、發現、負載均衡以及網絡操作
	testCallFunc()
	
	// 這裡示範消息的發送
	testSendMessage()
}
func testCallFunc(){
	// 擷取hello服務
	// 這裡第一個參數"go.micro.service.hello"必須與hello-service注冊資訊一緻
	// 一般由micro生成的項目預設服務名為:{namespace 預設[go.micro]}.{type 預設[service]}.{項目名}組成
	// 如果要修改預設值,在生成項目時可以這樣: micro --namespace=XXX --type=YYYY ZZZZ
	// 當然也可以直接修改main.go中micro.Name("go.micro.service.hello")的内容
	helloService := pb.NewHelloService("go.micro.service.hello", client.DefaultClient)

	// 預設生成的hello服務中自帶三個接口: Call() Stream() PingPong(),分别對應參數調用、流傳輸和心跳
	resp, err := helloService.Call(context.Background(), &pb.Request{
		Name: "xiao xie",
	})
	if err != nil {
		log.Panic("call func", err)
	}
	log.Println("call func success!", resp.Msg)
}

func testSendMessage(){
	// 消息主題,定義規則與服務一緻
	// 同樣,也可以修改main.go的micro.RegisterSubscriber("go.micro.service.hello", service.Server(), new(subscriber.Hello))
	const topic = "go.micro.service.hello"
	// 擷取消息發送接口,這裡我一直使用的時micro.NewPublisher()
	// 但在寫文時發現NewPublisher()已經被廢止,改為NewEvent(),二者參數和傳回值一緻
	event := micro.NewEvent(topic, client.DefaultClient)
	if err := event.Publish(context.Background(), &pb.Message{
		Say: "hello server!",
	}); err != nil {
		log.Panic("send msg", err)
	}
	log.Println("send msg success!")
}
           

執行

go run hello-cli.go

,即可看到運作結果:

> go run hello-cli.go
2020-09-10 12:43:25.446682 I | call func success! Hello xiao xie
2020-09-10 12:43:25.547441 I | send msg success!
           

至此,一個基礎的微服務就部署完成并通過測試了。

總結

本章我們介紹了借助

micro

工具包快速編寫go-micro微服務的基本操作流程,和微服務的兩種基本調用方式

gRpc

消息

,由于篇幅關系我們并沒有詳解自動生成的代碼的含義。

下一章我們将參考示例代碼結構手動編寫一個微服務,并在後續章節中逐漸開發一個微服務化的

todolist

項目。

支援一下

原創不易,支援一下買杯咖啡,謝謝:p

go-micro V2 從零開始(一)使用micro工具自動生成項目前言一、Go-Micro是什麼?二、第一個微服務 hello-service三、服務調用 hello-cli總結支援一下