You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GRPC服务无法在服务端反射显示,grpcurl无法列出问题求助

GRPC服务反射无法显示问题排查求助

我在基于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 {}
    }
}
}

排查方案

  1. 修复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
    
  2. 检查版本兼容性
    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)。

  3. 确认GRPC反射依赖
    虽然引入了grpc-all,但手动添加grpc-services依赖确保反射服务存在:

    implementation 'io.grpc:grpc-services:1.53.0'
    
  4. 验证Proto生成代码
    确保.proto文件中定义的服务名称与实现类继承的EmployeesServiceGrpc.EmployeesServiceImplBase完全对应,且生成的代码包含EmployeesServiceGrpc.getServiceDescriptor()方法——这是反射识别服务的核心。

  5. 检查grpcurl命令格式
    使用正确的命令调用反射服务:

    grpcurl -plaintext localhost:8080 list
    

    注意端口为GRPC的8080,而非Spring Boot的9191。

  6. Postman配置校验
    确保Postman已正确导入对应的.proto文件,且GRPC请求地址设置为localhost:8080(开启plaintext模式)。

内容的提问来源于stack exchange,提问作者Sayan Manna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 22:24:21