這篇文章主要是微服務服務端的實踐。node
開始開發前須要先配置好Go的開發環境,能夠看我寫的基於Golang的微服務——上手篇git
在 GOPATH目錄下的src目錄下建立咱們的實戰項目目錄 tech,切換到這個目錄github
go get github.com/micro/go-micro //用於開發的微服務的RPC框架,是micro架構的基礎
go get github.com/micro/protoc-gen-micro // 用於生成Protobuf的代碼
go get github.com/micro/micro // 工具集安裝,會自動將 micro加入環境變量
複製代碼
Go Micro提供分佈式系統開發的核心庫,包含RPC與事件驅動的通訊機制。micro的設計哲學是可插拔的架構理念,她提供可快速構建系統的組件,而且能夠根據自身的需求剝離默認實現並自行定製。golang
Go Micro 把分佈式系統的各類細節抽象出來web
註冊(Registry) 註冊提供了服務發現機制來解析服務名到地址上。它可使用Consul、etcd、zookeeper、dns、gossip等等提供支持。服務使用啓動註冊關機卸載的方式註冊。服務能夠選擇性提供過時TTL和定時重註冊來保證服務在線,以及在服務不在線時把它清理掉。算法
選擇器(Selector) 選擇器是構建在註冊這上的負載均衡抽象。它容許服務被過濾函數過濾掉不提供服務,也能夠經過選擇適當的算法來被選中提供服務,算法能夠是隨機、輪詢(客戶端均衡)、最少連接(leastconn)等等。選擇器經過客戶端建立語法時發生做用。客戶端會使用選擇器而不是註冊表,由於它提供內置的負載均衡機制。json
傳輸(Transport) Transport是服務與服務之間同步請求/響應的通訊接口。和Golang的net包相似,可是提供更高級的抽象,請容許咱們能夠切換通訊機制,好比http、rabbitmq、websockets、NATs。傳輸也支持雙向流,這一強大的功能使得客戶端能夠向服務端推送數據。api
代理(Broker) Broker提供異步通訊的消息發佈/訂閱接口。對於微服務系統及事件驅動型的架構來講,發佈/訂閱是基礎。一開始,默認咱們使用收件箱方式的點到點HTTP系統來最小化依賴的數量。可是,在go-plugins是提供有消息代理實現的,好比RabbitMQ、NATS、NSQ、Google Cloud Pub Sub等等。bash
編碼(Codec) 編碼包用於在消息傳輸到兩端時進行編碼與解碼,能夠是json、protobuf、bson、msgpack等等。與其它編碼方式不一樣,咱們支持RPC格式。因此咱們有JSON-RPC、PROTO-RPC、BSON-RPC等格式。websocket
編碼包把客戶端與服務端的編碼隔離開來,並提供強大的方法來集成其它系統,好比gRPC、Vanadium等等。
Server(服務端) Server包是使用編寫服務的構建包,能夠命名服務,註冊請求處理器,增長中間件等等。服務構建在以上說的包之上,提供獨立的接口來服務請求。如今服務的構建是RPC系統,在將來可能還會有其它的實現。服務端容許定義多個不一樣的編碼來服務不一樣的編碼消息。
Client(客戶端) 客戶端提供接口來建立向服務端的請求。與服務端相似,它構建在其它包之上,它提供獨立的接口,經過註冊中心來基於名稱發現服務,基於選擇器(selector)來負載均衡,使用transport、broker處理同步、異步消息。
上面的這些組件均可以在micro中,從更高的角度當作是服務(Service)
若是按照文章開頭執行的那三個命令行,用的GOPROXY 代理下載的依賴包,會有一個問題,獲取到的examples不是最新的。會有不少報錯,我本身的解決辦法是直接將目錄切換到
cd $GOPATH/pkg/mod/github/micro
git clone github.com/micro/examples examples
cd examples/greeter
複製代碼
用 git clone 直接下載最新的官網示例包 greeter示例 按照這個示例的說明文檔運行 最後發現調試 API 時出現報錯
{"id":"go.micro.client","code":500,"detail":"error selecting go.micro.srv.greeter node: not found","status":"Internal Server Error"}
複製代碼
剛開始找不到緣由,去github用蹩腳英語提問,丟人現眼了一回。哈哈,可是學到東西就行,我是這麼安慰本身的。 我在運行示例的時候,只執行了三個腳本:
go run api/api.go
micro api --handler=api
curl http://localhost:8080/greeter/say/hello?name=John
複製代碼
前兩個命令行正常,第三個報錯。去提issue,有個老外很快回復我了,但我仍是一臉懵逼。最後嘗試先執行
go run srv/main.go
複製代碼
就正常了,目前代碼裏的邏輯理解的不深刻,之後回過頭來探個究竟吧.最新版本的註冊中心沒有指定consul了,運行micro web
,能夠啓動 micro web工具集合,訪問localhost:8082
就能夠看到註冊的微服務名稱了。
go run main.go --registry=consul
複製代碼
就能夠在consul自帶的UI控制面板裏找到對應註冊的服務(go.micro.srv.greeter)
題外話:我的經驗,平常開發過程當中若是遇到問題跨不過去,能夠多查查資料,請教別人,一時解決不了的暫時放下,隔段時間回頭在看,不少時候都會有新的思路和解決辦法,不要死懟着問題不放。還有就是代碼若是邏輯實現太複雜了,請停下來,想下是否是本身的實現思路有問題,多半就是實現方式有問題,不會有很複雜的代碼的。血淚教訓,之前本身遇到問題了就是猛懟,身邊也沒有人能夠請教。其實那是不對的,很浪費時間。
官方示例運行正常了就來嘗試下寫本身的服務吧。根據以前提到的
如何才能使用micro?
來試試按照這兩步走會遇到什麼妖魔鬼怪吧
微服務中有個關鍵需求點,就是接口的強定義。Micro使用protobuf來完成這個需求。 GOPATH 文件夾下新建文件夾 popular/proto
touch popular.proto
複製代碼
建立好原型文件後,編輯文件內容
syntax = "proto3";
service Popular {
rpc Ping(PingRequest) returns (PingResponse) {}
}
message PingRequest {
string name = 1;
}
message PingResponse {
string popularing = 2;
}
複製代碼
文件的第一行指定了你使用的是proto3的語法. 咱們定義Popular處理器,它有一個Ping方法。它有PingRequest入參對象及PingResponse出參對象,兩個對象都有一個字符串類型的參數。
在定義好原型後咱們得使用protoc及micro的插件編譯它,micro插件能夠幫助生成go micro須要的原型文件。切換到$GOPATH/src
目錄,執行命令:
protoc --proto_path=$GOPATH/src/popular/proto:. --micro_out=. --go_out=. popular/proto/popular.proto
複製代碼
運行這個命令時可能會報錯
-bash: protoc: command not found
複製代碼
那是須要下面這個工具來生成protobuf代碼文件,它們負責生成定義的go代碼實現
brew install protobuf // 若是失敗就下載源碼包本身編譯,加入到環境變量,我是這麼整的
go get github.com/golang/protobuf/{proto,protoc-gen-go}
go get github.com/micro/protoc-gen-micro
複製代碼
protobuf 源碼編譯安裝會有一些報錯,忽略就行。安裝參考
一切正常後會在 proto 文件夾下生成
popular.micro.go popular.pb.go
複製代碼
須要實現幾個需求:
切換到 popular
文件夾下,建立文件 main.go
cd popular && touch main.go
複製代碼
編輯main.go 文件
package main
import (
"context"
"fmt"
micro "github.com/micro/go-micro"
proto "popular/proto"
)
type Popular struct{}
func (g *Popular) Ping(ctx context.Context, req *proto.PingRequest, rsp *proto.PingResponse) error {
rsp.Popularing = "Ping " + req.Name // (Popularing, Name 首字母都要大寫 )
return nil
}
func main() {
// 建立新的服務,這裏能夠傳入其它選項。
service := micro.NewService(
micro.Name("popular"),
)
// 初始化方法會解析命令行標識
service.Init()
// 註冊處理器
proto.RegisterPopularHandler(service.Server(), new(Popular))
// 運行服務
if err := service.Run(); err != nil {
fmt.Println(err)
}
}
複製代碼
[卡在這裏不能動了,緣由不說。。。] 幹了一成天,終於把微服務搭建起來了,有時間再整理文章吧,得休息下了,頭暈眼花。。 貼一張圖:服務發現與註冊用的是Consul
這篇關於服務端的文章到這裏暫告一段落
想繼續深刻能夠看我下一篇文章:基於Golang的微服務——Micro實踐(二)