使用grpc-netty-shaded的Kafka Connector Shaded Jar运行异常
问题根源
这个ServiceConfigurationError本质是类加载器隔离冲突:NettyChannelProvider类和它要实现的ManagedChannelProvider接口被不同的类加载器加载了,JVM因此判定它不是接口的子类。结合你的场景,问题出在三个地方:
- Shade插件对gRPC的ServiceLoader配置文件合并不到位
- 依赖中可能悄悄混入了
grpc-netty(和grpc-netty-shaded互斥) - Kafka Connect的插件类加载器机制,导致你的shaded jar中的类和Connect环境的类上下文不兼容
解决步骤
1. 清理依赖,只保留grpc-netty-shaded
你的pom可能通过传递依赖引入了grpc-netty,必须彻底排除。修改gRPC相关依赖:
<!-- gRPC dependencies --> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-netty-shaded</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-stub</artifactId> <exclusions> <exclusion> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.grpc</groupId> <artifactId>grpc-protobuf</artifactId> <exclusions> <exclusion> <groupId>io.grpc</groupId> <artifactId>grpc-netty</artifactId> </exclusion> </exclusions> </dependency>
2. 升级Shade插件配置,处理包重定位
只合并Service文件不够,得把gRPC的包全部重定位到自定义包下,避免和Kafka Connect环境里的其他gRPC依赖冲突。修改maven-shade-plugin:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.6.0</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <!-- 重定位gRPC和protobuf包,彻底隔离 --> <relocations> <relocation> <pattern>io.grpc</pattern> <shadedPattern>com.pinax.shaded.io.grpc</shadedPattern> </relocation> <relocation> <pattern>com.google.protobuf</pattern> <shadedPattern>com.pinax.shaded.com.google.protobuf</shadedPattern> </relocation> </relocations> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> <!-- 合并Manifest,确保类路径正确 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/> </transformers> </configuration> </execution> </executions> </plugin>
3. 代码中直接指定ChannelProvider,绕开ServiceLoader
不要让gRPC自动通过ServiceLoader查找Provider,直接在代码里指定shaded版本的NettyChannelProvider,从根源避免类加载器问题:
// 注意是shaded包下的类 import io.grpc.netty.shaded.io.grpc.netty.NettyChannelProvider; import io.grpc.ManagedChannelBuilder; public class PaymentGatewayClient { public void start() { // 直接用shaded的Provider构建Channel ManagedChannelBuilder<?> channelBuilder = NettyChannelProvider.provider() .builderForAddress("your-server-host", your-server-port); // 后续配置channel逻辑 // ... } }
4. 部署时注意Kafka Connect的插件隔离
- 把你的shaded jar单独放在一个插件目录,不要和其他带gRPC依赖的插件混放
- 确保Kafka Connect的
plugin.path只指向你的插件目录,避免核心类路径里的gRPC依赖干扰
验证方法
- 重新构建:
mvn clean package - 解压shaded jar,检查
META-INF/services/io.grpc.ManagedChannelProvider里只有shaded版本的Provider类路径 - 检查jar内有没有
io.grpc.netty(非shaded)的类,确保只有io.grpc.netty.shaded的内容
内容的提问来源于stack exchange,提问作者Charles Morin
相关产品推荐
相关产品推荐

