go-micro的api版本機制看example的時候感受很簡單,可是實際要是用的時候,仍是有好幾個點費了很多時間,最終經過扒code弄的差很少了,這裏記錄下。git
go-micro能夠提供同時提供http和grpc的訪問,若是不是用自定義的EndPoint時,這兩種的api版本控制沒有區別,下面分別說下這幾種狀況下的版本控制機制。github
grpc的訪問主要是經過protobuf文件生成的對應語言的文件來訪問,因此版本控制是經過protobuf中的package定義來控制的,只須要在package的定義中加入版本信息便可,好比:golang
//v1 package go.micro.api.v1.test; //v2 package go.micro.api.v2.test;
這裏我理解只要package定義不同,能夠區別出具體的服務便可,v1和v2主要是語義上好理解api
版本號建議加載api以後,這樣能夠保持和http訪問時的一致(go-micro api gateway可自動轉換grpc到http,下邊會詳細說)數組
go-micro的http訪問主要是經過micro的api網關實現的,目前有兩種形式:app
http的url按照上面的規則解析,動態轉化爲rpc的訪問,以上面的package定義爲例less
//v1 package go.micro.api.v1.test; //url v1/test/hello //v2 package go.micro.api.v2.test; //url v2/test/hello // hello func defined
下面還有幾個url解析的官方example更明瞭一點this
Path | Service | Method |
---|---|---|
/foo/bar | go.micro.api.foo | Foo.Bar |
/foo/bar/baz | go.micro.api.foo | Bar.Baz |
/foo/bar/baz/cat | go.micro.api.foo.bar | Baz.Cat |
Versioned API URLs can easily be mapped to service names:url
Path | Service | Method |
---|---|---|
/foo/bar | go.micro.api.foo | Foo.Bar |
/v1/foo/bar | go.micro.api.v1.foo | Foo.Bar |
/v1/foo/bar/baz | go.micro.api.v1.foo | Bar.Baz |
/v2/foo/bar | go.micro.api.v2.foo | Foo.Bar |
/v2/foo/bar/baz | go.micro.api.v2.foo | Bar.Baz |
code中的實現邏輯是:版本控制
分割url爲數組
根據數組的長度來構建service和method
// If we've got two or less parts // Use first part as service // Use all parts as method if len(parts) <= 2 { name := parts[0] return name, methodName(parts) }
等於3,前面2個做爲service,後邊2個爲method
// Treat /v[0-9]+ as versioning where we have 3 parts
// /v1/foo/bar => service: v1.foo method: Foo.bar
if len(parts) == 3 && versionRe.Match([]byte(parts[0])) {
name := strings.Join(parts[:len(parts)-1], ".")
r
```
// Service is everything minus last two parts // Method is the last two parts name := strings.Join(parts[:len(parts)-2], ".") return name, methodName(parts[len(parts)-2:])
endpoint是上面不一樣的是,由於url是本身定義的,因此上面的方式解析出來的結果是錯誤的,因此必須在用url比對路由的地址的時候,就成功,不然就會報錯
我這邊想到的版本就是在設置EndPoint的時候加入版本號(客戶端請求會帶版本後,爲了在比對的時候保持一致來保證成功找到註冊的EndPoint),找到endpoint以後的流程就相同了,這裏不過多描述。
以後我會在專門寫一篇文章,從code追蹤下整個url的解析過程,就會清楚爲何須要保證url一致,比對成功
func registerUser(server server.Server) error { return pb.RegisterUserHandler(server, new(Handler), mApi.WithEndpoint(&mApi.Endpoint{ // The RPC method Name: "User.Register", // The HTTP paths. This can be a POSIX regex Path: []string{"^v1/user/register$"}, // The HTTP Methods for this endpoint Method: []string{"POST"}, // The API handler to use Handler: rpc.Handler, }), ) }
這裏的版本號須要和**protobuf文件中的package定義的一致,不然仍是服務找到對應的服務(上邊提到了version添加的位置),由於最終仍是須要經過rpc來訪問具體的服務的。
這裏還有個問題,就是在main中,初始化micro服務的時候,設置的version到目前爲止都沒有用到,我好奇搜索了下version關鍵字,有發現client/selector/filter.go
中有對應version的使用,看位置應該是client用來過濾服務的,不過沒細看,留個坑,以後來填。