Я создаю сервер gRPC, которому необходимо предоставить несколько служб, как показано ниже.
Server server = ServerBuilder
.forPort(8980)
.addService(new GrpcService1())
.addService(new GrpcService2())
.addService(new GrpcService3())
.addService(ProtoReflectionService.newInstance())
.build();
Проблема в том, что есть конфликт между первыми двумя сервисами (GrpcService1 и GrpcService2). Если я добавлю GrpcService1 первым, а GrpcService2 вторым, то второй сервис не будет отображаться. Если я добавлю GrpcService2 первым и GrpcService1 вторым, первая служба не будет отображаться. Третья служба всегда открыта.
Что я имею в виду под «сервис не открыт», так это то, что при попытке запустить grpcurl на одном из rpcs второго сервиса я получаю такую ошибку:
$ 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"
Однако запуск команды grpcurl list показывает все службы.
$ grpcurl -plaintext localhost:8980 list
grpc.reflection.v1alpha.ServerReflection
specs.grpc_service3.GrpcService3
specs.grpc_service2.GrpcService2
specs.grpc_service1.GrpcService1
При использовании пользовательского интерфейса gRPC у меня возникает аналогичная проблема, только вторая добавленная служба не включена в список доступных служб.
Ниже приведены некоторые заглушки для прототипов определений двух конфликтующих сервисов.
Src/main/proto/grpc_service1/services.proto (используется в 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 (используется в 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 {
...
Я выяснил причину проблемы: вы не можете добавить 2 сервиса gRPC, которые определены в файлах Protobuf с одинаковым именем.
В моем случае две конфликтующие службы были определены в двух файлах с именами services.proto, несмотря на то, что они находились в двух разных каталогах и имели разные пространства имен.
Источником этой проблемы является реализация класса ProtoReflectionService (ProtoReflectionService.java):
if (!seenFiles.contains(fileDescriptor.getName())) {
seenFiles.add(fileDescriptor.getName());
fileDescriptorsToProcess.add(fileDescriptor);
}
Поэтому решение состоит в том, чтобы переименовать один из двух файлов .proto, чтобы избежать конфликта.
@Томас, спасибо! Я также думаю, что это ошибка, потому что я не понимаю причин, по которым не разрешается использовать два файла .proto с одинаковым именем. По крайней мере, следует учитывать пакет и имя файла.
Хорошая отладка там! Я собирался предложить вам зарегистрировать это как ошибку, но, похоже, у вас уже есть :)