Di bawah Hood - AWS Flow Framework untuk Java

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

Di bawah Hood

Tugas

Primitif mendasar yang digunakan AWS Flow Framework untuk Java untuk mengelola eksekusi kode asinkron adalah kelas Task. Sebuah objek tipe Task mewakili pekerjaan yang harus dilakukan secara asinkron. Ketika Anda memanggil metode asinkronus, kerangka kerja menciptakan Task untuk mengeksekusi kode dalam metode itu dan menempatkannya dalam daftar untuk eksekusi di lain waktu. Demikian pula, ketika Anda memanggil Activity, sebuah Task diciptakan untuk itu. Pemanggilan metode kembali setelah ini, biasanya mengembalikan Promise<T> sebagai hasil pemanggilan di masa mendatang.

Kelas Task adalah publik dan dapat digunakan secara langsung. Sebagai contoh, kita dapat menulis ulang contoh Hello World untuk menggunakan Task bukan metode asinkronus.

@Override public void startHelloWorld(){ final Promise<String> greeting = client.getName(); new Task(greeting) { @Override protected void doExecute() throws Throwable { client.printGreeting("Hello " + greeting.get() +"!"); } }; }

Kerangka kerja ini memanggil metode doExecute() ketika semua Promise diteruskan ke konstruktor dari Task menjadi siap. Untuk detail lebih lanjut tentang kelas Task, lihat dokumentasi AWS SDK for Java.

Kerangka kerja ini juga mencakup kelas yang disebut Functor yang mewakili Task yang juga merupakan Promise<T>. Functor objek menjadi siap ketika Task selesai. Pada contoh berikut, Functor dibuat untuk mendapatkan pesan ucapan:

Promise<String> greeting = new Functor<String>() { @Override protected Promise<String> doExecute() throws Throwable { return client.getGreeting(); } }; client.printGreeting(greeting);

Urutan eksekusi

Tugas menjadi memenuhi syarat untuk dieksekusi hanya ketika semua parameter yang bertipe Promise<T>, diteruskan ke metode atau aktivitas asinkron yang sesuai, telah siap. Task yang siap untuk eksekusi secara logis dipindahkan ke antrean siap. Dengan kata lain, dijadwalkan untuk eksekusi. Kelas pekerja mengeksekusi tugas dengan menerapkan kode yang Anda tulis dalam isi metode asyinkronus, atau dengan penjadwalan tugas aktivitas di Amazon Simple Workflow Service (AWS) jika ada metode aktivitas.

Saat tugas dijalankan dan menghasilkan hasil, maka itu menyebabkan tugas lain menjadi siap dan eksekusi program terus bergerak maju. Cara kerangka kerja menjalankan tugas penting untuk memahami urutannya di mana kode asinkron Anda dijalankan. Kode yang muncul secara berurutan dalam program Anda mungkin tidak benar-benar mengeksekusi dalam urutan itu.

Promise<String> name = getUserName(); printHelloName(name); printHelloWorld(); System.out.println("Hello, Amazon!"); @Asynchronous private Promise<String> getUserName(){ return Promise.asPromise("Bob"); } @Asynchronous private void printHelloName(Promise<String> name){ System.out.println("Hello, " + name.get() + "!"); } @Asynchronous private void printHelloWorld(){ System.out.println("Hello, World!"); }

Kode dalam daftar di atas akan mencetak berikut:

Hello, Amazon! Hello, World! Hello, Bob

Ini mungkin bukan apa yang Anda harapkan tetapi dapat dengan mudah dijelaskan dengan memikirkan bagaimana tugas-tugas untuk metode asinkronus dieksekusi:

  1. Panggilan ke getUserName membuat Task. Mari kita sebut saja Task1. Karena getUserName tidak mengambil parameter apapun, Task1 segera dimasukkan ke dalam antrean siap.

  2. Selanjutnya, panggilan ke printHelloName membuat Task yang perlu menunggu hasil dari getUserName. Mari kita sebut saja Task2. Karena nilai yang diperlukan belum siap, Task2 dimasukkan ke dalam daftar tunggu.

  3. Kemudian tugas untuk printHelloWorld dibuat dan ditambahkan ke antrean siap. Mari kita sebut saja Task3.

  4. Pernyataan println kemudian mencetak "Hello, Amazon!" ke konsol.

  5. Pada titik ini, Task1 dan Task3 berada dalam antrean siap dan Task2 ada di daftar tunggu.

  6. Pekerja mengeksekusi Task1, dan hasilnya membuat Task2 siap. Task2 akan ditambahkan ke antrean siap di belakang Task3.

  7. Task3 dan Task2 kemudian dieksekusi dalam urutan itu.

Pelaksanaan kegiatan mengikuti pola yang sama. Ketika Anda memanggil metode pada klien aktivitas, itu menciptakan Task yang, setelah eksekusi, menjadwalkan kegiatan di Amazon SWF.

Kerangka kerja ini bergantung pada fitur seperti generasi kode dan proxy dinamis untuk menyuntikkan logika untuk mengonversi panggilan metode ke pemanggilan aktivitas dan tugas asinkron dalam program Anda.

Eksekusi alur kerja

Eksekusi implementasi alur kerja juga dikelola oleh kelas pekerja. Saat Anda memanggil metode pada klien alur kerja, itu akan memanggil Amazon SWF untuk membuat instans alur kerja. Tugas di Amazon SWF tidak boleh disamakan dengan tugas dalam kerangka kerja. Tugas di Amazon SWF adalah tugas aktivitas atau tugas keputusan. Pelaksanaan tugas aktivitas sederhana. Kelas pekerja aktivitas menerima tugas aktivitas dari Amazon SWF, memanggil metode aktivitas yang sesuai dalam pelaksanaan Anda, dan mengembalikan hasilnya ke Amazon SWF.

Eksekusi tugas keputusan lebih terlibat. Pekerja alur kerja menerima tugas keputusan dari Amazon SWF. Tugas keputusan secara efektif merupakan permintaan yang menanyakan logika alur kerja apa yang harus dilakukan selanjutnya. Tugas keputusan pertama dibuat untuk contoh alur kerja saat dimulai melalui klien alur kerja. Setelah menerima tugas keputusan ini, kerangka kerja mulai mengeksekusi kode dalam metode alur kerja dijelaskan dengan @Execute. Metode ini mengeksekusi logika koordinasi yang menjadwalkan kegiatan. Saat status instans alur kerja berubah—misalnya, saat aktivitas selesai—tugas keputusan lebih lanjut dijadwalkan. Pada titik ini, logika alur kerja dapat memutuskan untuk mengambil tindakan berdasarkan hasil aktivitas; misalnya, mungkin memutuskan untuk menjadwalkan aktivitas lain.

Kerangka kerja menyembunyikan semua detail ini dari developer dengan menerjemahkan tugas keputusan secara mulus ke logika alur kerja. Dari sudut pandang developer, kode terlihat seperti program biasa. Secara rahasia, kerangka kerja memetakannya ke panggilan ke Amazon SWF dan tugas keputusan menggunakan riwayat yang dikelola oleh Amazon SWF. Ketika tugas keputusan tiba, kerangka kerja memutar ulang eksekusi program memasukkan hasil kegiatan yang diselesaikan sejauh ini. Metode dan aktivitas asinkronus yang menunggu hasil ini tidak diblokir, dan eksekusi program bergerak maju.

Eksekusi contoh alur kerja pemrosesan gambar dan riwayat terkait ditampilkan dalam tabel berikut.

Eksekusi alur kerja thumbnail
Eksekusi program alur kerja Riwayat dikelola oleh Amazon SWF
Eksekusi awal
  1. Loop pengiriman

  2. getImageUrls

  3. downloadImage

  4. createThumbnail (tugas dalam antrean tunggu)

  5. uploadImage (tugas dalam antrean tunggu)

  6. <iterasi berikutnya dari loop>

  1. Instans alur kerja dimulai, id="1"

  2. downloadImage terjadwal

Memutar ulang
  1. Loop pengiriman

  2. getImageUrls

  3. gambar downloadImage path="foo"

  4. createThumbnail

  5. uploadImage (tugas dalam antrean tunggu)

  6. <iterasi berikutnya dari loop>

  1. Instans alur kerja dimulai, id="1"

  2. downloadImage terjadwal

  3. downloadImage selesai, return="foo"

  4. createThumbnail terjadwal

Memutar ulang
  1. Loop pengiriman

  2. getImageUrls

  3. gambar downloadImage path="foo"

  4. createThumbnail thumbnail path="bar"

  5. uploadImage

  6. <iterasi berikutnya dari loop>

  1. Instans alur kerja dimulai, id="1"

  2. downloadImage terjadwal

  3. downloadImage selesai, return="foo"

  4. createThumbnail terjadwal

  5. createThumbnail selesai, return="bar"

  6. uploadImage terjadwal

Memutar ulang
  1. Loop pengiriman

  2. getImageUrls

  3. gambar downloadImage path="foo"

  4. createThumbnail thumbnail path="bar"

  5. uploadImage

  6. <iterasi berikutnya dari loop>

  1. Instans alur kerja dimulai, id="1"

  2. downloadImage terjadwal

  3. downloadImage selesai, return="foo"

  4. createThumbnail terjadwal

  5. createThumbnail selesai, return="bar"

  6. uploadImage terjadwal

  7. uploadImage selesai

    ...

Ketika panggilan ke processImage dibuat, kerangka kerja menciptakan instans alur kerja baru di Amazon SWF. Ini adalah catatan tahan lama dari instans alur kerja yang sedang dimulai. Program ini mengeksekusi sampai panggilan ke kegiatan downloadImage, yang meminta Amazon SWF untuk menjadwalkan suatu kegiatan. Alur kerja mengeksekusi lebih jauh dan membuat tugas untuk kegiatan berikutnya, tetapi tidak dapat dijalankan sampai kegiatan downloadImage selesai; maka, episode putar ulang ini berakhir. Amazon SWF mengirimkan tugas untuk kegiatan downloadImage untuk dieksekusi, dan setelah selesai, catatan dibuat dalam riwayat bersama dengan hasilnya. Alur kerja sekarang siap untuk bergerak maju dan tugas keputusan dihasilkan oleh Amazon SWF. Kerangka kerja menerima tugas keputusan dan replay alur kerja memasukkan hasil gambar download seperti yang tercatat dalam riwayat. Ini membuka blokir tugas untuk createThumbnail, dan pelaksanaan program berlanjut lebih jauh dengan penjadwalan tugas aktivitas createThumbnail di Amazon SWF. Proses yang sama berulang untuk uploadImage. Pelaksanaan program berlanjut dengan cara ini sampai alur kerja telah memproses semua gambar dan tidak ada tugas yang tertunda. Karena tidak ada status eksekusi disimpan secara lokal, setiap tugas keputusan mungkin berpotensi dieksekusi pada mesin yang berbeda. Hal ini mengizinkan Anda untuk dengan mudah menulis program yang toleran kesalahan dan dapat diskalakan.

Nondeterminisme

Karena kerangka kerja bergantung pada replay, penting bahwa kode orkestrasi (semua kode alur kerja dengan pengecualian implementasi aktivitas) menjadi deterministik. Misalnya, aliran kontrol dalam program Anda tidak harus bergantung pada nomor acak atau waktu saat ini. Karena hal-hal ini akan berubah di antara pemanggilan, pemutaran ulang mungkin tidak mengikuti jalur yang sama melalui logika orkestrasi. Hal ini akan menyebabkan hasil yang tidak terduga atau kesalahan. Kerangka kerja ini menyediakan WorkflowClock yang dapat Anda gunakan untuk mendapatkan waktu saat ini dengan cara deterministik. Lihat bagian di Konteks Eksekusi untuk lebih detailnya.

catatan

Pengkabelan pegas yang salah dari objek implementasi alur kerja juga dapat menyebabkan nondeterminisme. Alur kerja implementasi benas serta beans yang mereka andalkan harus berada dalam lingkup alur kerja (WorkflowScope). Misalnya, kabel alur kerja implementasi beans ke beans yang membuat status dan dalam konteks global akan menghasilkan perilaku tak terduga. Lihat Integrasi Spring bagian untuk detail lebih lanjut.