简体   繁体   中英

gRPC server (Java) doesn't expose service depending on the order in which it is added

I am building a gRPC server that needs to expose several services, as below

Server server = ServerBuilder
        .forPort(8980)
        .addService(new GrpcService1())
        .addService(new GrpcService2())
        .addService(new GrpcService3())
        .addService(ProtoReflectionService.newInstance())
        .build();

The problem is that there seems to be a conflict between the first two services ( GrpcService1 and GrpcService2 ). If I add GrpcService1 first, and GrpcService2 second, then the second service is not exposed. If I add GrpcService2 first and GrpcService1 second, the first service is not exposed. The third service is always exposed.

What I mean with "the service is not exposed" is that when trying to run grpcurl on one of the second service's rpcs, I get an error like this:

$ grpcurl -plaintext \                   
  localhost:8980 \
  specs.grpc_service2.GrpcService2/someRpc
Error invoking method "specs.grpc_service2.GrpcService2/someRpc": target server does not expose service "specs.grpc_service2.GrpcService2"

Running a grpcurl list command does reveal all services, however.

$ grpcurl -plaintext localhost:8980 list
grpc.reflection.v1alpha.ServerReflection
specs.grpc_service3.GrpcService3
specs.grpc_service2.GrpcService2
specs.grpc_service1.GrpcService1

When using gRPC UI, I get a similar problem, just that the second service added is not included in the list of available services.

Below are some stubs for the proto definitions of the two conflicting services.

src/main/proto/grpc_service1/services.proto (used in GrpcService1 ):

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.service.internal_query_api";
option java_outer_classname = "InternalQueryGrpcProto";

package specs.grpc_service1;

service GrpcService1 {
...

src/main/proto/grpc_service2/services.proto (Used in GrpcService2 ):

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.service.matform.api";
option java_outer_classname = "MatformGrpcProto";

package specs.grpc_service2;

service GrpcService2 {
...

I found out the cause of the problem: you cannot add 2 gRPC services that are defined in Protobuf files with the same name.

In my case, the 2 conflicting services were both defined in 2 files, both named services.proto , despite being in 2 different directories and having different namespaces.

The source of this issue comes from the implementation of the ProtoReflectionService class ( ProtoReflectionService.java ):

if (!seenFiles.contains(fileDescriptor.getName())) {
  seenFiles.add(fileDescriptor.getName());
  fileDescriptorsToProcess.add(fileDescriptor);
}

The solution is therefore to rename one of the two .proto files to avoid conflict.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM