-
Notifications
You must be signed in to change notification settings - Fork 115
CRaC
CRaC(Coordinated Restore at Checkpoint)是一个可以实现Java极速启动的技术,可以实现10x甚至更多的启动性能提升。
在本节通过对spring petclinc应用使用CRaC从而了解基本使用流程。
- 下载支持CRaC的Java版本,Dragonwell 11需要版本号需要>=待补充
- 准备一台有root权限的Linux机器(支持x86和aarch64),内核版本>=4.19
- 获取spring petclinc代码
git clone https://github.com/spring-projects/spring-petclinic.git
cd spring-petclinic
git reset --hard ab9135ad9bbc8631221caf0a7ee3eadd0561311d
- 替换tomcat-embed-core为支持CRaC的版本,进入到spring-petclinc的目录后,执行命令:
patch pom.xml <<EOF
--- pom.xml 2024-10-11 16:05:33
+++ pom.xml.new 2024-10-11 16:06:26
@@ -49,8 +49,19 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-core</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
+ <groupId>io.github.crac.org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-core</artifactId>
+ <version>9.0.58</version>
+ </dependency>
+ <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
EOF
- 执行命令
mvn clean packages
进行构建,构建的产物即target/spring-petclinic-2.4.0.BUILD-SNAPSHOT.jar
- 执行如下命令:
java -XX:CRaCCheckpointTo=cr -jar spring-petclinic-2.4.0.BUILD-SNAPSHOT.jar
启动spring petclinc - 启动后通过
curl http://127.0.0.1:8080/
检查是否启动成功 - 执行命令
jcmd $pid JDK.checkpoint
产生快照到目录cr,其中$pid为第一步启动的java进程的pid。执行成功以后会导致上面进程退出
执行命令从快照恢复 java -XX:CRaCRestoreFrom=cr -jar spring-petclinic-2.4.0.BUILD-SNAPSHOT.jar
恢复成功不会有输出,因为是从进程暂停的地方恢复执行,通过curl http://127.0.0.1:8080/
确认是否恢复成功
理解CRaC之前,需要先了解criu, CRaC依赖criu对进程在用户态进行checkpoint以及restore。 criu在用户态checkpoint时会将进程的状态保存到快照文件中。一旦有了快照文件,就可以从快照文件恢复进程到checkpoint时的状态。可以用在如下一些场景:
- 迁移进程:由于种种原因例如内核升级,更换机器等,需要将进程从某机器迁移到其它机器上 a. 进程可能是用户的,用户希望无感迁移 b. 进程可能执行一些耗时的科学计算,如果进程停止了,再重新运行需要很长时间
- 加速启动:以Java为例,Java语言本身的动态性使得Java在启动过程中类加载以及JIT编译会占用较多资源,只有进程进入到稳定态,才能达到性能的峰值。如果能直接从峰值的状态恢复,则会节约重新执行的时间。
criu会将进程的如下状态记录下来:
- 内存
- 映射
- 线程的寄存器
- 文件
- cgroup
- ...
criu从理论上可以对任何用户态的进程进行checkpoint并restore,但是如果直接使用criu会遇到很多阻碍。例如:
- 如果在checkpoint时候,进程正在写文件中,用户写入的数据调用write,可能写入部分数据,也有可能写入数据,但是还没有flush到磁盘
- restore时系统时间、IP地址会发生变化,程序中依赖这些变化的数据,必须要进行相应的变化。假设程序中一个心跳检测的线程判断执行某个操作是否超时了,由于checkpoint时将当时的系统时间保存到内存中,当restore时可能已经是很久之后的,这时如果用当前时间与checkpoint时的系统时间比较,就会发现可能已经超时了。程序可能认为异常了。
- 进程运行行为依赖配置文件,但是restore时的配置文件与checkpoint并不相同。
针对上述的问题,抽象出共性的一些需求:
- checkpoint时整个程序必须处于某个可控的“安全状态”,这个安全状态包括:
- 用户可见的状态:用户能控制的部分,比如文件确保写入到磁盘上
- 用户不可见的状态:对于JVM来说,就是JVM内部的状态。
- restore需要给用户控制状态的恢复,从而实现一个快照在多个环境上可以恢复,从而避免一个快照只能给一个环境使用。
那么CRaC是如何保证上述的几点的:
- 为了实现JVM的内部的状态安全:
- checkpoint是在进入safepoint以后完成的
- JVM内部的类,例如随机数在restore重新初始化
- 为了实现应用程序的可控的安全状态,CRaC提供了API给用户注册callback,这些callback在checkpoint之前调用,从而让用户自己保证程序在安全状态
- 为了实现一个快照在多个环境恢复,在恢复时提供了callback实现用户自定义的恢复
- JDK是否满足要求?目前只支持Dragonwell 11
- 运行环境内核版本是否满足要求?
- 内核版本< 4.19: 不支持
- 内核版本>=4.19但<5.9:是否允许以privileged模式运行,如果不允许则不支持
- 内核版本>=5.9: 是否允许程序拥有CAP_CHECKPOINT_RESTORE,如果不允许则不支持
- 评估CRaC收益是否达到预期: CRaC的收益取决于代码中调用checkpoint的位置,位置离启动成功越近,收益越大,但是可能带来代码适配工作量越大。
- 是否能接受应用程序针对CRaC的适配: 涉及到对应用程序的代码进行修改,具体的工作多少取决于应用的状态恢复的复杂程度
- Linux内核必须是4.19以及之后的版本
- 如果是4.19只支持以privileged运行
- >=5.9支持以非privileged运行
- checkpoint时确保有足够的空闲内存,否则可能由于OOM而导致失败(具体大小取决于应用)
- checkpoint以及restore的需要如下一致,否则可能恢复失败:
- JVM版本完全一致
- restore机器的CPU的features需要是checkpoint的features的超集
- 此特性与AppCDS(EagerAppCDS)存在冲突,不可同时使用
- 使用
jcmd $PID JDK.checkpoint
生成快照 - 程序中主动调用
org.crac.Core.checkpointRestore()
生成快照。一旦执行这个调用以后,快照就会生成(在未出错的情况下),同时进程退出 这一步可以会遇到快照没有生成,或者报错,请移步到错误处理
-
(root用户运行无需此步骤) 设置${JAVA_HOME}/lib/criu有相应capability:
setcap cap_checkpoint_restore+eip ${JAVA_HOME}/lib/criu
- JVM增加选项表示保存到快照到目录cr, 运行java
- root用户:
-XX:CRaCCheckpointTo=cr
- 非root用户:
-XX:CRaCCheckpointTo=cr -XX:+CRaCUnprivileged
- 产生快照
- JVM增加如下选项,从目录cr中的快照恢复,运行java进行恢复
- root用户:
-XX:CRaCRestoreFrom=cr
- 非root用户:
-XX:CRaCRestoreFrom=cr -XX:+CRaCUnprivileged
-
(privileged模式运行无需此步骤) 镜像构建时对${JAVA_HOME}/lib/criu设置相应的capability:
RUN setcap 'cap_checkpoint_restore+eip cap_setpcap+eip' /jdk/lib/criu
- JVM增加选项表示保存快照到目录cr
- privileged模式:
-XX:CRaCCheckpointTo=cr -XX:CRaCRestoreInheritPipeFds=1,2
- 非privileged模式:
-XX:CRaCCheckpointTo=cr -XX:CRaCRestoreInheritPipeFds=1,2 -XX:+CRaCUnprivileged
- docker run用于准备checkpoint,需要额外增加如下参数:
- privileged模式:
--privileged --user root
- 非privileged模式:
--security-opt seccomp=unconfined --cap-add CHECKPOINT_RESTORE --cap-add CAP_SETPCAP
- 产生快照
- JVM增加参数用于从cr目录恢复:
-XX:CRaCRestoreFrom=cr -XX:+CRaCUnprivileged
- docker run用于从cr目录恢复,需要额外增加如下参数:
- privileged模式:
--privileged --user root
- 非privileged模式:
--security-opt seccomp=unconfined --cap-add CHECKPOINT_RESTORE --cap-add CAP_SETPCAP
通过设置pod的环境变量来控制pod是用于做checkpoint,还是从快照恢复,如下是一个示例的脚本供参考:
#! /bin/sh
APP_DIR=$(dirname "$0")
JAVA=${JAVA_HOME}/bin/java
CR=${APP_DIR}/cr
UNPRIVILEGE_OPT=""
if [[ $EUID -ne 0 ]]; then
UNPRIVILEGE_OPT="-XX:+CRaCUnprivileged"
fi
pushd ${APP_DIR}
if test "x${DO_RESTORE}" = xtrue; then
export CRAC_CRIU_OPTS="-o ${CR}/restore.log -vvvv"
${JAVA} -XX:CRaCRestoreFrom=${CR} ${UNPRIVILEGE_OPT} -jar spring-petclinic-2.4.0.BUILD-SNAPSHOT.jar
elif test "x${DO_CHECKPOINT}" = xtrue; then
# avoid pid conflit
for i in {1..10}; do sh -c "echo null > /dev/null"; done
${JAVA} -XX:CRaCCheckpointTo=${CR} ${UNPRIVILEGE_OPT} -XX:CRaCRestoreInheritPipeFds=1,2 -jar spring-petclinic-2.4.0.BUILD-SNAPSHOT.jar &
pid=$!
sleep 10
${JAVA_HOME}/bin/jcmd $pid JDK.checkpoint
sleep 5
cat ${CR}/dump4.log
sleep 3600
fi
如果是以非privileged模式运行,则在构建镜像的时候,需要设置的capabilty,如下示例:
FROM alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/alinux3:latest
RUN groupadd -g 1000 app && useradd -u 1000 -g app -s /bin/sh -d /home/app -m app
USER app:app
ADD dw11.tar.gz /home/app
ADD spring-petclinic-2.4.0.BUILD-SNAPSHOT.tar.gz /home/app
ADD run.sh /home/app
ENV JAVA_HOME=/home/app/jdk
USER root
RUN setcap 'cap_checkpoint_restore+eip cap_setpcap+eip' /home/app/jdk/lib/criu
USER app:app
CMD /home/app/run.sh
与正常的Deployment基本一样,如果是privileged运行,则需要在Deployment的YAML文件中增加下面的部分:
env:
- name: DO_CHECKPOINT
value: "true"
securityContext:
privileged: true
如果是非privlieged,则需要增加如下部分:
env:
- name: DO_CHECKPOINT
value: "true"
securityContext:
capabilities:
add: ["CHECKPOINT_RESTORE"]
上面的Deployment会在启动成功以后生成快照,可以进入pod里将快照文件打包并传输到用于构建镜像的机器上 重新构建镜像,可以在原来的镜像上叠加一层
如果是privileged在YAML中增加如下部分:
env:
- name: DO_RESTORE
value: "true"
securityContext:
privileged: true
如果是非privileged增加如下部分:
env:
- name: DO_RESTORE
value: "true"
securityContext:
capabilities:
add: ["CHECKPOINT_RESTORE"]
CRaC是借助criu对java进程的状态保存下来,再次恢复时会从上次停下来的地方继续运行,但是在一些情况下需要程序对一些修改,从而确保CRaC能正确的恢复,包括但不限于:
- 文件可能需要在checkpoint时关闭确保文件的一致性,在restore时需要重新打开
- 网络连接在checkpoint时关闭,在restore时重新连接,因为这些连接可能已经失效
- 应用的状态可能已经无效,例如依赖环境变量、IP等,但是restore时已经发生了变化等
下面以一个简单的程序代码说明如何适配,如下的代码:
public class TimeoutChecker implements Run{
private long lastTime;
public TimeoutChecker() {
lastTime = System.currentTimeInMills();
}
public bool checkTimeout() {
if (System.currentTimeInMills() - lastTime) > 5*1000L) {
throw new TimeoutException();
} else {
lastTime = System.currentTimeInMills();
}
}
}
在checkpoint时lastTime保存的是最后一次的时间,但是在恢复的时候如果不对lastTime进行重新赋值则会导致一旦恢复就会抛出异常。 CRaC提供了Resource接口,提供了回调方法在checkpoint之前以及restore之后调用。 先依赖CRaC的三方包: Maven:
<dependency>
<groupId>org.crac</groupId>
<artifactId>crac</artifactId>
<version>1.4.0</version>
</dependency>
Gradle:
dependencies {
compile group:'org.crac' , name: 'crac', version: "1.4.0"
}
然后让TimeoutChecker实现Resource接口:
+ import org.crac.*;
+ public class TimeoutChecker implements Run, Resource{
- public class TimeoutChecker implements Run{
public TimeoutChecker() {
lastTime = System.currentTimeInMills();
+ Core.getGlobalContext().register(this);
}
+ @Override
+ public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
+ }
+ @Override
+ public void afterRestore(Context<? extends Resource> context) throws Exception {
+ lastTime = System.currentTimeInMills();
+ }
public bool checkTimeout() {
if (System.currentTimeInMills() - lastTime) > 5*1000L) {
throw new TimeoutException();
} else {
lastTime = System.currentTimeInMills();
}
}
}
文件一般在checkpoint时需要先关闭,但是针对一些特殊的情况可以不关闭。
log4j以及logback的日志文件一般打开的是方式是O_APPEND和O_WRONLY,这种方式下可以不用关闭文件,但是需要在JVM参数CRaCAppendOnlyLogFiles指定这些文件。CRaCAppendOnlyLogFiles指定的文件如果在恢复的时候不存在的话,会默认创建空文件。
例如指定进程所有以O_APPEND和O_WRONLY模式打开的文件都可以在checkpoint时不检查是否关闭-XX:CRaCAppendOnlyLogFiles="*"
,更多的配置方法参考配置参考。
- 增加
-XX:CRaCIgnoredFileDescriptors=3
让checkpoint时忽略gc日志文件 - restore时创建空的日志文件,重新开始写入
这类文件在checkpoint时确定内容,然后在容器下环境恢复,进程可以继续写入,但是这些写入一旦等到容器消亡以后就丢失了。可以通过JDK提供的API来注册文件,注册以后在checkpoint时,JDK会将这些文件保存到快照目录中。使用方法如下:
public class JvmCracUtils {
/**
* save the pseudo persistent file to image dir, then restore to origin path
*/
public static final int SAVE_RESTORE = 0x01;
/**
* create a symbol link when restore a file. This should have a better performance than
* COPY_WHEN_RESTORE if file is large
*/
public static final int SYMLINK_WHEN_RESTORE = 0x10;
private static boolean supportCracExtension;
private static Method registerPseudoPersistentMethod;
private static Method appendToAppClassLoaderClassPathMethod;
static {
initCracExtension();
}
private static void initCracExtension() {
try {
Class clsCore = Class.forName("javax.crac.Core");
registerPseudoPersistentMethod =
clsCore.getMethod("registerPseudoPersistent", String.class, int.class);
appendToAppClassLoaderClassPathMethod =
clsCore.getMethod("appendToAppClassLoaderClassPath", String.class);
supportCracExtension = true;
} catch (Throwable ignore) {
}
}
public static void registerPseudoPersistent(String absoluteFilePath, int mode)
throws CheckpointException {
if (!supportCracExtension) {
throw new RuntimeException("Current JDK not support CRaC extension.");
}
try {
registerPseudoPersistentMethod.invoke(null, absoluteFilePath, mode);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
public static void appendToAppClassLoaderClassPath(String path) throws CheckpointException {
if (!supportCracExtension) {
throw new RuntimeException("Current JDK not support CRaC extension.");
}
try {
appendToAppClassLoaderClassPathMethod.invoke(null, path);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
下面将文件/home/admin/logs/app.log注册
JvmCracUtils.registerPseudoPersistent("/home/admin/logs/app.log",
JvmCracUtils.SAVE_RESTORE | JvmCracUtils.SYMLINK_WHEN_RESTORE);
如果是用户程序依赖的jar包,由于是只读的并假设它在恢复一直存在,所以不需要关闭。但是在这个之外的其它文件则需要实现org.crac.Resource接口。
JMX的适配除了关闭javax.management.remote.JMXConnectorServer以及java.rmi.registry.Registry外,较为特殊的地方在于JMX关闭以后,内部的socket并不会立即关闭,所以在checkpoint时需要sleep一段时间,一般在60秒左右会完全关闭。
应用中使用server socket经常会一直以单独的线程中执行无超时的方式accept,可以参考如下方法关闭ServerSocket:
public class FooServer extends Thread {
/** Indicates whether a shutdown of server component has been requested. */
private final AtomicBoolean shutdownRequested = new AtomicBoolean();
private volatile checkpointing = false;
public void run() {
try {
while (!this.shutdownRequested.get()) {
try {
ServerConnection conn =
new ServerConnection(
NetUtils.acceptWithoutTimeout(serverSocket), this);
try {
synchronized (activeConnections) {
while (activeConnections.size() >= maxConnections) {
activeConnections.wait(2000);
}
activeConnections.add(conn);
}
conn.start();
conn = null;
} finally {
if (conn != null) {
conn.close();
synchronized (activeConnections) {
activeConnections.remove(conn);
}
}
}
} catch (Throwable t) {
if (checkpointing) {
synchronized (paused) {
paused.compareAndSet(false, true);
paused.notifyAll();
}
synchronized (restoring) {
while (!restoring.get()) {
// wait until notify in CRaCResource.afterRestore
try {
restoring.wait();
} catch (InterruptedException ie) {
// This interrupt exception caused by call closeForCRaC
continue;
}
}
}
} else {
throw t;
}
}
}
} catch (Throwable t) {
//....
}
}
/**
* CRaC checkpoint&restore need pause the thread first, then replace ServerSocket. After that
* start thread again.
*/
private void closeForCRaC() throws InterruptedException, IOException {
checkpointing = true;
Exception exception = null;
try {
this.serverSocket.close();
} catch (IOException ioe) {
exception = ioe;
}
// wake the thread up, in case it is waiting on some operation
interrupt();
// wait the thread paused, so make sure no one modify activeConnections
synchronized (paused) {
while (!paused.get()) {
paused.wait();
}
}
synchronized (activeConnections) {
if (!activeConnections.isEmpty()) {
for (ServerConnection conn : activeConnections) {
conn.close();
}
activeConnections.clear();
}
}
checkpointing = false;
paused.compareAndSet(true, false);
}
private class CRaCResource implements Resource {
@Override
public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
closeForCRaC();
}
@Override
public void afterRestore(Context<? extends Resource> context) throws Exception {
synchronized (restoring) {
restoring.compareAndSet(false, true);
restoring.notifyAll();
}
}
}
}
- 根据程序的语义,分析哪些状态在checkpoint时要处理,哪些在restore要恢复
- 将上述的逻辑通过实现org.crac.Resource接口并在适当的位置注册到CRaC的上下文中 这里要注意所有注册到CRaC上下文中的Resource都是以soft reference方式,意味着如果没有其它引用Resource,那么Resource在checkpoint时可能已经被清除了,所以需要清理状态的对象的生命周期决定是否需要Resource对象的强引用。
在应用自身状态适配的过程中,经常需要处理final字段的修改:
- 去掉final
- 更改字段的类型,用一个新的包装类型将原来的类型包装起来,这样final可以保留,但是包装类型提供方法更新实际的值
- 扩展原来的类,在新的类中去除掉final
- 类型增加一个拷贝方法,在restore时调用此方法恢复对象内部状态
- 是否已经有支持CRaC的版本? 如有更新到相应的版本
- 是否可以在应用层直接关闭三方库中资源? 例如netty可以在应用代码进行start和stop server
- 是否可以通过配置来关闭一些不必要但是会导致无法checkpoint的资源。以log4j的jmx为例,如果应用不使用此特性,可以通过
-Dlog4j2.disable.jmx=true
关闭
提供了如下的API在恢复的上下文时更新class path
public void afterRestore(Context<? extends Resource> context) throws Exception {
if (userLibDir != null) {
final Path workingDirectory = FileUtils.getCurrentWorkingDirectory();
//... 这里省略list用户jar的逻辑
for (Path jarPath : relativeJars) {
JvmCracUtils.appendToAppClassLoaderClassPath(jarPath.toString());
}
}
}
- 先检查标准错误输出是否有打印异常堆栈,异常主要包括如下2类:
- 如果没有异常,则有可能是criu执行过程中发生错误,检查-XX:CRaCCheckpointTo指定的目录中dump4.log查看是否有错误。
Error (compel/src/lib/infect.c:261): The criu itself is within dumped tree.
确保checkpoint的java进程的pid不能为1
(00.006081) Error (criu/files-reg.c:1735): Build-ID (For validation) could not be obtained for file /var/db/nscd/hosts because can't open the file
目前checkpoint时还不能处理使用nscd cache的情况下。需要关闭nscd cache再进行checkpoint。方法如下:
- 修改/etc/nscd.conf,将passwd和hosts对应的enable-cache设置为no
- 重启nscd服务,service nscd restart |
- 先检查标准错误输出是否有异常
- 如果第一步没有报错,则可能是criu在restore的过程中出错,通过设置环境变量设置restore的日志:export CRAC_CRIU_OPTS="-o restore.log -vvvv"
criu日志中/proc/sys read-only
criu在恢复时需要确保pid与checkpoint时一致,如果内核不支持clone3指定tid,则需要通过修改/proc/sys/kernel/ns_last_pid来控制新的进程(线程的)id,但是如果/proc/sys是只读挂载,则无法修改就会出现restore失败。解决方法:以只读方式重新挂载mount -o rw,remount proc /procmount -o rw,remount proc /proc/sys
open file: **/metadata for read failed, error:
checkpoint失败了,快照没有生成成功,请先确保checkpoint成功
vm version ** != **
checkpoint时运行的Java与restore的java版本不一致
CPU instruction capabilities which JVM used do not match run time
restore的环境中CPU缺少在checkpoint环境中JIT code中使用的指令
tty: Don't have tty to inherit session from, aborting
这是由于在checkpoint是没有关闭进程的标准输入对应的tty导致,可以在checkpoint和restore时将标准输入不再关联tty.setsid java xxx < /dev/null &> run.log
.上述命令会重新创建一个session,并且把输入用/dev/null代替,这时标准输出和错误都会写到run.log中
容器中恢复以后标准错误和输出没有内容
在checkpoint时增加选项:-XX:CRaCRestoreInheritPipeFds=1,2
Can't dump ghost file ** of 5693440 size, increase limit
根据提示大小调整如下环境变量的上限export CRAC_CRIU_OPTS="--ghost-limit=10M"
restore时java main方法参数不生效
restore时是从checkpoint往后执行,所以main的参数并不会重新读取。CRaC提供了重新读取system properties的方式,可以将main的参数通过system properties来指定。
Pid xxx do not match exptected xxx
pid被其它进程占用了,可以在checkpoint时运行若干次shell命令,空出一段pid避免restore时冲突
选项 | 说明 |
---|---|
-XX:CRaCCheckpointTo | 开启checkpoint并且将快照写入到选项指定目录 |
-XX:CRaCRestoreFrom | 从指定选项指定的目录中的快照恢复java进程 |
-XX:CRaCValidateBeforeRestore | 默认打开,在restore之前校验cpu,jvm的一致性,如果不一致则fail back到正常启动 |
-XX:+CRTraceStartupTime和-Djdk.crac.trace-startup-time=true | 打印快照的恢复的时间戳 |
-Djdk.crac.debug=true | 打印每个Resource在checkpoint以及restore调用的详细信息 |
-XX:+CRPrintResourcesOnCheckpoint | 在checkpoint之前打印所有的fd信息 |
-XX:CRaCIgnoredFileDescriptors | 例如:-XX:CRaCIgnoredFileDescriptors=3表示在checkpoint时忽略fd为3文件 |
-XX:CRaCRestoreInheritPipeFds | 例如-XX:CRaCRestoreInheritPipeFds=1,2用于在容器环境中Java进程的fd为1,2可能是管道,这样容器运行时可以通过管道获取到进程的标准输出和错误。此选项用于在恢复时对于从父进程的fd保留,不做恢复。 |
-XX:+CRaCUnprivileged | 以unprivileged模式运行,在此模式运行时需要对${JAVA_HOME}/lib/criu设置相应的capability才可以运行。如果内核是4.19,需要CAP_SYS_ADMIN,如果内核是5.10,需要CAP_CHECKPOINT_RESTORE |
-XX:CRaCAppendOnlyLogFiles | 配置通过O_APPEND和O_WRONLY打开文件可以在checkpoint可以忽略。支持""表示所有这种模式打开的文件,".log,*.txt"表示所有扩展名为log和txt的文件,"/home/admin/foo.log,/home/admin/logs/bar.log"指定特定的文件 |
环境变量名称 | 说明 |
---|---|
CRAC_CRIU_OPTS | CRaC内部使用了criu作为快照的引擎,criu本身支持较多的选项,需要使用这些选项,可以环境变量来传递。criu完整的选项参考:Usage |
CRAC_CRIU_LEAVE_RUNNING | 默认情况dump之后就会将目标进程kill掉,有时不希望kill掉,可以将此值设置为true,从而继续运行 |