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

Spring Boot gRPC Server初始化错误:无法获取NettyServerProvider无参构造方法

Java 17 Spring Boot自定义gRPC Server配置遇到ServiceConfigurationError问题

问题描述

我在Java 17的Spring Boot应用中手动配置gRPC Server时,实例化服务器触发了如下错误。

自定义配置代码

package org.xenwgram.config;

import io.grpc.Grpc;
import io.grpc.InsecureServerCredentials;
import io.grpc.Server;
import io.grpc.ServerCredentials;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.xenwgram.service.Impl.MessageServiceImpl;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Configuration
public class GrpcServerConfig {
    @Bean
    public Server grpcServer() {
        try {
            Server server = Grpc.newServerBuilderForPort(6565, InsecureServerCredentials.create())
                    .build();
            server.start();

            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                try {
                    server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }));

            return server;
        } catch (IOException e) {
            throw new RuntimeException("Failed to start gRPC server", e);
        }
    }
} 

build.gradle.kts依赖配置

plugins {
    id("java")
    id("com.google.protobuf") version "0.9.4"
    id("io.spring.dependency-management") version "1.1.6"
    id("org.springframework.boot") version "2.7.16"
}

group = "org.xenwgram"
version = "v0.0.1"

repositories {
    mavenLocal()
    mavenCentral()
    maven("https://gitlab.com/api/v4/projects/65346162/packages/maven")
}

dependencies {
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")

    implementation("org.xenwgram:xengram-proto:test-1.1")

    // Spring Boot starter web
    implementation("org.springframework.boot:spring-boot-starter-web:3.4.0")

    // Lombok for compile-time code generation
    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")
    implementation("org.projectlombok:lombok-mapstruct-binding:0.1.0")

    // gRPC Spring Boot starter
    implementation("net.devh:grpc-server-spring-boot-starter:3.1.0.RELEASE")

    // gRPC dependencies
    implementation("io.grpc:grpc-netty-shaded:1.69.0")
    implementation("io.grpc:grpc-protobuf:1.69.0")
    implementation("io.grpc:grpc-stub:1.69.0")

    // Google Protocol Buffers
    implementation("com.google.protobuf:protobuf-java:4.29.1")
}

tasks.test {
    useJUnitPlatform()
}

错误信息

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'grpcServer' defined in class path resource [org/xenwgram/config/GrpcServerConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.grpc.Server]: Factory method 'grpcServer' threw exception; nested exception is java.util.ServiceConfigurationError: io.grpc.ServerProvider: io.grpc.netty.NettyServerProvider Unable to get public no-arg constructor 

已尝试操作

  • 使用grpc-server-spring-boot-starter自动配置时运行正常;
  • 使用上述自定义配置时触发错误。

疑问

  1. 为何会出现NettyServerProvider的ServiceConfigurationError?
  2. 我的gRPC Server配置是否存在问题?
  3. 是否应该切换为Spring Boot starter的自动配置?

解答

1. 为何出现NettyServerProvider的ServiceConfigurationError?

核心原因是依赖冲突与类加载问题:

  • 你同时引入了grpc-netty-shaded和grpc-server-spring-boot-starter,starter内部已经包含非shaded版的Netty gRPC依赖,shaded包会重命名Netty相关类,导致gRPC的ServiceLoader无法找到正确的NettyServerProvider类(原始类名已被修改),进而抛出"无法获取无参构造"的错误。
  • Spring Boot版本不一致:你用的Spring Boot核心版本是2.7.16,但spring-boot-starter-web用了3.4.0,跨大版本的依赖会导致整个依赖树混乱,间接引发类加载异常。

2. 自定义gRPC Server配置的问题

你的配置存在多处问题:

  • 版本不兼容:spring-boot-starter-web版本3.4.0与Spring Boot核心2.7.16严重不兼容,破坏了Spring的依赖管理逻辑。
  • 服务未注册:手动构建Server时没有添加MessageServiceImpl服务实现,即便启动成功也无法处理任何gRPC请求。
  • 生命周期管理错误:在Bean初始化阶段直接调用server.start(),此时Spring上下文尚未完全初始化,可能导致后续依赖该Server的Bean出现异常;手动添加shutdown hook也不符合Spring的生命周期管理规范。
  • 重复配置冲突:grpc-server-spring-boot-starter已经会自动创建gRPC Server Bean,手动创建的Bean会与自动配置的Bean产生冲突。

3. 是否应该切换为Spring Boot starter的自动配置?

优先推荐使用grpc-server-spring-boot-starter的自动配置,理由如下:

  • 它已经封装了gRPC Server的生命周期管理(自动启动、优雅关闭),无需手动编写shutdown hook和启动逻辑。
  • 自动处理依赖冲突、类加载问题,避免手动配置时的版本兼容坑。
  • 提供Spring Boot风格的配置项(如通过application.yml修改gRPC端口、启用TLS等),与Spring生态无缝集成。
  • 如需自定义,可通过添加ServerBuilderCustomizer Bean来扩展Server配置,无需完全手动实现。

如果坚持手动配置,需要做以下调整:

  1. 移除grpc-server-spring-boot-starter依赖,避免冲突。
  2. 统一Spring Boot版本:将spring-boot-starter-web改为2.7.16,与核心版本一致。
  3. 在ServerBuilder中注册服务:.addService(new MessageServiceImpl())。
  4. 调整启动时机:使用@PostConstruct注解在Bean初始化完成后启动Server,而非在Bean创建阶段直接启动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:42:46