乐趣区

关于gradle:效率提升maven-转-gradle-实战-京东云技术团队

一、灵魂三问

1、gradle 是什么?

一个打包工具,是一个开源构建自动化工具,足够灵便,能够构建简直任何类型的软件,高性能、可扩大、能洞察等。其中洞察,能够用于剖析构建过程中数据,提供剖析参考,不便排查问题和一直优化构建性能,以下一次编译剖析报告。

2、有什么劣势

参考官网文章,针对蕴含 10 子模块的工程,绝对 maven 构建速度,大略有 2-3 倍的性能晋升,增量编译大略 7 倍的性能晋升,参考官网

实测比照:

gradle 耗时 maven 耗时
全新构建(clean 及下载依赖包) 1m 35s 1m58s
全新构建(clean) 43s 60s
增量构建 14s 43s

gradle 执行命令:time gradle clean build package -x test

mvn 执行的命令:time mvn clean package -Dmaven.test.skip=true -f $(pwd) -T 1C -Dmaven.artifact.threads=16

综述,通过多轮测试,在增量编译场景劣势比较突出均匀有 2 倍的性能晋升,工程模块越多效率晋升越大。

3、迁徙是否容易

摸着心口说,并不容易,尽管官网提供了一键迁徙的工具,然而还是有肯定学习老本,但革新实现的确节俭了大把的工夫,尤其是改了一两行代码再次编译时。

二、动动手试试

1、装置 gradle

举荐应用 sdkman , 次要用于工具多版本治理的工具,如 java、gradle、maven 等能够依据理论状况装置应用其中某个一个版本,如 jdk8,jdk11 等,版本间切换十分简便。sdk 介绍:

sdk install  gradle 8.1.1

2、执行迁徙命令

在以后 maven 工程下,执行如下的命令。

gradle init 
Found a Maven build. Generate a Gradle build from this? (default: yes) [yes, no] yes
Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1
Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] no

不出意外下,会在默认子模块下增加 build.gradle 文件,如下图:

文件解释:

1)buildSrc/main/groovy/com.jd.pegasus.java-conventions.gradle:外面配置的是内网私服库地址。

repositories {mavenLocal()
    maven {url = uri('http://artifactory.jd.com/libs-releases')

        allowInsecureProtocol = true
    }

    maven {url = uri('http://artifactory.jd.com/libs-snapshots')

         allowInsecureProtocol = true
    }
    maven {url "https://plugins.gradle.org/m2/"}

}

2)gradle.properties:配置环境变量,必须设置 jvm 的参数,否则很容易 oom。更多配置

# gradle jvm 设置
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# 开启并行编译
org.gradle.parallel=true



3)build.gradle:蕴含了编译过程中应用的插件,id ‘com.jd.pegasus.java-conventions’ 代表自定义的插件。dependencies 为工程所应用的依赖。

plugins {id 'com.jd.pegasus.java-conventions'}

dependencies {api project(':pegasus-service')
    api project(':pegasus-common')
    implementation 'org.springframework.boot:spring-boot:2.1.9.RELEASE'
    api project(':component-metric')
    testImplementation 'org.springframework.boot:spring-boot-starter-test:2.1.9.RELEASE'
    annotationProcessor 'org.projectlombok:lombok:1.18.10'
}

description = 'pegasus-worker'

这外面有一个 dependencies 依赖项中 api 与 implementation 区别,参见如下解释:

假如你正在保护一个名为 MyLibrary 的库,它依赖于另一个库 InternalLibrary。你心愿 MyLibrary 的用户可能应用 InternalLibrary 中的某些类和办法,但不心愿他们应用其余类和办法。在这种状况下,你能够在 MyLibrary 的 build.gradle 文件中应用 api 配置来申明对 InternalLibrary 的依赖:

dependencies {

api project(‘:InternalLibrary’)

}

这样,当其余模块依赖于 MyLibrary 时,它们也可能拜访 InternalLibrary 中的类和办法。

然而,如果你不心愿 MyLibrary 的用户可能拜访 InternalLibrary 中的任何内容,你能够在 MyLibrary 的 build.gradle 文件中应用 implementation 配置来申明对 InternalLibrary 的依赖:

dependencies {

implementation project(‘:InternalLibrary’)

}

这样,当其余模块依赖于 MyLibrary 时,它们将无法访问 InternalLibrary 中的任何内容。

简略点就是如果你想把你依赖组件,让应用你组件人也晓得的明明白白的也能应用,那你就用 api 把组件传递上来,反之就用 implementation,就自个偷摸应用了,对第三方暗藏了一些外部细节。

3、gitignore 排除不要的目录和文件

# Gradle generated files
build/
.gradle/
/out/
/.gradle/

4、容许以不平安的形式拜访私服库

# 在这个文件外面,buildSrc/main/groovy/com.jd.pegasus.java-conventions.gradle 

repositories {mavenLocal()
    maven {url = uri('http://artifactory.jd.com/libs-releases')

        allowInsecureProtocol = true
    }
}



5、解决 lombok 引发的编译问题

通过 lombok 注解会在编译过程中把注解的类进行扩大,增加 get、set、toString 办法等。

# 在编译出错的模块外面 build.gradle 文件中增加注解处理器,annotationProcessor  如下:dependencies {api project(':pegasus-service')
    annotationProcessor 'org.projectlombok:lombok:1.18.10'
}

6、解决版本依赖抵触

版本抵触指同依赖组件呈现不同的版本状况,如 pegasus-common 模块依赖的 fastjson 有 1.2.83-jdsec.rc1, 1.2.29 and 1.2.12 三个版本,gradle 会主动解决仲裁,规定有以下几点:

1)抵触时会默认采纳最新的版本。

2)通过 strictly 标记次要用于降级到指定的版本,如传递依赖引入的版本高,以后版本不兼容,那能够通过这个关键字设置指定的版本。

implementation('com.alibaba:fastjson'){   
  version{strictly("1.2.12")    
  } 
}
或者简写为 
implementation 'com.alibaba:fastjson:1.2.29!!!'

3)force 的优先级会比拟高,会笼罩 strictly 策略

configurations.all {
    resolutionStrategy {
        // 在这里定义您的依赖解析规定
        //force 'com.alibaba:fastjson:1.2.12'
    }
}

排查某个模块的依赖抵触

gradle :pegasus-common:dependencyInsight --configuration compileClasspath --dependency com.alibaba:fastjson

7、如何构建 zip 包

以 springboot 为例,参考如下代码即可,在子工程 build.gradle 文件里。

。plugins {
    id 'com.jd.pegasus.java-conventions'
    // 引入 springboot 插件
    id 'org.springframework.boot' version '2.5.6'
}

// 指定 jar 启动的入口函数
bootJar {
    manifest {attributes 'Main-Class': 'com.jd.pegasus.Application'}
}
// 构建 zip 压缩包,蕴含启动脚本 bin 目录和 配置文件 conf 目录
task packageZip(type: Zip) {archiveFileName = "${project.name}-${project.version}.zip"
    destinationDirectory = file("${project.buildDir}")

    from("${project.projectDir}/src/main/bin") {into "bin"}
    from("${project.buildDir}/resources/main/conf") {into "conf"}

    from("${project.buildDir}/libs/${project.name}-${project.version}.jar") {into "lib"}
    // 示意此工作的运行依赖其它 子工作。dependsOn bootJar
    dependsOn build
}

8、执行构建命令

# -x test 排除单测
gradle clean  build package -x test  

三、附录参考

  1. 一文搞懂 Gradle 的依赖治理和版本决定
  2. gradle 与 maven 性能比照
  3. 爬坑指南 — 了解 Plugin、Task、构建流程
  4. 如何定位和解决依赖抵触
  5. Gradle 依赖之‘五种依赖配置’
  6. Migrating Builds From Apache Maven

后记:

据说 maven 不甘寂寞,由 gradle 和 Takari 的灵感,做了一个守护的 mvnd,在增量编译场景效率杠杠的,有工夫测试比照下。mvnd 参考

作者:京东科技 宁利广
起源:京东云开发者社区 转载请注明起源

退出移动版