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用来过滤服务的,不过没细看,留个坑,以后来填。

相关文章
相关标签/搜索