Ulangi setelah saya:
REST dan acara asinkron bukanlah alternatif. Mereka sepenuhnya ortogonal.
Anda dapat memiliki satu, atau yang lain, atau keduanya, atau tidak sama sekali. Mereka alat yang sama sekali berbeda untuk domain masalah yang sama sekali berbeda. Faktanya, komunikasi permintaan-respons untuk keperluan umum benar-benar mampu menjadi tidak sinkron, berdasarkan peristiwa, dan toleran terhadap kesalahan .
Sebagai contoh sepele, protokol AMQP mengirim pesan melalui koneksi TCP. Dalam TCP, setiap paket harus diakui oleh penerima . Jika pengirim paket tidak menerima ACK untuk paket itu, ia terus mengirim ulang paket itu sampai ACK atau sampai lapisan aplikasi "menyerah" dan meninggalkan koneksi. Ini jelas merupakan model permintaan-respons non-toleran karena setiap "permintaan pengiriman paket" harus memiliki "paket respons respons" yang menyertainya, dan kegagalan untuk merespons mengakibatkan seluruh koneksi gagal. Namun AMQP, protokol standar dan diadopsi secara luas untuk pesan toleransi kesalahan asinkron, dikomunikasikan melalui TCP! Apa yang menyebabkannya?
Konsep inti yang dimainkan di sini adalah bahwa pesan yang toleran-bebas-skal yang dapat diskalakan ditentukan oleh pesan apa yang Anda kirim , bukan bagaimana Anda mengirimnya . Dengan kata lain, kopling longgar didefinisikan pada lapisan aplikasi .
Mari kita lihat dua pihak yang berkomunikasi baik secara langsung dengan RESTful HTTP atau secara tidak langsung dengan broker pesan AMQP. Misalkan Pihak A ingin mengunggah gambar JPEG ke Pihak B yang akan menajamkan, mengompres, atau meningkatkan gambar. Pihak A tidak memerlukan gambar yang diproses segera, tetapi memang membutuhkan referensi untuk itu untuk penggunaan dan pengambilan di masa depan. Inilah salah satu cara yang mungkin berlaku di REST:
- Pihak A mengirim
POST
pesan permintaan HTTP ke Pihak B denganContent-Type: image/jpeg
- Pihak B memproses gambar (untuk waktu yang lama jika itu besar) sementara Pihak A menunggu, mungkin melakukan hal-hal lain
- Pihak B mengirim
201 Created
pesan tanggapan HTTP ke Pihak A dengan Content-Location: <url>
tajuk yang menautkan ke gambar yang diproses
- Pihak A menganggap pekerjaannya dilakukan karena sekarang memiliki referensi ke gambar yang diproses
- Suatu saat di masa depan ketika Pihak A membutuhkan gambar yang diproses, itu MENDAPATKANnya menggunakan tautan dari
Content-Location
header sebelumnya
The 201 Created
kode respon memberitahu klien bahwa tidak hanya permintaan mereka berhasil, itu juga menciptakan sumber daya baru. Dalam respons 201, Content-Location
header adalah tautan ke sumber daya yang dibuat. Ini ditentukan dalam RFC 7231 Bagian 6.3.2 dan 3.1.4.2.
Sekarang, mari kita lihat bagaimana interaksi ini bekerja melalui protokol RPC hipotetis di atas AMQP:
- Pihak A mengirim broker pesan AMQP (sebut saja Messenger) pesan yang berisi gambar dan instruksi untuk merutekannya ke Pihak B untuk diproses, kemudian menanggapi Pihak A dengan alamat semacam alamat untuk gambar.
- Pihak A menunggu, mungkin melakukan hal-hal lain
- Messenger mengirimkan pesan asli Pihak A ke Pihak B
- Pihak B memproses pesan tersebut
- Pihak B mengirim pesan kepada Messenger yang berisi alamat untuk gambar yang diproses dan instruksi untuk merutekan pesan itu ke Pihak A
- Messenger mengirim Pihak A pesan dari Pihak B yang berisi alamat gambar yang diproses
- Pihak A menganggap pekerjaannya dilakukan karena sekarang memiliki referensi ke gambar yang diproses
- Suatu saat di masa depan ketika Pihak A membutuhkan gambar, itu mengambil gambar menggunakan alamat (mungkin dengan mengirim pesan ke pihak lain)
Apakah Anda melihat masalahnya di sini? Dalam kedua kasus, Pihak A tidak bisa mendapatkan alamat gambar sampai setelah Pihak B memproses gambar . Namun Pihak A tidak membutuhkan gambar segera dan, dengan semua hak, tidak peduli jika pemrosesan selesai!
Kami dapat memperbaiki ini dengan mudah dalam kasus AMQP dengan meminta Pihak B memberi tahu A bahwa B menerima gambar untuk diproses, memberikan A alamat tempat gambar akan berada setelah pemrosesan selesai. Kemudian Pihak B dapat mengirim pesan pada suatu waktu di masa depan yang mengindikasikan pemrosesan gambar selesai. Olahpesan AMQP untuk menyelamatkan!
Kecuali tebak: Anda dapat mencapai hal yang sama dengan REST . Dalam contoh AMQP kami mengubah pesan "inilah gambar yang diproses" menjadi "gambar sedang diproses, Anda bisa mendapatkannya nanti". Untuk melakukannya di RESTful HTTP, kami akan menggunakan 202 Accepted
kode dan Content-Location
lagi:
- Pihak A mengirim
POST
pesan HTTP ke Pihak B denganContent-Type: image/jpeg
- Pihak B segera mengirim kembali
202 Accepted
respons yang berisi semacam konten "operasi asinkron" yang menjelaskan apakah pemrosesan selesai dan di mana gambar akan tersedia ketika selesai diproses. Termasuk juga Content-Location: <link>
tajuk yang, dalam 202 Accepted
respons, adalah tautan ke sumber daya yang diwakili oleh apa pun badan respons. Dalam hal ini, itu artinya itu adalah tautan ke operasi asinkron kami!
- Pihak A menganggap pekerjaannya dilakukan karena sekarang memiliki referensi ke gambar yang diproses
- Suatu saat di masa depan ketika Pihak A membutuhkan gambar yang diproses, pertama-tama MENDAPATKAN sumber daya operasi async yang ditautkan ke dalam
Content-Location
header untuk menentukan apakah pemrosesan selesai. Jika demikian, Pihak A kemudian menggunakan tautan dalam operasi async itu sendiri untuk MENDAPATKAN gambar yang diproses.
Satu-satunya perbedaan di sini adalah bahwa dalam model AMQP, Pihak B memberi tahu Pihak A ketika pemrosesan gambar dilakukan. Tetapi dalam model REST, Pihak A memeriksa apakah pemrosesan dilakukan sebelum benar-benar membutuhkan gambar. Pendekatan-pendekatan ini dapat diukur secara ekuivalen . Ketika sistem semakin besar, jumlah pesan yang dikirim baik dalam async AMQP dan asest strategi REST meningkat dengan kompleksitas asimptotik yang setara. Satu-satunya perbedaan adalah klien mengirim pesan tambahan, bukan server.
Tetapi pendekatan REST memiliki beberapa trik lagi: penemuan dinamis dan negosiasi protokol . Pertimbangkan bagaimana interaksi REST sinkronisasi dan async dimulai. Pihak A mengirim permintaan yang sama persis kepada Pihak B, dengan satu-satunya perbedaan adalah jenis pesan keberhasilan tertentu yang direspon oleh Pihak B. Bagaimana jika Pihak A ingin memilih apakah pemrosesan gambar sinkron atau asinkron? Bagaimana jika Pihak A tidak tahu apakah Pihak B bahkan mampu memproses async?
Nah, HTTP sebenarnya sudah memiliki protokol standar untuk ini! Ini disebut HTTP Preferences, khususnya respond-async
preferensi RFC 7240 Bagian 4.1. Jika Pihak A menginginkan respons yang tidak sinkron, ia menyertakan Prefer: respond-async
header dengan permintaan POST awalnya. Jika Pihak B memutuskan untuk menghormati permintaan ini, ia mengirim kembali 202 Accepted
respons yang mencakup a Preference-Applied: respond-async
. Jika tidak, Pihak B mengabaikan Prefer
header dan mengirim kembali 201 Created
seperti biasanya.
Hal ini memungkinkan Pihak A untuk bernegosiasi dengan server, secara dinamis beradaptasi dengan implementasi pemrosesan gambar apa pun yang kebetulan sedang diajaknya bicara. Lebih lanjut, penggunaan tautan eksplisit berarti Pihak A tidak perlu tahu tentang pihak lain selain B: tidak ada broker pesan AMQP, tidak ada Pihak C misterius yang tahu bagaimana mengubah alamat gambar menjadi data gambar, tanpa B-Async kedua pihak jika permintaan sinkron dan asinkron perlu dibuat, dll. Ini hanya menggambarkan apa yang dibutuhkan, apa yang secara opsional suka, dan kemudian bereaksi terhadap kode status, konten respons, dan tautan. MenambahkanCache-Control
header untuk instruksi eksplisit tentang kapan menyimpan salinan data lokal, dan sekarang server dapat bernegosiasi dengan klien yang sumber dayanya dapat disimpan oleh salinan lokal (atau bahkan offline!). Ini adalah bagaimana Anda membangun microservices toleran-longgar yang digabungkan dalam REST.
UserCreated
acara (misalnya, duplikat nama pengguna atau email atau pemadaman database)./users/
titik akhir, dan memungkinkan sistem untuk menerbitkan acara jika berhasil, dan menanggapi permintaan dengan entitas baruDengan sistem sumber peristiwa, aspek asinkron biasanya ikut bermain ketika sesuatu yang mewakili keadaan, mungkin database, atau tampilan agregat dari beberapa data, diubah. Dengan menggunakan contoh Anda, panggilan ke GET / api / pengguna dapat dengan mudah mengembalikan respons dari layanan yang memiliki representasi terkini dari daftar pengguna dalam sistem. Dalam skenario lain, permintaan untuk GET / api / pengguna dapat menyebabkan layanan menggunakan aliran peristiwa sejak snapshot terakhir pengguna untuk membuat snapshot lain dan hanya mengembalikan hasilnya. Sistem yang digerakkan oleh peristiwa tidak harus murni tidak sinkron dari Permintaan ke Respons, tetapi cenderung berada pada tingkat di mana layanan perlu berinteraksi dengan layanan lain. Seringkali tidak masuk akal untuk secara asinkron mengembalikan permintaan GET dan oleh karena itu Anda hanya dapat mengembalikan respons suatu layanan,
sumber