• 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

    比较推荐

  • 相关阅读:
    【听课笔记】航空航天概论(国家精品课程 北京航空航天大学)
    java基于ssm的企业职工工资管理系统
    宏观经济学通识课-读书笔记
    RPA教程01:EXCEL自动化从入门到实操
    计算机网络 | 基于UDP的C/S模型代码实现
    【Linux命令】文件操作、通配符、文件属性、创建链接文件、关机重启
    MMICCI2015- U-Net: Convolutional Networks for Biomedical Image Segmentation
    C++实现类似QT中的计时器QTime类(CQTime)
    RHCA---DO477---变量和过滤
    在线直播性能分析:用3个小时分析一个系统的性能瓶颈(从现象到代码)
  • 原文地址:https://blog.csdn.net/qq_40225004/article/details/126449039