基於Golang的微服務——Micro實踐(一)

這篇文章主要是微服務服務端的實踐。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

Go Micro提供分佈式系統開發的核心庫,包含RPC與事件驅動的通訊機制。micro的設計哲學是可插拔的架構理念,她提供可快速構建系統的組件,而且能夠根據自身的需求剝離默認實現並自行定製。golang

Go Micro主要特性

Go Micro 把分佈式系統的各類細節抽象出來web

  • 服務發現(Service Discovery) - 自動服務註冊與名稱解析。服務發現是微服務開發中的核心。當服務A要與服務B協做時,它得知道B在哪裏。默認的服務發現系統是Consul,而multicast DNS (mdns,組播)機制做爲本地解決方案,或者零依賴的P2P網絡中的SWIM協議(gossip)
  • 負載均衡(Load Balancing) - 在服務發現之上構建了負載均衡機制。當咱們獲得一個服務的任意多個的實例節點時,咱們要一個機制去決定要路由到哪個節點。咱們使用隨機處理過的哈希負載均衡機制來保證對服務請求頒發的均勻分佈,而且在發生問題時進行重試。
  • 消息編碼(Message Encoding) - 支持基於內容類型(content-type)動態編碼消息。客戶端和服務端會一塊兒使用content-type的格式來對Go進行無縫編/解碼。各類各樣的消息被編碼會發送到不一樣的客戶端,客戶端服服務端默認會處理這些消息。content-type默認包含proto-rpc和json-rpc。
  • Request/Response - RPC通訊基於支持雙向流的請求/響應方式,咱們提供有抽象的同步通訊機制。請求發送到服務時,會自動解析、負載均衡、撥號、轉成字節流,默認的傳輸協議是http/1.1,而tls下使用http2協議。
  • 異步消息(Async Messaging) - 發佈訂閱(PubSub)頭等功能內置在異步通訊與事件驅動架構中。事件通知在微服務開發中處於核心位置。默認的消息傳送使用點到點http/1.1,激活tls時則使用http2。
  • 可插拔接口(Pluggable Interfaces) - Go Micro爲每一個分佈式系統抽象出接口。所以,Go Micro的接口都是可插拔的,容許其在運行時不可知的狀況下仍可支持。因此只要實現接口,能夠在內部使用任何的技術

Go micro 組成包

  • transport 用於同步消息
  • broker 用於異步消息
  • codec 用於消息編碼
  • registry 用於服務發現
  • selector 用於負載均衡
  • client 用於發送請求
  • server 用於處理請求

註冊(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)

官方的Greeter示例

若是按照文章開頭執行的那三個命令行,用的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就能夠看到註冊的微服務名稱了。

也能夠本地啓動 consul,而後將consul設置爲註冊中心,執行命令:

go run main.go --registry=consul 
複製代碼

就能夠在consul自帶的UI控制面板裏找到對應註冊的服務(go.micro.srv.greeter)

題外話:我的經驗,平常開發過程當中若是遇到問題跨不過去,能夠多查查資料,請教別人,一時解決不了的暫時放下,隔段時間回頭在看,不少時候都會有新的思路和解決辦法,不要死懟着問題不放。還有就是代碼若是邏輯實現太複雜了,請停下來,想下是否是本身的實現思路有問題,多半就是實現方式有問題,不會有很複雜的代碼的。血淚教訓,之前本身遇到問題了就是猛懟,身邊也沒有人能夠請教。其實那是不對的,很浪費時間。

編寫本身的服務

官方示例運行正常了就來嘗試下寫本身的服務吧。根據以前提到的

如何才能使用micro

  • 使用go-micro編寫服務。
  • 使用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代碼實現

  • protoc
  • protoc-gen-go
  • protoc-gen-micro
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 Handler中定義的接口。
  • 初始化 micro.Service
  • 註冊 Popular handler
  • 運行服務

切換到 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實踐(二)

相關文章
相關標籤/搜索