Java, das auf AWS Lambda ausgeführt wird, ist beim ersten Mal langsam, aber ich habe nach einer Möglichkeit gesucht, es schneller zu machen. Ich bin am Ende zum Inhalt der Referenzseite gekommen und habe es tatsächlich ausprobiert, es ist also eine Aufzeichnung.
Die Latenzinformationen wurden von X-Ray erfasst.
Legen Sie die Datei einfach in S3
S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
RequestBody.fromString("contents"));
Versuchen Sie es zuerst normal.
package helloworld;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
public class TestTarget0429 implements RequestHandler<Object, Object> {
public Object handleRequest(final Object input, final Context context) {
String ENV_BUCKET = System.getenv("BUCKET");
S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
return null;
}
}
Anzahl | Latenz(ms) | Inhalte verarbeiten |
---|---|---|
1 | 6200 | |
2 | 422 | |
3 | 217 | |
4 | 210 | |
5 | 315 |
Nur das erste Mal ist spät, der sogenannte Kaltstart ist spät. Nur eine Datei in S3 zu erstellen ist 6 Sekunden langsam, nicht wahr?
Wie wäre es also mit der "Provisioned Concurrency", die Ende letzten Jahres erschien? https://aws.amazon.com/jp/blogs/news/new-provisioned-concurrency-for-lambda-functions/
Der Quellcode ist der gleiche wie bei Verification 1.
Anzahl | Latenz(ms) | Inhalte verarbeiten |
---|---|---|
1 | 5500 | |
2 | 266 | |
3 | 274 | |
4 | 402 | |
5 | 304 |
** Ist das erste Mal nicht noch zu spät? .. ** ** ** Die Bereitstellung von Concurrency 1 kostet 14,42 USD pro Monat, ist aber nicht so viel. .. ..
Deaktivieren Sie anschließend Provisioned Concurrency und setzen Sie die Überprüfung fort
Um die Ursache für die Langsamkeit beim ersten Mal herauszufinden, habe ich versucht, die Verarbeitung beim ersten Start von Lambda und beim zweiten Start zu trennen.
Erstellen Sie eine statische "count" -Variable und versuchen Sie es mit einer Eile, die nur den ersten Aufruf zurückgibt.
if (count == 1) {
count++;
return null;
}
package helloworld;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
public class TestTarget0429 implements RequestHandler<Object, Object> {
private static int count = 1;
public Object handleRequest(final Object input, final Context context) {
if (count == 1) {
count++;
return null;
}
String ENV_BUCKET = System.getenv("BUCKET");
S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
return null;
}
}
Anzahl | Latenz | Inhalte verarbeiten |
---|---|---|
1 | 625ms | Nur Initialisierungsprozess |
2 | 5600ms | S3 PUT (1. Mal) |
3 | 393ms | S3 PUT (2. Mal) |
4 | 401ms | S3 PUT (3. Mal) |
5 | 311ms | S3 PUT (4. Mal) |
Es stellt sich heraus, dass der Initialisierungsprozess nicht langsam ist. Es scheint, dass S3 PUT (zum ersten Mal) lange dauert.
Lassen Sie uns den Teil, der S3Client erstellt, statisch machen.
private static String ENV_BUCKET = System.getenv("BUCKET");
private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
package helloworld;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
public class TestTarget0429 implements RequestHandler<Object, Object> {
private static int count = 1;
private static String ENV_BUCKET = System.getenv("BUCKET");
private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
public Object handleRequest(final Object input, final Context context) {
if (count == 1) {
count++;
return null;
}
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
return null;
}
}
Anzahl | Latenz | Inhalte verarbeiten |
---|---|---|
1 | 2400ms | Initialisierungsprozess und Erstellung der S3Client-Instanz |
2 | 2200ms | S3 PUT (1. Mal) |
3 | 43ms | S3 PUT (2. Mal) |
4 | 46ms | S3 PUT (3. Mal) |
5 | 78ms | S3 PUT (4. Mal) |
Oh! Die erste Verarbeitung dauerte etwas länger und die zweite etwas schneller. Nach dem dritten Mal wird es schneller, aber hat das auch Auswirkungen?
Ich fand, dass die Verarbeitung mit statischer Aufladung es schneller macht. Lassen Sie uns einmal eine Dummy-Datei mit dem statischen Initialisierer erstellen.
static{
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("dummy.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
}
package helloworld;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
public class TestTarget0429 implements RequestHandler<Object, Object> {
private static int count = 1;
private static String ENV_BUCKET = System.getenv("BUCKET");
private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
static{
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("dummy.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
}
public Object handleRequest(final Object input, final Context context) {
if (count == 1) {
count++;
return null;
}
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
return null;
}
}
Anzahl | Latenz | Inhalte verarbeiten |
---|---|---|
1 | 4000ms | S3 PUT-Dummy-Datei (zum ersten Mal) durch Initialisierungsverarbeitung und statische Methode |
2 | 42ms | S3 PUT (2. Mal) |
3 | 125ms | S3 PUT (3. Mal) |
4 | 42ms | S3 PUT (4. Mal) |
5 | 44ms | S3 PUT (5. Mal) |
Herzlichen Glückwunsch, das zweite und die folgenden Male sind schneller geworden!
Wird es vom ersten Mal an schneller sein, wenn es mit Provisioned Concurrency kombiniert wird, da es in Verifikation 5 schneller wurde? !!
Die Quelle ist dieselbe wie bei Überprüfung 5.
Anzahl | Latenz | Inhalte verarbeiten |
---|---|---|
1 | 80ms | Initialisierungsprozess |
2 | 370ms | S3 PUT (2. Mal) * Da es während Provisioned bereits einmal mit dem statischen Initialisierer ausgeführt wurde |
3 | 43ms | S3 PUT (3. Mal) |
4 | 72ms | S3 PUT (4. Mal) |
5 | 84ms | S3 PUT (5. Mal) |
** Ich habs gemacht! ** ** ** Das habe ich erwartet.
Die endgültige Form ist wie folgt.
package helloworld;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
public class TestTarget0429 implements RequestHandler<Object, Object> {
private static String ENV_BUCKET = System.getenv("BUCKET");
private static S3Client s3 = S3Client.builder().region(Region.AP_NORTHEAST_1).build();
static{
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("dummy.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
}
public Object handleRequest(final Object input, final Context context) {
PutObjectResponse result = s3.putObject(
PutObjectRequest.builder().bucket(ENV_BUCKET).key("filename.txt").build(),
RequestBody.fromString("contents"));
System.out.println(result);
return null;
}
}
Anzahl | Latenz | Inhalte verarbeiten |
---|---|---|
1 | 552ms | S3 PUT (2. Mal) * Da es während Provisioned bereits einmal mit dem statischen Initialisierer ausgeführt wurde |
2 | 118ms | S3 PUT (3. Mal) |
3 | 44ms | S3 PUT (4. Mal) |
4 | 86ms | S3 PUT (5. Mal) |
5 | 146ms | S3 PUT (6. Mal) |
Glückwunsch Glückwunsch.
Anscheinend lädt der Java-Klassenlader die Klasse, wenn die Klasse zum ersten Mal aufgerufen wird, und es scheint, dass das anfängliche Laden der Klasse Zeit braucht. Wenn Sie es also einmal laden und die Klasse laden, wird es beim nächsten Mal schneller.
Es wäre schön, wenn alle Klassen zuerst geladen würden, nicht wenn sie aufgerufen würden, aber ist das nicht möglich?
Die Referenzseite ist hier.
Blog der Klassenmethode https://dev.classmethod.jp/articles/report-best-practive-for-java-on-lambda/
Sitzungsmaterial bei re: Invent 2019 https://d1.awsstatic.com/events/reinvent/2019/REPEAT_1_Best_practices_for_AWS_Lambda_and_Java_SVS403-R1.pdf https://youtu.be/ddg1u5HLwg8
Andere Blogs habe ich gefunden https://pattern-match.com/blog/2020/03/14/springboot2-and-aws-lambda-provisioned-concurrency/
Recommended Posts