首先,完整的报错是java.lang.AbstractMethodError: io.grpc.netty.shaded.io.grpc.netty.NettyClientStream$Sink.request(I)V。

这是博主在做一次微服务迁移碰到的问题,原先的配置在Spring Boot下跑是完全正常的,然后把grpc的配置迁移到Spring Cloud下就开始报该错误了。

两个项目对于GRPC唯一不同的地方就是引入的Boot版本不一致,单体引入的是2.2.5.RELEASE,微服务引入的是2.3.5.RELEASE,引入的GRPC版本都是1.32.1。一开始我以为找到问题了,从版本依赖关系进行入手,查阅到grpc-spring-boot-starter(感谢作者大大)有这方面的介绍,

具体链接如下:https://github.com/yidongnan/grpc-spring-boot-starter/blob/master/docs/en/versions.md,提升了grpc的版本到1.32.1以上,然后还是一直报错,这就让我很苦恼了。

没办法,操作下Rollback,还是仔细debug看下到底是哪块代码出错了,最后发现的问题是Sink接口中的request方法竟然没有被实现而导致的报错,如下图所示:

 

这完全不该啊,我在Spring Boot版本那边引入的也是相同的grpc版本啊,于是切回到boot版本找到AbstractClientStream中内部类Sink中的request方法是否有被实现。然而惊呆了我,如下图,你是不是也很吃惊,压根就没有这个request方法啊。

 

如果仔细看的话,我们会发现一个问题,卧槽,同样的AbstractClientStream类怎么在不同的包下面,而且我在Cloud版本那边压根没用引过1.30.2的包啊,心里顿时一万只羊驼在奔跑。于是自然而然的就会想到,是引入的core包不对,于是在Cloud版本再引入

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-core</artifactId>
            <version>1.32.1</version>
        </dependency>

再使用Maven Helper插件(强烈推荐,开发必备)发现在grpc-netty-shaded包中存在core的冲突,于是修改如下:

        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>${grpc.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>grpc-core</artifactId>
                    <groupId>io.grpc</groupId>
                </exclusion>
            </exclusions>
        </dependency>

后面又一次debug发现还是报错,有了前面的坑,后面就有经验了,这次的错是grpc-api版本不对,于是又是一顿操作。最后修改的配置如下:

        <!-- grpc -->
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-netty-shaded</artifactId>
            <version>${grpc.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>grpc-core</artifactId>
                    <groupId>io.grpc</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-protobuf</artifactId>
            <version>${grpc.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>grpc-api</artifactId>
                    <groupId>io.grpc</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-stub</artifactId>
            <version>${grpc.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>grpc-api</artifactId>
                    <groupId>io.grpc</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-core</artifactId>
            <version>${grpc.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>grpc-api</artifactId>
                    <groupId>io.grpc</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-api</artifactId>
            <version>${grpc.version}</version>
        </dependency>
        <dependency> <!-- necessary for Java 9+ -->
            <groupId>org.apache.tomcat</groupId>
            <artifactId>annotations-api</artifactId>
            <version>${tomcat.annotations-api.version}</version>
            <scope>provided</scope>
        </dependency>

这个坑有点深,一层套一层啊。

最后总结一下这次采坑,可能是GRPC在版本升级过程中没有指定grpc-core和grpc-api的版本,于是在Spring Boot的不同版本下,GRPC会默认使用grpc-core和grpc-api的版本为1.30.2。当然直接把引入的grpc依赖全部改成1.30.2或许也行,这个我就不去测试了。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐