• maven-assembly-plugin 打包后 grpc请求异常


    maven-assembly-plugin 打包后 grpc请求异常


    描述: 一个 grpc 客户端项目,在本地直接通过idea启动测试都没问题。而打成可执行jar包后,请求服务端时会抛出
    io.grpc.StatusRuntimeException:UNKNOWN 、 java.nio.channels.UnsupportedAddressTypeException 异常

    问题分析: 为什么本地idea跑没问题,而打包后有问题 ?

    从打包和启动方式来看

    maven-assembly-plugin 的打包机制是将依赖的所有a.jar、b.jar…的class打成一个jar(packaged.jar),然后 java -jar packaged.jar 启动。所以如果jar包里有相同 class或者配置文件,就会出现覆盖等问题。

    本地idea是通过 java -classpath a.jar:b.jar mainclass 指定依赖jar包路径启动的,启动时每个jar都会被加载,所以在程序启动前,不会出现同名class或者配置文件覆盖。加载过程中才会有后加载的同名class被跳过等问题。

    所以大概率就是两种情况

    1. 不同jar中有同名的class,因为加载顺序产生的问题。但可能性很小
    2. jar包里的某些配置文件,在打包时就已经被覆盖,启动时压根没有被加载。例如spi配置。

    带着这种想法网上搜一下,果然发现了相关问题。和分析的差不多,是不同jar包里的spi配置文件: META-INF/services/xxxx 名称相同,导致内容在打包后(程序启动前)就已经被覆盖。

    举个例子

    如下图的,grpc-core:1.47.0 和 grpc-netty-shaded:1.47.0 这两个 jar 包中就有相同的 spi 配置文件 io.grpc.NameResolverProvider

    20220821.png

    但是它们文件里的实际内容是不一样的,如下图

    20220821_1.png

    而我解压通过 maven-assembly 打的jar包,发现里面只有一个内容

    20220821_2.png

    所以问题清楚了,就是 maven-assembly 打包,导致同名配置文件内容被覆盖了

    解决:

    1. 直接把依赖的jar包全部放到一个目录下,不合并。可以使用 onejar-maven-plugin 配合 maven-jar-plugin
    
    <plugin>
        <groupId>org.apache.maven.pluginsgroupId>
        <artifactId>maven-jar-pluginartifactId>
        <configuration>
            <archive>
                <manifest>
                    <mainClass>com.xxx.MainmainClass>
                manifest>
            archive>
        configuration>
    plugin>
    <plugin>
    <groupId>com.joliragroupId>
    <artifactId>onejar-maven-pluginartifactId>
    <version>1.4.4version>
    <executions>
        <execution>
            <configuration>
                <attachToBuild>trueattachToBuild>
                <classifier>onejarclassifier>
            configuration>
            <goals>
                <goal>one-jargoal>
            goals>
        execution>
    executions>
    plugin>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    这样打出来的jar包里,就包含了依赖的jar包。但是比较麻烦,并且 onejar-maven-plugin 没维护了,不太推荐

    1. 使用 maven-shade-plugin 并且加上 ServicesResourceTransformer
    
    <plugin>
        <groupId>org.apache.maven.pluginsgroupId>
        <artifactId>maven-shade-pluginartifactId>
        <version>3.3.0version>
        <executions>
            <execution>
                <goals>
                    <goal>shadegoal>
                goals>
                <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.xxx.MainmainClass>
                        transformer>
                    transformers>
                configuration>
            execution>
        executions>
    plugin>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    比较推荐

  • 相关阅读:
    作为前端你还不懂MutationObserver?那Out了
    使用gitlab的基本过程,常用的git和gitlab命令
    『NLP学习笔记』图解GPT3(How GPT3 Works-Visualizations and Animations)
    手撸大文件上传:实现切片上传,断点上传和文件秒传的功能。
    Unity3D开发之传送带实现
    计算机网络 实验五 RIP与OSPF实验(网络层算法)
    CentOS 7 无界面版本设置静态IP步骤
    javaweb驾驶员考试报名审批系统
    java版Spring Cloud+Mybatis+Oauth2+分布式+微服务+实现工程管理系统
    我用GPT搭建了一个虚拟女友!
  • 原文地址:https://blog.csdn.net/qq_40225004/article/details/126449039