golang[86]-go-micro版本差异带来的问题f

起因

问题的起因在我的新项目中使用最新microv1.9.1版本调用发送邮件的follow.srv.push服务出现问题:

1
{"id":"go.micro.client","code":500,"detail":"","status":"Internal Server Error"}

经过排查发现 go-micro 1.7以上含1.7 client发送给服务器端的fullmethod发生了改变。
从 /push.PushSrv/Push => /followme.srv.push.PushSrv/Push
从 /followme.trade-engine.TradeEngine/Close 到 /tradeengine.TradeEngine/Close

问题追踪

具体出现在
122行 github.com/micro/go-plugins1.0/client/grpc/grpc.go
//method:/PushSrv.Push

1
err := cc.Invoke(ctx, methodToGRPC(req.Endpoint(), req.Body()), req.Body(), rsp, grpc.CallContentSubtype(cf.String()))

变为了:
go-micro@1.9/client/grpc/grpc.go
//method:/followme.srv.push.PushSrv/Push

1
err := cc.Invoke(ctx, methodToGRPC(req.Service(), req.Endpoint()), req.Body(), rsp, grpc.CallContentSubtype(cf.Name()))

导致访问出现问题。

go-micro代码改变commit地址:https://github.com/micro/go-micro/commit/d3a6297b17cb78602875440b62d88971346a0f05

解决办法

由于新版本的micro,req.Service()其实是注册的microName,那么是否可以将其变为Push?这样传递到服务器的fullmethod就变为了/push.PushSrv/Push。
但是,由于在micro的代码中,registery又需要microName从consul中拿到服务地址,因此可以从这里下手hook去consul中访问的服务名。

下面给出一段micro1.9 调用push的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package main

import (
"context"
"fmt"
"github.com/micro/go-micro"
"github.com/micro/go-micro/client/selector"
"github.com/micro/go-micro/registry"
"github.com/micro/go-micro/registry/consul"
"github.com/micro/go-micro/service/grpc"
"gitlab.followme.com/CopyTradingGo/proto/src/push"
"strconv"
"time"
)

type NewRegistry struct {
C registry.Registry
}

func (c NewRegistry) Init(opts...registry.Option) error {
return c.C.Init(opts...)
}

func (c NewRegistry) Options() registry.Options {
return c.C.Options()
}

func (c NewRegistry) Register(srv *registry.Service,opts ...registry.RegisterOption) error {
return c.C.Register(srv,opts...)
}

func (c NewRegistry) Deregister(srv*registry.Service) error {
return c.C.Deregister(srv)
}

func (c NewRegistry) GetService(s string) ([]*registry.Service, error) {
return c.C.GetService("followme.srv.push")
}

func (c NewRegistry) ListServices() ([]*registry.Service, error) {
return c.C.ListServices()
}

func (c NewRegistry) Watch(opts...registry.WatchOption) (registry.Watcher, error) {
return c.C.Watch(opts...)
}

func (c NewRegistry) String() string {
return c.C.String()
}

func main(){
reg := consul.NewRegistry(func(op *registry.Options) {
op.Addrs = []string{
"192.168.8.6:8500",
}
})
service:= grpc.NewService(
micro.Registry(reg),
)

newreg:= NewRegistry{C:reg}
service.Client().Options().Selector.Init(selector.Registry(newreg))
srv:= push.NewPushSrvService("push", service.Client())
smsParams := []string{
"demo",
strconv.FormatInt(int64(1), 10),
strconv.FormatFloat(99.99, 'f', -1, 64),
}

var req = new(push.PushRequest)
req.Type = push.PushType_SMS
req.Sender = "guard"
req.ToUserId = 80
var sms = new(push.SMSRequest)
sms.TemplateId = 100401
sms.Params = smsParams
req.Sms = sms
ctx:=context.Background()
cc,_:= context.WithTimeout(ctx,5*time.Minute)
result,err:= srv.Push(cc,req)
fmt.Println(result,err)
}

一开始以为所有高版本的micro 调用低版本的micro都会出现问题。 但是我经过多次实验发现,micro1.9调用 trade-engine micro1.1版本ok。
我接着怀疑是不是trade-engine做了特殊处理。查看代码未发现问题。
我接着自己实验了用1.9版本micro 去调用自己的1.1版本 helloworld服务,仍然OK。
接着查看代码发现,1.9版本传递过来的fullmethod确实是/followme.trade-engine.Say/Hello
但是fullmethod拆分为了servise:Say 以及method:Hello。 只用到了这两个参数。
也就是说不管是1.9版本传递的/followme.trade-engine.Say/Hello 还是1.1版本传递的 /tradeEngine.Say/Hello,服务器只需要最后的Say/Hello。
所以即便是修改了fullmethod,仍然可以用高版本调用低版本。

问题:为何高版本不能调用Push?

push是C#维护,推测是C#对传递过去的fullmethod做了处理,必须要保证匹配。