Skip to content

Commit 90da683

Browse files
committed
2.4s -> 0.65s
1 parent 0182484 commit 90da683

9 files changed

+225
-45
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/target
2+
/aws-lambda-rie
3+
/jdk
4+
/cr

Dockerfile.baseline

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
FROM ubuntu:18.04
2+
3+
COPY jdk /jdk
4+
5+
# Copy function code and runtime dependencies from Maven layout
6+
COPY target/classes /function
7+
COPY target/dependency/* /function/lib/
8+
9+
WORKDIR /function
10+
11+
ENV AWS_XRAY_CONTEXT_MISSING=LOG_ERROR
12+
13+
ENTRYPOINT [ "/jdk/bin/java", \
14+
"-XX:-UsePerfData", \
15+
"-cp", "/function:/function/lib/*", \
16+
"com.amazonaws.services.lambda.runtime.api.client.AWSLambda" ]
17+
18+
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
19+
CMD [ "example.Handler::handleRequest" ]
20+

Dockerfile.checkpoint

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
FROM ubuntu:18.04 as builder
2+
3+
RUN apt update && \
4+
DEBIAN_FRONTEND=noninteractive apt -y --no-install-recommends install liblz4-tool && \
5+
apt clean && \
6+
rm -rf /var/lib/apt /var/cache/apt
7+
8+
COPY jdk /jdk
9+
10+
# Copy function code and runtime dependencies from Maven layout
11+
COPY target/classes /function
12+
COPY target/dependency/* /function/lib/
13+
14+
RUN cd /function/lib; /jdk/bin/jar -x -f aws-lambda-java-runtime-interface-client*.jar \
15+
aws-lambda-runtime-interface-client.musl.so \
16+
aws-lambda-runtime-interface-client.glibc.so
17+
18+
RUN tar -c /jdk | lz4 -z -9 - /jdk.tar.lz4
19+
20+
FROM ubuntu:18.04
21+
22+
RUN apt update && \
23+
DEBIAN_FRONTEND=noninteractive apt -y --no-install-recommends install liblz4-tool && \
24+
apt clean && \
25+
rm -rf /var/lib/apt /var/cache/apt
26+
27+
COPY --from=builder /jdk.tar.lz4 /
28+
COPY --from=builder /function /function
29+
30+
WORKDIR /function
31+
32+
ENV AWS_XRAY_CONTEXT_MISSING=LOG_ERROR
33+
34+
COPY checkpoint.cmd.sh /
35+
36+
ENTRYPOINT [ "/bin/bash", "/checkpoint.cmd.sh" ]
37+
38+
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
39+
CMD [ "example.Handler::handleRequest" ]

Dockerfile.restore

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM ubuntu:18.04 as builder
2+
3+
RUN apt update && \
4+
DEBIAN_FRONTEND=noninteractive apt -y --no-install-recommends install liblz4-tool && \
5+
apt clean && \
6+
rm -rf /var/lib/apt /var/cache/apt
7+
8+
COPY cr /cr
9+
RUN tar -c /cr | lz4 -z -9 - /cr.tar.lz4
10+
11+
FROM crac-lambda-checkpoint
12+
13+
COPY --from=builder /cr.tar.lz4 /
14+
15+
ADD restore.cmd.sh /
16+
ENTRYPOINT [ "/bin/bash", "/restore.cmd.sh" ]
17+
18+
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
19+
CMD [ "example.Handler::handleRequest" ]

checkpoint.cmd.sh

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
3+
lz4 -d /jdk.tar.lz4 - | tar x -C /tmp/
4+
5+
# Ensure small PID, for privileged-less criu to be able to restore PID by bumping.
6+
# But not too small, to avoid clashes with other occasional processes on restore.
7+
exec /aws-lambda-rie /bin/bash -c '\
8+
while [ 128 -ge $(cat /proc/sys/kernel/ns_last_pid) ]; do :; done; \
9+
setsid /tmp/jdk/bin/java \
10+
-Xshare:off \
11+
-XX:-UsePerfData \
12+
-XX:CRaCCheckpointTo=/cr \
13+
-cp /function:/function/lib/* \
14+
-Dcom.amazonaws.services.lambda.runtime.api.client.NativeClient.libsBase=/function/lib/ \
15+
com.amazonaws.services.lambda.runtime.api.client.AWSLambda $0' "$@"

crac-steps.sh

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/bash
2+
3+
s00_init() {
4+
5+
if [ -z $JAVA_HOME ]; then
6+
echo "No JAVA_HOME specified"
7+
return 1
8+
fi
9+
10+
rm -rf jdk
11+
cp -r $JAVA_HOME jdk
12+
13+
curl -L -o aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/download/v1.3/aws-lambda-rie-$(uname -m)
14+
chmod +x aws-lambda-rie
15+
}
16+
17+
dojlink() {
18+
$JAVA_HOME/bin/jlink --bind-services --output jdk --module-path $JAVA_HOME/jmods --add-modules java.base,jdk.unsupported,java.sql
19+
}
20+
21+
s01_build() {
22+
mvn compile dependency:copy-dependencies -DincludeScope=runtime
23+
docker build -t crac-lambda-checkpoint -f Dockerfile.checkpoint .
24+
}
25+
26+
s02_start_checkpoint() {
27+
docker run \
28+
--privileged \
29+
--rm \
30+
--name crac-checkpoint \
31+
-v $PWD/aws-lambda-rie:/aws-lambda-rie \
32+
-v $PWD/cr:/cr \
33+
-p 8080:8080 \
34+
-e AWS_REGION=us-west-2 \
35+
crac-lambda-checkpoint
36+
}
37+
38+
rawpost() {
39+
local c=0
40+
while [ $c -lt 20 ]; do
41+
curl -XPOST --no-progress-meter -d "$@" http://localhost:8080/2015-03-31/functions/function/invocations && break
42+
sleep 0.2
43+
c=$(($c + 1))
44+
done
45+
}
46+
47+
post() {
48+
rawpost "{ Records : [ { body : \"${1}\" } ] }"
49+
}
50+
51+
s03_checkpoint() {
52+
post checkpoint
53+
sleep 2
54+
post fini
55+
docker rm -f crac-checkpoint
56+
}
57+
58+
s04_prepare_restore() {
59+
rm -f cr/dump4.log # XXX
60+
docker build -t crac-lambda-restore -f Dockerfile.restore .
61+
}
62+
63+
"$@"

pom.xml

+30-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@
1212
<maven.compiler.target>1.8</maven.compiler.target>
1313
</properties>
1414
<dependencies>
15+
<dependency>
16+
<groupId>io.github.crac</groupId>
17+
<artifactId>org-crac</artifactId>
18+
<version>0.1.0</version>
19+
</dependency>
20+
<dependency>
21+
<groupId>io.github.crac.com.amazonaws</groupId>
22+
<artifactId>aws-lambda-java-runtime-interface-client</artifactId>
23+
<version>1.0.0</version>
24+
</dependency>
1525
<dependency>
1626
<groupId>com.amazonaws</groupId>
1727
<artifactId>aws-lambda-java-core</artifactId>
@@ -52,6 +62,7 @@
5262
<artifactId>lambda</artifactId>
5363
<version>2.10.72</version>
5464
</dependency>
65+
<!-- XRay is not supported now
5566
<dependency>
5667
<groupId>com.amazonaws</groupId>
5768
<artifactId>aws-xray-recorder-sdk-core</artifactId>
@@ -72,6 +83,7 @@
7283
<artifactId>aws-xray-recorder-sdk-aws-sdk-v2-instrumentor</artifactId>
7384
<version>2.4.0</version>
7485
</dependency>
86+
-->
7587
<dependency>
7688
<groupId>org.junit.jupiter</groupId>
7789
<artifactId>junit-jupiter-api</artifactId>
@@ -131,6 +143,23 @@
131143
<target>1.8</target>
132144
</configuration>
133145
</plugin>
146+
<plugin>
147+
<groupId>org.apache.maven.plugins</groupId>
148+
<artifactId>maven-dependency-plugin</artifactId>
149+
<version>3.1.2</version>
150+
<executions>
151+
<execution>
152+
<id>copy-dependencies</id>
153+
<phase>package</phase>
154+
<goals>
155+
<goal>copy-dependencies</goal>
156+
</goals>
157+
<configuration>
158+
<!-- configure the plugin here -->
159+
</configuration>
160+
</execution>
161+
</executions>
162+
</plugin>
134163
</plugins>
135164
</build>
136-
</project>
165+
</project>

restore.cmd.sh

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
lz4 -d /jdk.tar.lz4 - | tar x -C /tmp/
4+
lz4 -d /cr.tar.lz4 - | tar x -C /tmp/
5+
6+
exec /tmp/jdk/bin/java -XX:CRaCRestoreFrom=/tmp/cr

src/main/java/example/Handler.java

+29-44
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,50 @@
11
package example;
22

33
import com.amazonaws.services.lambda.runtime.Context;
4-
import com.amazonaws.services.lambda.runtime.LambdaLogger;
54
import com.amazonaws.services.lambda.runtime.RequestHandler;
65
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
76
import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage;
8-
9-
import software.amazon.awssdk.services.lambda.model.GetAccountSettingsRequest;
10-
import software.amazon.awssdk.services.lambda.model.GetAccountSettingsResponse;
11-
import software.amazon.awssdk.services.lambda.model.ServiceException;
12-
import software.amazon.awssdk.services.lambda.LambdaAsyncClient;
13-
import software.amazon.awssdk.services.lambda.model.AccountUsage;
14-
15-
import com.google.gson.Gson;
16-
import com.google.gson.GsonBuilder;
17-
7+
import org.crac.CheckpointException;
8+
import org.crac.RestoreException;
189
import org.slf4j.Logger;
1910
import org.slf4j.LoggerFactory;
2011

21-
import java.lang.StringBuilder;
22-
import java.util.Map;
23-
import java.util.List;
24-
import java.util.concurrent.CompletableFuture;
25-
26-
// Handler value: example.Handler
12+
// Handler value: io.github.crac.example.lambda.Handler
2713
public class Handler implements RequestHandler<SQSEvent, String>{
2814
private static final Logger logger = LoggerFactory.getLogger(Handler.class);
29-
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
30-
private static final LambdaAsyncClient lambdaClient = LambdaAsyncClient.create();
15+
3116
public Handler(){
32-
CompletableFuture<GetAccountSettingsResponse> accountSettings = lambdaClient.getAccountSettings(GetAccountSettingsRequest.builder().build());
33-
try {
34-
GetAccountSettingsResponse settings = accountSettings.get();
35-
} catch(Exception e) {
36-
e.getStackTrace();
37-
}
3817
}
18+
3919
@Override
4020
public String handleRequest(SQSEvent event, Context context)
4121
{
42-
String response = new String();
43-
// call Lambda API
44-
logger.info("Getting account settings");
45-
CompletableFuture<GetAccountSettingsResponse> accountSettings =
46-
lambdaClient.getAccountSettings(GetAccountSettingsRequest.builder().build());
47-
// log execution details
48-
logger.info("ENVIRONMENT VARIABLES: {}", gson.toJson(System.getenv()));
49-
logger.info("CONTEXT: {}", gson.toJson(context));
50-
logger.info("EVENT: {}", gson.toJson(event));
22+
logger.info("handleRequest start");
23+
5124
// process event
52-
for(SQSMessage msg : event.getRecords()){
25+
String response = "";
26+
27+
for (SQSMessage msg : event.getRecords()) {
5328
logger.info(msg.getBody());
29+
response = msg.getBody();
30+
31+
switch (msg.getBody()) {
32+
case "checkpoint":
33+
(new Thread(() -> {
34+
try {
35+
Thread.sleep(1_000);
36+
org.crac.Core.checkpointRestore();
37+
} catch (CheckpointException | RestoreException | InterruptedException e) {
38+
e.printStackTrace();
39+
}
40+
})).start();
41+
break;
42+
default:
43+
// Just echo. Will also be used to break out of curl waiting for connection.
44+
break;
45+
}
5446
}
55-
// process Lambda API response
56-
try {
57-
GetAccountSettingsResponse settings = accountSettings.get();
58-
response = gson.toJson(settings.accountUsage());
59-
logger.info("Account usage: {}", response);
60-
} catch(Exception e) {
61-
e.getStackTrace();
62-
}
47+
6348
return response;
6449
}
65-
}
50+
}

0 commit comments

Comments
 (0)