go-micro v1.7.0 breaks calls to non-go-micro service

Created on 2 Jul 2019  路  8Comments  路  Source: asim/go-micro

We've recently moved from a dependency on micro/go-micro v1.1.0 - which in turn depended on micro/go-grpc v1.0.0 - to using go-micro v.1.7.0, and that seems to have broken interoperability from our Go services using go-micro to a C# service using generated C# code per the official C# / GRPC documentation. Our requests are being responded to with GRPC status code 12, unimplemented.

With GRPC_TRACE and GRPC_DEBUG we can see requests from the Go service to e.g. "/usUsers-v1.Users/GetUserPassword" on the C# service. That's /<name of service in consul>.<protobuf service name>/<method name>/.

My understanding is that the API URL should be /<protobuf package name>.<protobuf service name>/<method name>. e.g. for the helloworld example you can see the request path is expected to be "/helloworld.Greeter/SayHello". In our protobuf generated C# code we have the following line - static readonly string __ServiceName = "userspb.Users"; - which seems to indicate that the C# code is expecting requests to match that convention.

We're constructing the service client with:

service := grpc.NewService(
    micro.Name(serviceName), // usUsers-v1
    grpc.WithTLS(tlsConfig),
    micro.Registry(consulreg.NewRegistry()),
)
service.Init()
service.Client().Init(client.RequestTimeout(time.Second * time.Duration(timeoutSecs)))

We could change the service name to be "userspb" but that would change the name registered in Consul, and then we could never have multiple services using the same protobuf.

question

Most helpful comment

Micro's code generation is for its default protocol which is rpc not grpc. Hardcoding it to accommodate grpc would break a number of things but also highlights that maybe people should just be using grpc directly in that case.

All 8 comments

The following replace directive:

replace github.com/micro/go-micro => github.com/micro/go-micro v1.6.0

in my go.mod fixes the issue - service calls work as expectged - so it must be something that changed from 1.6.0 => 1.7.0.

Possibly related to commit d3a6297b.

That looks like it changed client/grpc/request.go methodToGRPC() to change the prefix from the package name to the service name:

-return fmt.Sprintf("/%s.%s/%s", pkg, mParts[0], mParts[1])
+return fmt.Sprintf("/%s.%s/%s", service, mParts[0], mParts[1])

And also in a few places changed calls to methodToGRPC() to pass in req.Service() instead of req.Endpoint():

-err := cc.Invoke(ctx, methodToGRPC(req.Endpoint(), req.Body()), req.Body(), rsp, grpc.ForceCodec(cf))
+err := cc.Invoke(ctx, methodToGRPC(req.Service(), req.Endpoint()), req.Body(), rsp, grpc.ForceCodec(cf))
-st, err := cc.NewStream(ctx, desc, methodToGRPC(req.Endpoint(), req.Body()))
+st, err := cc.NewStream(ctx, desc, methodToGRPC(req.Service(), req.Endpoint()))

@GeorgeBills can you provide pr?

There's a reason for this. Proto package name is used as the service name in grpc. Go-micro doesn't actually have access to this or doesn't use it unless you provide a blank name to NewXService. Otherwise we use what's passed in. To comply with service names matching grpc service names we're now using the service name as that prefix.

I think this is correct behaviour. The alternative was a hack using the request package via reflection. If the request definition lives in a different proto file than the grpc service definition then we essentially call the wrong thing.

I think to have something configurable where it uses package as part of the grpc endpoint path we need to look at an alternative route. Open to suggestions.

@asim, couldn't protoc-gen-micro just hardcode the path to /<protobuf package name>.<protobuf service name>/<method name>? That's what protoc-gen-go does, e.g. helloworld.pb.go.

Micro's code generation is for its default protocol which is rpc not grpc. Hardcoding it to accommodate grpc would break a number of things but also highlights that maybe people should just be using grpc directly in that case.

as i know, if you use proto package name as service name and register service with the same name all must works fine.

tests with python grpc clients says that we can communicate via grpc with other services when using grpc client+server+transport

Was this page helpful?
0 / 5 - 0 ratings

Related issues

5teven picture 5teven  路  5Comments

jnvillar picture jnvillar  路  9Comments

guanwenbogit picture guanwenbogit  路  5Comments

xmlking picture xmlking  路  7Comments

aimpsmile picture aimpsmile  路  9Comments