在Gradle深化解析 – Task原理(履行篇)中分析过gradle的缓存机制,知道gradle有本地和长途缓存的区分,它会记载下task的输入输出,能够从缓存中康复输出来防止从头履行,以加速构建速度,那么咱们怎么来运用remote build cache部分呢?

运用remote build cache有2种办法

  1. dockerjar包的办法运转
  2. 自己写一个build cache service

2种办法有什么区别呢?
个人感觉第一种比较合适小团队,小团队人数不多,一同开发一个项目,docker运转服务在一个服务机器上就行,关于大型团队来说,每个项目都装备一次docker比较麻烦,也不容易将不同团队数据阻隔
自己写一个插件来完成build cache service能够解决这个问题,build cache service和自己的OSS服务器通讯,自己的OSS服务器能够阻隔不同团队(不同的团队恳求不同的Bucket),并且不同每次从头装备docker服务,只需要apply一下plugin,然后改一下装备即可,十分方便

本篇针对第二种办法进行解说,第一种办法能够参阅以下一些文章的相关部分
Build Cache Node User Manual | Gradle Enterprise Docs
运用本地和长途的Gradle构建缓存加速构建速度
Android-Studio编译速度优化
Using Gradle Build Cache Server

google androidx团队开源了一个GitHub – androidx/gcp-gradle-build-cache,便是利用Google Cloud Storage来完成这个需求的

可是国内最大的OSS服务商还是阿里云,这个插件不支持,于是我仿照它的完成写了一个基于阿里云OSS的插件GitHub – neas-neas/aliyun-gradle-build-cache,用法相似

下面咱们就从这个插件的用法打开,详细解说怎么创立一个阿里云OSS Bucket,怎么装备gradle文件,后面再简略测试一下作用讲起
再分析其完成具体完成进程,你也能够基于自己公司的OSS服务完成一个自己的build cache server

阿里云OSS有必定的免费额度,超越额度会收费,你能够在简略的项目里边测试

运用办法

1. 创立阿里云OSS Bucket

首先去阿里云OSS官网创立OSS Bucket oss.console.aliyun

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

点击立即创立开端创立Bucket,顺便记载一下endpointbucket name,没有记下来也没关系,后面能够在概览里边找到

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

然后在bucket页面找到权限控制 -> RAM拜访控制,前往RAM控制台

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

假如没有用户要先创立用户,至少勾选OpenAPI调用拜访

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

创立用户成功后会跳转到这个页面,这里需要记载下AccessKey IDAccessKey Secret,后面封闭页面就获取不到了

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

用户创立完后,给用户添加权限

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

权限选中OSS相关的,保险起见FullAccessReadOnlyAccess都选上了,因为我之前都装备过了所以显示是灰色的

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

至此阿里云OSS的Bucket就创立完成了,现在就能够去项目中进行相关的装备

2. 装备gradle

settings.gradle中添加如下装备,着重一下是settings,kts脚本相似这里就不列出来了

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.github.neas-neas:alibuildcache:1.0.0'
    }
}
apply plugin: 'io.github.neas-neas.alibuildcache'
import io.github.neas.AliyunBuildCache
import io.github.neas.AliyunBuildCacheServiceFactory
import io.github.neas.ExportedAliyunCredentials
buildCache {
	registerBuildCacheService(AliyunBuildCache, AliyunBuildCacheServiceFactory)
    remote(AliyunBuildCache) {
        endpoint = 'your-aliyun-oss-endpoint'
        bucketName = "bucket-name"
        credentials = new ExportedAliyunCredentials("your-access-key-id", "your-secret-key")
        push = true //System.getenv().containsKey("CI")
    }
}

新办法引入插件如下,见plugins.gradle.org/plugin/io.g…

plugins {
    id("io.github.neas-neas.alibuildcache") version "1.0.0"
}

然后之前在创立Bucket时记载的信息这里就需要用上了

endpoint
bucketName
accessKeyId
secretKey

和咱们记载时的参数名字相同,不需要过多解说了,对座入号填入即可

照官方推荐push只在CI机器上开,developer的机器拉缓存就行,不过为了测试咱们这里先改为true好了

3. 测试作用

所有都装备好了,咱们来测试一下看看情况

rm -r ~/.gradle/caches/build-cache-1
./gradlew clean build -i

rm删除去本地build cache缓存,因为咱们要看remote cache,本地缓存优先级更高,所以要扫除它 -i 能够在输出中看到相关日志

第一次履行,看看compileJava输出

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

因为没有缓存,所以第一次履行会store到阿里云OSS

再履行一下上面的指令,再看看compileJava的输出

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

因为没有本地缓存(被咱们提早rm了,不rm的话第一步履行时也会在本地进行保存的),咱们能够看到compileJava task被符号为了FROM_CACHE,2次的cache key完全一致,并且日志输出了是从阿里云OSS下载下来的

有这个key,咱们也能够去阿里云OSS Bucket文件管理页面找到对应的文件,将它下载下来看看它究竟是什么

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

其实它便是个tar包压缩文件,能够进行解压看看里边究竟有什么,这个RemoteBuildCache便是我测试项目里边的代码文件了,你也能够对你的class文件反编译看看是否一致。这部分在Gradle深化解析 – Task原理(履行篇)其实有讲过了

此外针对android项目建议一起运用上GitHub – gradle/android-cache-fix-gradle-plugin: Gradle plugin that fixes Android build caching problems,agp插件对cache的完成有些问题,这个插件能够规避一些此类的问题

具体完成

关系图暗示如下

搭建自己的Gradle Build Cache Service(基于阿里云OSS)

核心办法

BuildCacheService

最首要的是完成BuildCacheService这个接口,接口有2个十分关键的办法loadstore

public interface BuildCacheService extends Closeable {
    boolean load(BuildCacheKey key, BuildCacheEntryReader reader) throws BuildCacheException;  
	void store(BuildCacheKey key, BuildCacheEntryWriter writer) throws BuildCacheException;  
    void close() throws IOException;  
}

load便是拿key去恳求OSS获取文件,然后将获取到的InputStream对接给reader
store便是将文件保存到OSS,调用writerwriteTo办法将数据导入到咱们的OutputStream,再将OutputStream转为InputStream传给OSS服务器
阿里云OSS有提供SDK,按照其SDK文档就行对应办法调用即可

BuildCache

public interface BuildCache {
    boolean isEnabled();  
    void setEnabled(boolean enabled);  
    boolean isPush();  
    void setPush(boolean enabled);  
}

BuildCache是用于装备BuildCacheService的,相似于写gradle plugin时的extension
默许有enabledpush2个参数
关于OSS来说还不够,以阿里云为例,还需要endpointbucketNamecredentials(首要用于装备accessKeyIdsecretAccessKey)

咱们能够经过继承来完成自己的BuildCache类,比方

abstract class AliyunBuildCache(
) : AbstractBuildCache() {  
    lateinit var endpoint: String  
    var credentials: AliyunCredentials = DefaultAliyunCredentials  
}

BuildCacheServiceFactory

public interface BuildCacheServiceFactory<T extends BuildCache> {
	BuildCacheService createBuildCacheService(T configuration, Describer describer);
}

这个接口是用来创立BuildCacheService,看看AliyunBuildCacheServiceFactory的完成,调用describer结合buildCache进行一些描绘性质的装备,然后用buildCache去创立AliyunBuildCacheService实例 ![[aliyun-gradle-plugin-factory.png]]

Describer

interface Describer {
     Describer type(String type);   
     Describer config(String name, String value);  
}

用于描绘BuildCacheService
type 网络恳求的是http,本地的是directory,自定义的比方我这里是aliyun
config 装备一些tag,例如bucketName的值,endpoint
这些信息能够被build scan插件搜集,关于判别缓存命中率有必定帮助

建立相关

需要在Plugin里边去绑定关系

class AliyunGradleBuildCachePlugin : Plugin<Settings> {
    override fun apply(settings: Settings) {  
        settings.buildCache.registerBuildCacheService(  
            AliyunBuildCache::class.java,  
            AliyunBuildCacheServiceFactory::class.java  
        )  
    }  
}

留意这是一个针对Setting的Plugin,调用registerBuildCacheService注册BuildCacheBuildCacheServiceFactory

之后就能够在settings.gradle脚本对BuildCache进行装备了,例如上面提到过的

buildCache {
    remote(AliyunBuildCache) {  
        endpoint = 'your-end-point'  
        bucketName = "bucket-name"  
        credentials = new ExportedAliyunCredentials("your-access-key-id", "your-secret-key")  
        push = true
    }  
}

至此关于Build Cache的运用和原理大致都进行了阐明,Build Cache在实际运用中假如感觉作用欠安,那还需要从多个方面去提升它的缓存命中率,有几个对其命中率有影响的要素,例如履行gradle的JVM的版别不同,Java/Kotlin编译时的JVM版别不同,classpath改变等,可能需要经过build scan等构建信息搜集办法去进行具体分析,以提升缓存命中率。关于构建信息的搜集能够参阅我之前的怎么像build scan相同搜集gradle构建信息

参阅资料

GitHub – androidx/gcp-gradle-build-cache
Docker
运用本地和长途的Gradle构建缓存加速构建速度
Android-Studio编译速度优化
Using Gradle Build Cache Server. Fastest way to work is to avoid doing… | by Csar Ferreira | Medium
Build Cache Node User Manual | Gradle Enterprise Docs
GitHub – rnett/github-actions-gradle-cache