GRPC服务无法在服务端反射显示,grpcurl无法列出问题求助
我在基于Spring Boot实现MySQL的CRUD操作时,整合了GRPC与REST接口,但遇到以下问题:
- 暴露的GRPC服务无法在服务端反射中显示,使用
grpcurl的list命令也无法列出服务/方法 - 通过Postman发起GRPC调用时,看不到对应的方法
已经在application.yml中开启enableReflection=true,尝试多种方案仍未解决,相关代码及配置如下:
GRPC服务实现代码
package com.nucleiassignment3.grpc; import com.google.protobuf.Empty; import com.mysql_crud.grpc.*; import com.nucleiassignment3.HttpServer.bo.EmployeeBo; import com.nucleiassignment3.HttpServer.mapper.ProtoToRequestMapper; import com.nucleiassignment3.HttpServer.service.EmployeeService; import io.grpc.stub.StreamObserver; import org.lognet.springboot.grpc.GRpcService; import org.springframework.beans.factory.annotation.Autowired; @GRpcService public class EmployeeGrpcImpl extends EmployeesServiceGrpc.EmployeesServiceImplBase { @Autowired EmployeeService employeeService; @Override public void createEmployee(CreateEmployeeRequest request, StreamObserver<CreateEmployeeResponse> responseObserver) { EmployeeBo employeeBo=employeeService.createEmployee(ProtoToRequestMapper.employeeRequest(request)); java.sql.Date dob=employeeBo.getDob(); CreateEmployeeResponse createEmployeeResponse=CreateEmployeeResponse.newBuilder() .setEmployee(Employee.newBuilder() .setId(employeeBo.getEmpId()) .setName(employeeBo.getName()) .setDob(Date.newBuilder() .setDay(dob.getDay()) .setMonth(dob.getMonth()) .setYear(dob.getYear()) .build()) .setGender(employeeBo.getGender()) .build()) .build(); responseObserver.onNext(createEmployeeResponse); responseObserver.onCompleted(); } @Override public void getEmployee(GetEmployeeRequest request,StreamObserver<GetEmployeeResponse> responseObserver){ EmployeeBo employeeBo=employeeService.getEmployee(request.getId()); GetEmployeeResponse employeeResponse=GetEmployeeResponse.newBuilder() .setEmployee(Employee.newBuilder() .setId(employeeBo.getEmpId()) .setName(employeeBo.getName()) .setGender(employeeBo.getGender()) .setDob(Date.newBuilder() .setDay(employeeBo.getDob().getDay()) .setMonth(employeeBo.getDob().getMonth()) .setYear(employeeBo.getDob().getYear()) .build()) .build()) .build(); responseObserver.onNext(employeeResponse); responseObserver.onCompleted(); } @Override public void listEmployees(ListEmployeesRequest request, StreamObserver<ListEmployeesResponse> responseObserver) { } @Override public void updateEmployee(UpdateEmployeeRequest request,StreamObserver<UpdateEmployeeResponse> responseObserver){ } @Override public void deleteEmployee(DeleteEmployeeRequest request, StreamObserver<Empty> responseObserver) { } }
application.yml配置
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: 'jdbc:mysql://localhost:3306/****' username: root password: ****** jpa: show-sql: true hibernate: ddl-auto: update properties: hibernate: dialect: org.hibernate.dialect.MySQL5Dialect server: port: '9191' grpc: port: '8080' enableReflection: true
build.gradle配置
plugins { id 'java' id 'org.springframework.boot' version '3.0.2' id 'io.spring.dependency-management' version '1.1.0' id "com.google.protobuf" version "0.9.2" } group = 'com.nucleiassignment3' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation "org.springframework.boot:spring-boot-starter-actuator" implementation "io.micrometer:micrometer-registry-prometheus" implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-jdbc' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation "org.mapstruct:mapstruct:1.4.2.Final" annotationProcessor "org.mapstruct:mapstruct-processor:1.4.2.Final" testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' implementation group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2' implementation group: 'com.google.protobuf', name: 'protobuf-java', version: '3.21.12' implementation group: 'io.grpc', name: 'grpc-all', version: '1.53.0' implementation group: 'com.google.protobuf', name: 'protoc', version: '3.21.12', ext: 'pom' implementation 'javax.annotation:javax.annotation-api:1.3.2' implementation 'io.github.lognet:grpc-spring-boot-starter:5.0.0' } sourceSets { main { proto { srcDirs 'src/main/resources/proto' } java { srcDirs 'build/generated/source/proto/main/grpc' srcDirs 'build/generated/source/proto/main/java' } } } protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.0.0' } plugins { grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0-pre2' } } generateProtoTasks { all()*.plugins { grpc {} } } }
排查方案
修复YAML配置缩进问题
当前application.yml中jpa、server、grpc等节点错误嵌套在spring节点下,会导致GRPC配置未被正确加载。修正后的配置:spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: 'jdbc:mysql://localhost:3306/****' username: root password: ****** jpa: show-sql: true hibernate: ddl-auto: update properties: hibernate: dialect: org.hibernate.dialect.MySQL5Dialect server: port: '9191' grpc: port: '8080' enableReflection: true检查版本兼容性
Spring Boot 3.0.2基于Spring 6,而io.github.lognet:grpc-spring-boot-starter:5.0.0可能存在Spring 6兼容性问题。建议升级到5.1.0+版本,同时替换javax依赖为jakarta(比如javax.persistence-api换为jakarta.persistence:jakarta.persistence-api:3.1.0)。确认GRPC反射依赖
虽然引入了grpc-all,但手动添加grpc-services依赖确保反射服务存在:implementation 'io.grpc:grpc-services:1.53.0'验证Proto生成代码
确保.proto文件中定义的服务名称与实现类继承的EmployeesServiceGrpc.EmployeesServiceImplBase完全对应,且生成的代码包含EmployeesServiceGrpc.getServiceDescriptor()方法——这是反射识别服务的核心。检查grpcurl命令格式
使用正确的命令调用反射服务:grpcurl -plaintext localhost:8080 list注意端口为GRPC的8080,而非Spring Boot的9191。
Postman配置校验
确保Postman已正确导入对应的.proto文件,且GRPC请求地址设置为localhost:8080(开启plaintext模式)。
内容的提问来源于stack exchange,提问作者Sayan Manna

