Tentukan penangan fungsi Lambda di Java - AWS Lambda

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Tentukan penangan fungsi Lambda di Java

Handler fungsi Lambda Anda adalah metode dalam kode fungsi Anda yang memproses peristiwa. Saat fungsi Anda diaktifkan, Lambda menjalankan metode handler. Fungsi Anda berjalan sampai handler mengembalikan respons, keluar, atau waktu habis.

GitHub Repo untuk panduan ini menyediakan easy-to-deploy contoh aplikasi yang mendemonstrasikan berbagai jenis handler. Untuk detailnya, lihat akhir topik ini.

Contoh handler: Java 17 runtime

Dalam contoh Java 17 berikut, kelas bernama HandlerIntegerJava17 mendefinisikan metode handler bernama. handleRequest Metode handler mengambil input berikut:

  • AnIntegerRecord, yang merupakan catatan Java kustom yang mewakili data peristiwa. Dalam contoh ini, kami mendefinisikan IntegerRecord sebagai berikut:

    record IntegerRecord(int x, int y, String message) { }
  • Sebuah objek konteks, yang menyediakan metode dan properti yang memberikan informasi tentang pemanggilan, fungsi, dan lingkungan eksekusi.

Misalkan kita ingin menulis fungsi yang mencatat message dari inputIntegerRecord, dan mengembalikan jumlah x dany. Berikut ini adalah kode fungsi:

contoh HandlerIntegerJava17.java
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; // Handler value: example.HandlerInteger public class HandlerIntegerJava17 implements RequestHandler<IntegerRecord, Integer>{ @Override /* * Takes in an InputRecord, which contains two integers and a String. * Logs the String, then returns the sum of the two Integers. */ public Integer handleRequest(IntegerRecord event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("String found: " + event.message()); return event.x() + event.y(); } } record IntegerRecord(int x, int y, String message) { }

Anda menentukan metode mana yang ingin Lambda panggil dengan menyetel parameter handler pada konfigurasi fungsi Anda. Anda dapat mengekspresikan hander dalam format berikut:

  • package.Class::method – Format penuh. Sebagai contoh: example.Handler::handleRequest.

  • package.Class— Format singkatan untuk kelas yang mengimplementasikan antarmuka handler. Sebagai contoh: example.Handler.

Saat Lambda memanggil handler Anda, runtime Lambda menerima peristiwa sebagai string yang JSON diformat -dan mengubahnya menjadi objek. Untuk contoh sebelumnya, contoh peristiwa mungkin terlihat seperti berikut:

contoh event.json
{ "x": 1, "y": 20, "message": "Hello World!" }

Anda dapat menyimpan file ini dan menguji fungsi Anda secara lokal dengan perintah AWS Command Line Interface (CLI) berikut:

aws lambda invoke --function-name function_name --payload file://event.json out.json

Contoh handler: Java 11 runtime dan di bawahnya

Lambda mendukung catatan di Java 17 dan runtime yang lebih baru. Di semua runtime Java, Anda dapat menggunakan kelas untuk mewakili data peristiwa. Contoh berikut mengambil daftar bilangan bulat dan objek konteks sebagai masukan, dan mengembalikan jumlah semua bilangan bulat dalam daftar.

Dalam contoh berikut, kelas bernama Handler menentukan metode handler bernama handleRequest. Metode handler mengambil peristiwa dan objek konteks sebagai input dan mengembalikan string.

contoh HandlerList.jawa
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.List; // Handler value: example.HandlerList public class HandlerList implements RequestHandler<List<Integer>, Integer>{ @Override /* * Takes a list of Integers and returns its sum. */ public Integer handleRequest(List<Integer> event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("EVENT TYPE: " + event.getClass().toString()); return event.stream().mapToInt(Integer::intValue).sum(); } }

Untuk contoh selengkapnya, lihat Contoh kode handler.

Kode inisialisasi

Lambda menjalankan kode statis Anda dan konstruktor kelas selama fase inisialisasi sebelum menjalankan fungsi Anda untuk pertama kalinya. Sumber daya yang dibuat selama inisialisasi tetap berada di memori di antara pemanggilan dan dapat digunakan kembali oleh penangan ribuan kali. Dengan demikian, Anda dapat menambahkan kode inisialisasi di luar metode handler utama Anda untuk menghemat waktu komputasi dan menggunakan kembali sumber daya di beberapa pemanggilan.

Dalam contoh berikut, kode inisialisasi klien berada di luar metode handler utama. Runtime menginisialisasi klien sebelum fungsi menyajikan acara pertamanya. Peristiwa selanjutnya jauh lebih cepat karena Lambda tidak perlu menginisialisasi klien lagi.

contoh Handler.java
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.Map; import software.amazon.awssdk.services.lambda.LambdaClient; import software.amazon.awssdk.services.lambda.model.GetAccountSettingsResponse; import software.amazon.awssdk.services.lambda.model.LambdaException; // Handler value: example.Handler public class Handler implements RequestHandler<Map<String,String>, String> { private static final LambdaClient lambdaClient = LambdaClient.builder().build(); @Override public String handleRequest(Map<String,String> event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("Handler invoked"); GetAccountSettingsResponse response = null; try { response = lambdaClient.getAccountSettings(); } catch(LambdaException e) { logger.log(e.getMessage()); } return response != null ? "Total code size for your account is " + response.accountLimit().totalCodeSize() + " bytes" : "Error"; } }

Memilih tipe input dan output

Anda menentukan jenis objek yang peristiwa petakan ke tanda tangan metode handler. Dalam contoh sebelumnya, runtime Java mendeserialisasi acara menjadi tipe yang mengimplementasikan antarmuka. Map<String,String> String-to-stringpeta berfungsi untuk acara datar seperti berikut:

contoh Event.json – Data cuaca
{ "temperatureK": 281, "windKmh": -3, "humidityPct": 0.55, "pressureHPa": 1020 }

Namun, nilai setiap bidang harus berupa string atau angka. Jika kegiatan mencakup bidang yang memiliki objek sebagai nilai, runtime tidak dapat mendeserialisasi dan mengembalikan kesalahan.

Pilih jenis input yang berfungsi dengan data peristiwa yang diproses oleh fungsi Anda. Anda dapat menggunakan jenis dasar, jenis generik, atau jenis yang didefinisikan dengan baik.

Jenis input
  • Integer, Long, Double, dll. — Peristiwa tersebut merupakan nomor tanpa format tambahan—misalnya, 3.5. Runtime mengonversi nilai ke dalam objek dengan tipe yang ditentukan.

  • String— Acara ini adalah JSON string, termasuk kutipan—misalnya,. "My string." Runtime mengonversi nilai (tanpa tanda kutip) menjadi objek String.

  • Type, Map<String,Type> dll. Event adalah sebuah JSON obyek. Runtime mendeserialisasikannya menjadi objek dengan jenis atau antarmuka yang ditentukan.

  • List<Integer>, List<String>, List<Object>, dll. — Acara ini adalah JSON array. Runtime mendeserialisasikannya menjadi objek dengan jenis atau antarmuka yang ditentukan.

  • InputStream- Acara ini adalah JSON jenis apa pun. Runtime menyampaikan aliran byte dokumen ke handler tanpa modifikasi. Anda mendeserialisasi input dan menuliskan output ke aliran output.

  • Jenis pustaka — Untuk acara yang dikirim oleh AWS layanan, gunakan tipe di aws-lambda-java-eventsperpustakaan.

Jika Anda menentukan jenis masukan Anda sendiri, itu harus berupa objek Java lama yang dapat diubah dan dapat diubah, dengan konstruktor dan properti default untuk setiap bidang dalam acara tersebut. POJO Kunci dalam peristiwa yang tidak memetakan ke properti serta properti yang tidak disertakan ke dalam peristiwa akan dijatuhkan tanpa kesalahan.

Tipe output dapat menjadi objek atau void. Runtime membuat serial nilai-nilai yang kembali ke dalam teks. Jika output adalah objek dengan bidang, runtime serialisasikannya ke dalam dokumen. JSON Jika ini adalah jenis yang membungkus nilai primitif, runtime mengembalikan representasi teks dari nilai tersebut.

Antarmuka handler

aws-lambda-java-corePustaka mendefinisikan dua antarmuka untuk metode handler. Gunakan antarmuka yang disediakan untuk menyederhanakan konfigurasi handler dan memvalidasi tanda tangan metode handler pada waktu kompilasi.

Antarmuka RequestHandler adalah jenis generik yang mengambil dua parameter: jenis input dan jenis output. Kedua jenis tersebut harus berupa objek. Saat Anda menggunakan antarmuka ini, runtime Java akan mendeserialisasi peristiwa menjadi objek dengan jenis input, dan menserialisasi output menjadi teks. Gunakan antarmuka ini saat serialisasi bawaan bekerja dengan tipe input dan output Anda.

contoh Handler.java – Antarmuka handler
// Handler value: example.Handler public class Handler implements RequestHandler<Map<String,String>, String>{ @Override public String handleRequest(Map<String,String> event, Context context)

Untuk menggunakan serialisasi Anda sendiri, terapkan antarmuka RequestStreamHandler. Dengan antarmuka ini, Lambda melewatkan aliran input dan aliran output ke handler Anda. Handler membaca byte dari aliran input, menuliskan aliran output, dan mengembalikan pembatalan.

Contoh Java 21 berikut menunjukkan bagaimana Anda dapat menggunakan fungsi Lambda untuk memproses pesanan. Contoh ini menggunakan jenis pembaca dan penulis buffer untuk bekerja dengan aliran input dan output, dan menunjukkan bagaimana Anda dapat menentukan catatan Java kustom untuk digunakan dalam fungsi Anda.

contoh HandlerStream.jawa
import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; public class HandlerStream implements RequestStreamHandler { private static final ObjectMapper objectMapper = new ObjectMapper(); @Override public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { Order order = objectMapper.readValue(input, Order.class); processOrder(order); OrderAccepted orderAccepted = new OrderAccepted(order.orderId); objectMapper.writeValue(output, orderAccepted); } private void processOrder(Order order) { // business logic } public record Order(@JsonProperty("orderId") String orderId, @JsonProperty("items") List<Item> items) { } public record Item(@JsonProperty("name") String name, @JsonProperty("quantity") Integer quantity) { } public record OrderAccepted(@JsonProperty("orderId") String orderId) { } }

Praktik terbaik kode untuk fungsi Java Lambda

Patuhi panduan dalam daftar berikut untuk menggunakan praktik pengkodean terbaik saat membangun fungsi Lambda Anda:

  • Pisahkan handler Lambda dari logika inti Anda. Ini memungkinkan Anda untuk membuat fungsi yang lebih dapat teruji.

  • Kontrol dependensi dalam paket penerapan fungsi Anda. Lingkungan AWS Lambda eksekusi berisi sejumlah pustaka. Untuk mengaktifkan serangkaian fitur dan pembaruan keamanan terbaru, Lambda akan memperbarui pustaka ini secara berkala. Pembaruan ini dapat memberikan perubahan kecil pada perilaku fungsi Lambda Anda. Untuk memiliki kendali penuh atas dependensi yang digunakan fungsi Anda, kemas semua dependensi Anda dengan paket deployment Anda.

  • Minimalkan kompleksitas dependensi Anda. Utamakan memilih kerangka kerja lebih sederhana yang cepat dimuat dalam memulai lingkungan eksekusi. Misalnya, utamakan kerangka kerja injeksi dependensi Java (IoC) yang lebih sederhana seperti Dagger atau Guice, daripada yang lebih kompleks seperti Spring Framework.

  • Minimalkan ukuran paket penerapan Anda sesuai kebutuhan runtime-nya. Ini akan mengurangi jumlah waktu yang dibutuhkan untuk mengunduh dan membongkar paket deployment Anda sebelum invokasi. Untuk fungsi yang ditulis di Java, hindari mengunggah seluruh AWS SDK pustaka sebagai bagian dari paket penerapan Anda. Sebagai gantinya, secara selektif bergantung pada modul yang mengambil komponen yang SDK Anda butuhkan (misalnya DynamoDB, modul Amazon SDK S3, dan pustaka inti Lambda).

  • Manfaatkan penggunaan kembali lingkungan eksekusi untuk meningkatkan kinerja fungsi Anda. Inisialisasi SDK klien dan koneksi database di luar fungsi handler, dan cache aset statis secara lokal di direktori. /tmp Invokasi selanjutnya yang diproses oleh instans yang sama dari fungsi Anda dapat menggunakan kembali sumber daya ini. Ini menghemat biaya dengan mengurangi waktu pengoperasian fungsi.

    Untuk menghindari potensi kebocoran data di seluruh invokasi, jangan menggunakan lingkungan eksekusi untuk menyimpan data pengguna, peristiwa, atau informasi lainnya implikasi keamanan. Jika fungsi Anda bergantung pada status yang dapat disenyapkan yang tidak dapat disimpan dalam memori di dalam handler, pertimbangkan untuk membuat fungsi terpisah atau versi terpisah dari fungsi untuk setiap pengguna.

  • Gunakan arahan keep-alive untuk mempertahankan koneksi yang persisten. Lambda membersihkan koneksi idle dari waktu ke waktu. Mencoba menggunakan ulang koneksi idle saat mengidentifikasi suatu fungsi akan menyebabkan kesalahan koneksi. Untuk mempertahankan koneksi yang persisten, gunakan arahan tetap aktif yang berkaitan dengan runtime Anda. Sebagai contoh, lihat Menggunakan Kembali Koneksi dengan Keep-Alive di Node.js.

  • Gunakan variabel lingkungan untuk meneruskan parameter operasional ke fungsi Anda. Misalnya, jika Anda ingin menulis ke bucket Amazon S3 alih-alih melakukan hard-coding nama bucket yang Anda tulis, konfigurasikan nama bucket sebagai variabel lingkungan.

  • Hindari menggunakan pemanggilan rekursif dalam fungsi Lambda Anda, di mana fungsi memanggil dirinya sendiri atau memulai proses yang dapat memanggil fungsi lagi. Hal ini dapat menyebabkan volume invokasi fungsi yang tidak diinginkan dan peningkatan biaya. Jika Anda melihat volume pemanggilan yang tidak diinginkan, setel konkurensi fungsi cadangan untuk 0 segera membatasi semua pemanggilan ke fungsi, saat Anda memperbarui kode.

  • Jangan gunakan non-dokumen, non-publik APIs dalam kode fungsi Lambda Anda. Untuk runtime AWS Lambda terkelola, Lambda secara berkala menerapkan pembaruan keamanan dan fungsional ke internal Lambda. APIs APIPembaruan internal ini mungkin tidak kompatibel ke belakang, yang menyebabkan konsekuensi yang tidak diinginkan seperti kegagalan pemanggilan jika fungsi Anda memiliki ketergantungan pada non-publik ini. APIs Lihat APIreferensi untuk daftar yang tersedia APIs untuk umum.

  • Tulis kode idempoten. Menulis kode idempoten untuk fungsi Anda memastikan bahwa peristiwa duplikat ditangani dengan cara yang sama. Kode Anda harus memvalidasi peristiwa dengan benar dan menangani peristiwa duplikat dengan anggun. Untuk informasi selengkapnya, lihat Bagaimana cara membuat fungsi Lambda saya idempoten? .

  • Hindari menggunakan DNS cache Java. Fungsi Lambda sudah cache DNS respons. Jika Anda menggunakan DNS cache lain, maka Anda mungkin mengalami batas waktu koneksi.

    java.util.logging.LoggerKelas secara tidak langsung dapat mengaktifkan JVM DNS cache. Untuk mengganti pengaturan default, setel networkaddress.cache.ttl ke 0 sebelum menginisialisasi. logger Contoh:

    public class MyHandler { // first set TTL property static{ java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); } // then instantiate logger var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class); }
  • Kurangi waktu yang dibutuhkan Lambda untuk membuka paket deployment yang ditulis di Java dengan meletakkan file .jar dependensi Anda dalam direktori/lib terpisah. Ini lebih cepat daripada memasukkan semua kode fungsi Anda dalam satu wadah yang berisi sejumlah besar file .class. Untuk instruksi, lihat Menyebarkan fungsi Java Lambda JAR dengan.zip atau arsip file.

Kode handler sampel

GitHub Repositori untuk panduan ini mencakup contoh aplikasi yang menunjukkan penggunaan berbagai jenis handler dan antarmuka. Setiap contoh aplikasi menyertakan skrip untuk penyebaran dan pembersihan yang mudah, AWS SAM templat, dan sumber daya pendukung.

Sampel aplikasi Lambda di Java
  • java17-examples - Fungsi Java yang menunjukkan bagaimana menggunakan catatan Java untuk mewakili objek data peristiwa masukan.

  • java-basic - Kumpulan fungsi Java minimal dengan pengujian unit dan konfigurasi logging variabel.

  • java-events - Kumpulan fungsi Java yang berisi kode kerangka untuk cara menangani peristiwa dari berbagai layanan seperti Amazon GatewayAPI, Amazon, dan Amazon SQS Kinesis. Fungsi-fungsi ini menggunakan versi terbaru dari aws-lambda-java-eventsperpustakaan (3.0.0 dan yang lebih baru). Contoh-contoh ini tidak memerlukan ketergantungan AWS SDK sebagai.

  • s3-java — Fungsi Java yang memproses peristiwa notifikasi dari Amazon S3 dan menggunakan Java Class Library JCL () untuk membuat thumbnail dari file gambar yang diunggah.

  • Gunakan API Gateway untuk menjalankan fungsi Lambda — Fungsi Java yang memindai tabel Amazon DynamoDB yang berisi informasi karyawan. Kemudian menggunakan Amazon Simple Notification Service untuk mengirim pesan teks kepada karyawan yang merayakan ulang tahun kerja mereka. Contoh ini menggunakan API Gateway untuk memanggil fungsi.

s3-javaAplikasi java-events dan mengambil acara AWS layanan sebagai input dan mengembalikan string. Aplikasi java-basic meliputi beberapa jenis handler:

Untuk menguji jenis handler yang berbeda, cukup ubah nilai handler di template. AWS SAM Untuk instruksi terperinci, lihat file readme aplikasi sampel.