Behandeln Sie große JSON mit Java Lambda

Ich habe einen Artikel geschrieben, der InputStream zu einer Eingabe für Lambda macht.

Ich habe den Eingabe- / Ausgabetyp von Java Lambda ~ Stream Version ~ ausprobiert https://qiita.com/kazfuku/items/6f0f55ffa3a88d76cfaa

Der Vorteil von InputStream besteht darin, dass es mit großem JSON umgehen kann. Also habe ich versucht zu überprüfen, was es tatsächlich war.

Testdaten

Zuerst habe ich einen riesigen JSON vorbereitet. Die Daten enthalten 6000 Objekte mit Namen und Text, was ungefähr 5,9 MB entspricht, was nahe an der Eingabegrößenbeschränkung von Lambda von 6 MB liegt.

{
  "data":[
    {
      "name":"vrZPwIw3T7","text":"Ku7aQqW3WzUeiRdXnNB26iVElWdOUj8mQhvHksvN1sMmQ2fT3M8navvbTJuspda2q0bY3FWvsDoguE33tTNtoxuiHjdkUIHmylIezYGitmhJ2bbgcHhcHPzGr4eg3Ger9EijFU82Sq4WS9G5UVW62Cw1rDMNdIld2yxn1Zd3DXqE26iOf1IaBQTzEG7Pld03hkXIkAdTdeAjXlAJlGrwnQgjMh1FohW1bUAYeaLi52qLnbgQd7lZAJuOlitfGUyUbP0BjbsPflOLGQwInPjr2Mt3mG4HDokWj2JJgRkXkRYxq34AxQGNWXjlfWKViDxk2InIP6oMsir5YmTL1oO58dzmBGCoYV7e0PTGQHXJbgPJUFUoCmv3mATCEg1xhOa4IUcP7vC7dMvydS3Qt1QHteYajeCvXiW0HjuHkm2oJ61yEg6JocqLVMQ75RaU0Wjb2KvbAwQmggSel5E6mMl0BacZwBXw7OaYHkHO1p1hQup2hhNkaAkN7B8NS8QJ3oSRPQsM6QsETC3x1ErrN0jZZVqupjDvPEr9xj0fDOpqCo7XqTuSPbf3UhHQgjPyikbc2JaqeMdJf1R0RojlqWmf2STGH8HTuGJTQG3vEP04BkrNLaKNVoXE49tPyePO6EqRAKWNxVZoQmw34Xv6yGzMfOLPcSRhML0rYk1FEaBDmgGNpQIPdYjbT3MC08eEY9cHa813iWvm42XmG5LaiIt2z4IcGaWnLwCRytYJJsdqphSEhyvyOpIKM4i02t9rx3Pkt0704EhFo3SD8gVVIE2y1coFUJqy2GxVqptZrKpFv56c4SsWSPqdLqTH9Gh09Y5Cph6eOKg0JXvip1GoONZ80oBUeRudMvsl32m23fYZlG1dNFnGUZSkz2TiGP9baIfLyPWCcPZGEvVaP9FR64FW0yOLvpKyTNYXg21ZsgEkYo3tbcn3AS5R3Ai4eg5hYMaBoVAsMBK1BPZAncDoqOs97nLa2DZFyqgNSz8Asgmh"
    },
    {
      "name":"OXJIXTP9dz","text":"HkWP0PumYHQZxiGNhGWASXOPrygri7cKXs2hrWx0WaumM8OEVc9UKs2EIknzCsBmAMFRER5YNIUs5oz30LjDrjn1PsoKuh60KPOEaHnBNTt8PivYx0hIfmLoLk56ad6LSLNpUVMCP26WiPyont6OjfD1c4sxtKn3qlg6SaNSs2B1tGoReVb3pwOVvPH2BaULL5rzYyDFfAqFqo4D2UevrdoUOeXK3Ks3tav92wHnECM9pbXdsCbWyr1BNulJ5elcZm8HALPgBeX9dg0vaqpgITfz3klyYIWynzPOJC92t0vMao2tL7lr6uxuQvldWgdhlzGjYP123pdWb2h0zItg8NyyK58tCKy2t2YqtdP23fvmVpmOFygiM6kF9LvDRfnu3mz0X2SvcsQh8UqB84dHiOXwicmnI6DX47OuPXOUZc0wICql8zit6WvbEmDchKy9M74u9mPaiIxGXBy8FvLEptqqGytywwC3GGYXEpLYZlbxDycrSTtCq6PUuWoUbfsJmZT4iZSvM0aoyVKBE2l23oXhFZpM4fxyyziIVAHP9YsQbHQlvr8adtD3voumsGKcklt4mnNQclQdSLKPKSIGdUlkvhcCO4MZcEpKcmSrFU6naOYGL1geB1CuTYHYuw0x6tc7JudQAEB6IWE8xwTgPWQUM15xTsqsLrBIwZ70MGpCGW8JCw6sqJExsXi6wpJ1I3L43TUG4hJOnEPIHeXTco06zaDiSrqG3LsLuCiHIkqYui1N0fJBRJhVcn2X8dXMnQKxqhISGrnP7TeBBcAhI8qrmNK0k9EV6mECQtN2g8qaRYVqwOqC4kwzMpvPWkUnNQuUZbknLlWOKuVeh0mrjTzIxQkMShqhdt21o75h9rz0DPxvNHkS6jLw7TBprYieZwcO8iIRy1zYFedSXyVktczdEczIebkfDFmjGtDeZw5RuuFUYKDk4U3J5lpmfmf9K3G6LuPeV5soPxL54l8ZxlJGNpP1kZftZeadtms7"
    },
...

Versuchen Sie es mit der Map-Methode

Erstens ist dies eine Implementierung der Map-Methode, und die Anzahl der Daten wird gezählt.

Was ist die Kartenmethode? -> Ich habe den Eingabe- / Ausgabetyp von Java Lambda ~ Map Edition ~ ausprobiert

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Collections;
import java.util.List;
import java.util.Map;

public class MapHugeJsonFunction implements RequestHandler<Map<String, Object>, Map<String, Object>> {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @Override
    public Map<String, Object> handleRequest(Map<String, Object> event, Context context) {
        List<Map<String, Object>> data = (List<Map<String, Object>>) event.get("data");
        int count = data.size();

        return Collections.singletonMap("count", count);
    }
}

Ausführungsergebnis (≠ Kaltstart)

REPORT RequestId: ac45a98c-be93-49b5-8813-c30ae7d731c9	Duration: 2030.51 ms	Billed Duration: 2100 ms	Memory Size: 128 MB	Max Memory Used: 118 MB

Wir verwenden 118 MB, was nahe am maximalen Speicher liegt. Dies ist der Zustand, in dem sich der gesamte JSON im Speicher befindet, wenn die an handlerRequest zu übergebende Map erstellt wird. Wenn Sie mehr Geschäftslogik hinzufügen, reichen 128 MB nicht aus.

Versuchen Sie es mit der Stream-Methode

Ich habe den gleichen Prozess mit der Stream-Methode versucht. Mit dieser Implementierung können Sie den gesamten JSON verarbeiten, ohne ihn zu speichern.

Die Jackson Streaming API (https://github.com/FasterXML/jackson-databind#5-minute-tutorial-streaming-parser-generator) wird für die JSON-Analyse verwendet. In XML entspricht dies der Verwendung von SAX Parser.

Was ist die Stream-Methode? -> Ich habe den Eingabe- / Ausgabetyp von Java Lambda ~ Stream Version ~ ausprobiert

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Map;

public class StreamHugeJsonFunction implements RequestStreamHandler {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        JsonParser parser = OBJECT_MAPPER.createParser(inputStream);

        int count = 0;
        boolean inData = false;
        boolean inDataArray = false;
        JsonToken token;
        while((token = parser.nextToken()) != null) {
            if ("FIELD_NAME".equals(token.name()) && "data".equals(parser.getCurrentName())) {
                inData = true;
            }
            if (inData && "START_ARRAY".equals(token.name())) {
                inDataArray = true;
            }
            if (inDataArray && "END_ARRAY".equals(token.name())) {
                inDataArray = false;
            }
            if (inData && "END_OBJECT".equals(token.name())) {
                inData = false;
            }
            if (inDataArray && "START_OBJECT".equals(token.name())) {
                count++;
            }
        }

        Map<String, Integer> response = Collections.singletonMap("count", count);
        OBJECT_MAPPER.writeValue(outputStream, response);
    }
}

Ausführungsergebnis (≠ Kaltstart)

REPORT RequestId: 41f93e2e-e1db-4775-b296-8b280d2696f9	Duration: 871.01 ms	Billed Duration: 900 ms	Memory Size: 128 MB	Max Memory Used: 80 MB

Der Speicher wurde auf 118 MB-> 80 MB verbessert. Die Verarbeitungszeit wurde ebenfalls auf 2030 ms-> 871 ms verbessert.

Zusammenfassung

Bei Prozessen, deren Analyse von JSON umständlich ist, für die jedoch nicht alle JSON-Daten erforderlich sind, spart die Stream-Methode wahrscheinlich Verarbeitungszeit und Speicher.

Recommended Posts

Behandeln Sie große JSON mit Java Lambda
Lesen Sie JSON in Java
POST JSON in Java
Erstellen Sie JSON in Java
Üben Sie die Arbeit mit Unicode-Ersatzpaaren in Java
Verwenden Sie Lambda-Ebenen mit Java
[Java] JSON-Kommunikation mit Jackson
Adressiert, da Azure-Funktionen in Java nicht mehr funktionieren
POST Json in Java ~ HttpURLConnection ~
Json-Serialisierung / Deserialisierung in Java 1.4
Protokollaggregation und -analyse (Arbeiten mit AWS Athena in Java)
Erstellen Sie einen SlackBot mit AWS Lambda & API Gateway in Java
Java-Lambda-Ausdruck, der mit Comparator gelernt wurde
Tweak Markdown mit Java Flexmark-Java
Implementieren Sie API Gateway Lambda Authorizer in Java Lambda
Parallelitätsmethode in Java mit grundlegendem Beispiel
Versuchen Sie es mit der JSON-Format-API in Java
Lesen Sie die xlsx-Datei in Java mit Selenium
Teilen Sie eine Zeichenfolge in Java mit ". (Dot)"
Ich habe eine Lambda-Funktion in Java geschrieben und mit SAM bereitgestellt
Ich möchte für jedes Array mit Lambda-Ausdruck in Java
Interagieren Sie mit der LINE Message API mit Lambda (Java)
Lesen Sie eine Zeichenfolge in einer PDF-Datei mit Java
Erstellen Sie eine CSR mit erweiterten Informationen in Java
Überarbeitetes GUI-Tool, das 2016 mit Java8 + JavaFX erstellt wurde
Partisierung in Java
Führen Sie eine statische Code-Analyse mit Checkstyle mit Java + Gradle durch
Code zum Escapezeichen von JSON-Zeichenfolgen in Java
Änderungen in Java 11
Verwendung des Java-Frameworks mit AWS Lambda! ??
Lösung für NetBeans 8.2 funktioniert nicht in Java 9-Umgebung
JSON mit Java und Jackson Teil 2 XSS-Maßnahmen
Janken in Java
Textextraktion in Java aus PDF mit pdfbox-2.0.8
Verwendung der Java-API mit Lambda-Ausdrücken
Anders als bei JSON
Hallo Java Lambda
[Java] Lambda-Ausdruck
[JAVA] [Spring] [MyBatis] Verwenden Sie IN () mit SQL Builder
Umfangsrate in Java
Verschlüsseln / Entschlüsseln mit AES256 in PHP und Java
Java Lambda Ausdruck
FizzBuzz in Java
Behandeln Sie JSON domänenübergreifend mit Play Framework
Programmierung mit dem direkten Summentyp in Java (Nachrichten)
Kommen Sie mit Java-Containern in Cloud Run zurecht
Code, der verwendet werden soll, wenn Sie Json nur mit Standardbibliotheken in Java verarbeiten möchten
Konvertieren Sie JSON und YAML in Java (mit Jackson und SnakeYAML)
So stellen Sie Java mit Serverless Framework für AWS Lambda bereit
Fügen Sie das Bild mit der statischen Java-Methode in die JAR-Datei ein
Beachten Sie das Multithread-Problem, wenn Sie mit Java Servlet arbeiten
Implementieren Sie Singleton mit Enum schnell in Java
Ausgabe true mit if (a == 1 && a == 2 && a == 3) in Java (Invisible Identifier)
Erste Schritte mit älteren Java-Ingenieuren (Stream + Lambda)
Überprüfen Sie die Abdeckung mit Codecov in der Java + Gradle + Wercker-Konfiguration
Installieren Sie Java mit Homebrew
Interpreter-Implementierung durch Java
Machen Sie einen Blackjack mit Java
Janken App in Java