一、开头:你是不是也被Gradle卡过?
做Java或者安卓开发的朋友,十有八九遇到过这种糟心场景:下班前改了两行代码,想跑个单元测试或者打个包回家,结果Gradle构建卡在“下载依赖”的环节,进度条要么半天不动,要么直接报“连接超时”“连接被拒绝”,等半小时都下不来,好好的下班计划全被打乱。还有更气人的:有时候换个网络环境(比如从公司内网回家用WiFi),构建速度直接差好几倍,明明都是正常网络,为啥Gradle的表现差这么多?
其实Gradle构建的大部分网络问题,本质上都是“依赖下载”的问题——毕竟Gradle本身很小,构建时需要从网上拉各种第三方包(比如Spring的核心包、安卓的支持库),这些包叫“依赖”,整个构建过程70%以上的时间都花在下载依赖上。这篇文章就帮你把这些网络问题拆解清楚,从排查到优化,一步步把Gradle的构建速度提上去。
二、先搞懂Gradle的网络逻辑:为啥它会卡?
在排查问题之前,得先知道Gradle是怎么和网络打交道的,不然瞎调配置只会越调越乱。
2.1 Gradle的依赖下载流程
Gradle找依赖的逻辑很简单,就像你去超市买东西:
- 先看自己的“仓库货架”(本地缓存)有没有这个东西——本地缓存就是你之前下载过的依赖,存在你电脑的某个文件夹里;
- 如果本地没有,就去“指定的超市”(远程仓库)找——远程仓库就是网上存所有依赖的服务器,比如Maven中央仓库、阿里云的仓库;
- 要是第一个仓库找不到,就去第二个、第三个仓库找,直到找到为止;
- 下载完的依赖会存到本地缓存,下次再用就不用下载了。
举个例子:你要找Spring Boot的web依赖,Gradle先看你电脑的~/.gradle/caches/modules-2/files-2.1文件夹里有没有这个包(不同系统的路径不一样,Windows是C:\Users\你的用户名\.gradle\caches\modules-2\files-2.1),如果没有,就去你配置的远程仓库下载。
2.2 常见的网络问题类型
搞懂了流程,就能对应上常见的网络问题了:
- 本地缓存损坏:之前下载的依赖坏了,Gradle要重新下载;
- 远程仓库连接慢/连不上:仓库服务器离你太远、网络波动、仓库本身有问题;
- 代理配置错误:公司内网要求用代理,你没配或者配错了;
- 依赖冲突导致重复下载:同一个依赖有多个版本,Gradle反复拉取。
三、网络问题排查:一步步定位问题
遇到问题别慌,按这个顺序查,90%的问题都能找到原因。
3.1 第一步:先看本地缓存有没有问题
很多时候,Gradle卡不是网络的锅,是本地缓存坏了。比如你之前下载依赖时断网了,导致缓存里的包不完整,Gradle会一直尝试重新下载。
排查方法很简单:先清一次本地缓存,再重新构建,看问题是不是还存在。
# 清缓存命令(Windows、Mac、Linux都能用)
./gradlew clean build --refresh-dependencies
这里解释下命令:
./gradlew:是项目自带的Gradle包装器,不用你自己装Gradle,直接用项目里的就行;clean:清掉上次构建生成的临时文件;build:重新执行构建;--refresh-dependencies:强制Gradle刷新所有依赖,相当于清空本地缓存的依赖元数据,下次构建会重新检查依赖是否完整。
如果清完缓存后,构建正常了,那就是本地缓存的问题,不用管网络的事。
3.2 第二步:看Gradle的构建日志,找具体卡在哪
如果清缓存没用,就看构建日志,日志会明确告诉你Gradle在哪个步骤卡着。
打开项目的build.gradle(或者settings.gradle),先加一行日志配置,让Gradle把网络相关的细节打出来:
// 技术栈:Gradle(Groovy语法)
// 在项目根目录的build.gradle里加这个配置
tasks.withType(org.gradle.api.tasks.testing.Test) {
testLogging {
events "PASSED", "SKIPPED", "FAILED"
}
}
// 专门开网络日志,看依赖下载的细节
tasks.withType(org.gradle.api.tasks.CompileJava) {
options.compilerArgs << "-verbose"
}
// 或者更简单的,构建时加参数打详细日志
然后重新构建,加参数打详细日志:
./gradlew build --info
日志里会出现类似这样的内容:
10:23:45.123 [INFO] [org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.DefaultArtifactResolver] Downloading https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-web/2.7.0/spring-boot-starter-web-2.7.0.jar
10:23:45.456 [WARN] [org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.DefaultArtifactResolver] Download attempt 1 failed: Connection timed out
10:23:46.789 [WARN] [org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.DefaultArtifactResolver] Download attempt 2 failed: Connection timed out
看到这个你就知道了:Gradle正在从Maven中央仓库(repo1.maven.org)下载Spring Boot的web依赖,而且连接超时了——这就说明是远程仓库的问题,不是本地的事。
3.3 第三步:测试远程仓库的连通性
知道了是哪个仓库的问题,就直接测这个仓库能不能正常访问。
比如刚才日志里的Maven中央仓库地址,你可以用curl命令测一下:
# 技术栈:Shell(curl命令)
# 测Maven中央仓库的连通性,指定超时时间10秒
curl -m 10 https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-starter-web/2.7.0/spring-boot-starter-web-2.7.0.jar
如果命令报错“Connection timed out”,说明你连不上这个仓库;如果能正常输出一堆乱码(那是jar包的二进制内容),说明仓库是通的,问题出在Gradle的配置上。
再举个例子,测阿里云的仓库:
curl -m 10 https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starter-web/2.7.0/spring-boot-starter-web-2.7.0.jar
国内的网络连阿里云的仓库一般都很快,要是这个能通,那直接把Gradle的远程仓库换成阿里云的就行。
3.4 第四步:检查代理配置
如果你在公司内网,或者用了VPN,那代理配置错了也会导致Gradle连不上仓库。
先看Gradle的代理配置文件,路径是~/.gradle/gradle.properties(Windows是C:\Users\你的用户名\.gradle\gradle.properties),打开看看有没有类似下面的内容:
# 技术栈:Gradle配置文件(properties格式)
# HTTP代理配置
systemProp.http.proxyHost=proxy.company.com
systemProp.http.proxyPort=8080
# HTTPS代理配置(Gradle大部分仓库用HTTPS,这个更重要)
systemProp.https.proxyHost=proxy.company.com
systemProp.https.proxyPort=8080
# 如果代理需要账号密码,还要加这两行
systemProp.https.proxyUser=your_username
systemProp.https.proxyPassword=your_password
如果你的公司内网确实需要代理,就检查这些配置对不对:比如proxyHost是不是公司给的正确代理地址,端口是不是8080(有的公司是其他端口),账号密码有没有错。
如果不需要代理,就把这些配置删掉,然后重新构建。
四、网络问题优化:让Gradle跑的更快
排查完问题,接下来就是优化了,这里分几个场景给你具体的优化方法。
4.1 场景一:国内网络,默认仓库慢(最常见)
很多人用Gradle的时候,默认用的是Maven中央仓库或者JCenter仓库,这些仓库的服务器在国外,国内访问特别慢,甚至连不上。
优化方法:把Gradle的远程仓库换成国内的镜像,比如阿里云的仓库、华为云的仓库,国内访问速度能快好几倍。
具体配置步骤:
- 打开项目根目录的
settings.gradle文件(注意不是build.gradle,这个文件是配置仓库的核心); - 找到
repositories相关的配置,替换成国内的镜像。
示例配置(Gradle 7.0及以上版本):
// 技术栈:Gradle(Groovy语法)
// settings.gradle文件内容
pluginManagement {
repositories {
// 先加阿里云的镜像,再保留原来的仓库(防止阿里云没有的依赖)
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/repository/spring" }
gradlePluginPortal()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
// 先加阿里云的镜像,再保留原来的仓库
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/repository/spring" }
mavenCentral()
}
}
rootProject.name = "your-project-name"
include("app")
解释一下这个配置:
pluginManagement:是配置Gradle插件的仓库,比如你用的Spring Boot插件、安卓的构建插件,都是从这里下载的;dependencyResolutionManagement:是配置项目依赖的仓库,比如你自己加的Spring Web、MyBatis这些依赖,都是从这里下载的;- 把阿里云的仓库放在前面,Gradle会优先从阿里云找依赖,找不到再去国外的仓库找,兼顾速度和兼容性。
如果是Gradle 6.0及以下的旧版本,配置略有不同,直接在build.gradle的repositories里加阿里云的镜像就行:
// 技术栈:Gradle(Groovy语法)
// 旧版本Gradle的build.gradle配置
repositories {
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/repository/spring" }
mavenCentral()
}
4.2 场景二:公司内网,只能用内网仓库
很多公司为了安全,会搭建自己的内网仓库(比如Nexus、Artifactory),所有开发人员只能从内网仓库下载依赖,不能连外网。
优化方法:把Gradle的仓库配置换成公司的内网仓库,同时配置内网代理(如果需要的话)。
具体配置步骤:
- 先问公司的运维要内网仓库的地址,比如
http://nexus.company.com/repository/maven-public/; - 把
settings.gradle里的仓库换成这个地址:
// 技术栈:Gradle(Groovy语法)
// settings.gradle的仓库配置
pluginManagement {
repositories {
maven { url "http://nexus.company.com/repository/maven-public/" }
gradlePluginPortal()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
maven { url "http://nexus.company.com/repository/maven-public/" }
mavenCentral()
}
}
- 再配置代理(如果内网仓库需要代理),打开
~/.gradle/gradle.properties,加代理配置:
# 技术栈:Gradle配置文件(properties格式)
systemProp.http.proxyHost=proxy.company.com
systemProp.http.proxyPort=8080
systemProp.https.proxyHost=proxy.company.com
systemProp.https.proxyPort=8080
4.3 场景三:频繁切换网络(比如从公司到家里)
如果你经常换网络环境(比如在公司用内网,回家用家里的WiFi),每次换网络都要改Gradle的仓库或者代理配置,太麻烦了。
优化方法:给Gradle配置多个仓库和代理,让它自动适配不同的网络环境。
具体配置:
- 先在
settings.gradle里加多个仓库,包括国内的阿里云、公司的内网仓库、国外的中央仓库,Gradle会自动选最快的那个:
// 技术栈:Gradle(Groovy语法)
// settings.gradle的仓库配置
pluginManagement {
repositories {
// 公司内网仓库(优先)
maven { url "http://nexus.company.com/repository/maven-public/" }
// 国内阿里云仓库(其次)
maven { url "https://maven.aliyun.com/repository/public" }
// 国外中央仓库(兜底)
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
maven { url "http://nexus.company.com/repository/maven-public/" }
maven { url "https://maven.aliyun.com/repository/public" }
mavenCentral()
}
}
- 再给代理加“条件判断”,只有在公司内网的时候才用代理,在家不用:
打开
~/.gradle/gradle.properties,加下面的配置:
# 技术栈:Gradle配置文件(properties格式)
# 定义一个变量,判断是不是在公司内网(这里用公司的DNS后缀判断,比如公司的域名是company.com)
# 你可以把下面的“company.com”换成自己公司的域名
isCompanyNetwork=${systemProp.os.name}.contains("Windows")?${systemProp.userdomain}.equals("COMPANY"):${systemProp.USER}.endsWith("company.com")
# 如果是公司网络,就开代理,否则关
systemProp.http.proxyHost=${isCompanyNetwork?'proxy.company.com':''}
systemProp.http.proxyPort=${isCompanyNetwork?'8080':''}
systemProp.https.proxyHost=${isCompanyNetwork?'proxy.company.com':''}
systemProp.https.proxyPort=${isCompanyNetwork?'8080':''}
解释一下这个配置:
- 用
isCompanyNetwork这个变量判断当前是不是在公司内网,Windows系统看用户域是不是COMPANY,Mac/Linux看用户名是不是以company.com结尾; - 如果是公司网络,就把代理地址和端口设成公司的,否则设成空(相当于不用代理)。
4.4 场景四:多项目共用缓存(团队开发)
如果团队里有多个开发者,每个人都要下载一遍依赖,不仅浪费时间,还浪费公司的带宽。
优化方法:搭建团队共享的本地缓存,让所有开发者共用同一个缓存,只需要一个人下载一遍依赖,其他人都能直接用。
具体实现:
- 先找一台团队里的公共电脑(或者服务器),安装Gradle,然后在这台电脑上执行一次项目的构建,把所有依赖都下载到它的本地缓存里;
- 把这台电脑的Gradle缓存文件夹(
~/.gradle/caches)共享给团队的其他成员; - 其他成员修改自己的Gradle配置,把本地缓存的路径指向共享的缓存文件夹:
打开自己的
~/.gradle/gradle.properties,加下面的配置:
# 技术栈:Gradle配置文件(properties格式)
# 把本地缓存路径指向共享的文件夹(比如共享的路径是\\server\gradle-cache)
org.gradle.caching.local.directory=\\server\gradle-cache
这样其他成员构建的时候,就会从共享的缓存里找依赖,不用自己下载了。
五、技术优缺点与注意事项
5.1 核心技术的优缺点
这里说的核心技术主要是“Gradle镜像仓库”和“共享缓存”:
- 镜像仓库: 优点:国内访问速度快,稳定,能解决大部分网络问题; 缺点:有的小众依赖可能不在国内镜像里,需要保留国外仓库兜底。
- 共享缓存: 优点:节省团队的下载时间和带宽,适合多人协作的项目; 缺点:共享缓存的电脑如果关机了,其他人就用不了,需要保证这台电脑一直在线。
5.2 注意事项
- 仓库的顺序很重要:一定要把速度快的仓库放在前面,Gradle会按顺序找依赖,先找到就用;
- 不要随便清本地缓存:清缓存会导致所有依赖重新下载,只有在确定缓存损坏的时候才清;
- 敏感配置要保密:如果代理需要账号密码,不要把
gradle.properties提交到Git仓库,不然所有人都能看到你的密码; - 版本要统一:团队里的Gradle版本要尽量统一,不然可能会出现依赖不兼容的问题。
六、文章总结
Gradle构建的网络问题,本质上都是依赖下载的问题,排查的时候先看本地缓存,再看日志找具体卡的步骤,然后测试仓库的连通性,最后检查代理配置。优化的时候,根据自己的场景选对应的方法:国内网络换国内镜像,公司内网用内网仓库,频繁换网络用多仓库和条件代理,团队开发用共享缓存。
只要把这些方法用对,Gradle的构建速度能提升好几倍,再也不会因为网络问题耽误下班了。
评论
围绕“Gradle构建过程中的网络问题排查与优化”参与讨论