go-micro api version

go-micro的api版本機制看example的時候感受很簡單,可是實際要是用的時候,仍是有好幾個點費了很多時間,最終經過扒code弄的差很少了,這裏記錄下。git

go-micro能夠提供同時提供http和grpc的訪問,若是不是用自定義的EndPoint時,這兩種的api版本控制沒有區別,下面分別說下這幾種狀況下的版本控制機制。github

grpc

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,下邊會詳細說)數組

http

go-micro的http訪問主要是經過micro的api網關實現的,目前有兩種形式:app

/[service]/[method]

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中的實現邏輯是:版本控制

  1. 分割url爲數組

  2. 根據數組的長度來構建service和method

    • 少於等於2,第一個做爲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
    ```

    • 大於3,最後兩個做爲method,其他全部做爲service
    // 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

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用來過濾服務的,不過沒細看,留個坑,以後來填。

相關文章
相關標籤/搜索