Benden sonra tekrar et:
REST ve eşzamansız olaylar alternatif değildir. Tamamen diktirler.
Birine ya da diğerine ya da her ikisine birden sahip olabilirsiniz ya da hiçbiri olmayabilir. Bunlar tamamen farklı sorun alanları için tamamen farklı araçlardır. Aslında, genel amaçlı istek-yanıt iletişimi kesinlikle asenkron, olay güdümlü ve hataya dayanıklı olabilir .
Önemsiz bir örnek olarak, AMQP protokolü TCP bağlantısı üzerinden mesaj gönderir. TCP'de her paketin alıcı tarafından onaylanması gerekir . Bir paketi gönderen kişi bu paket için bir ACK almazsa, bu paketi ACK olana kadar veya uygulama katmanı "vazgeçene" ve bağlantıyı kesene kadar yeniden göndermeye devam eder. Her "paket gönderme isteği" Bunun nedeni açıkça olmayan bir hataya dayanıklı istek-yanıt modelidir gerekir başarısız tüm bağlantılı olarak yanıt sonuçlarına bir beraberindeki "paket, alındı yanıtı" ve başarısızlık var. Yine de, asenkron hataya dayanıklı mesajlaşma için standartlaştırılmış ve yaygın olarak benimsenen bir protokol olan AMQP, TCP üzerinden iletilir! Ne oluyor?
Burada oyunun ana konsepti, ölçeklenebilir gevşek bağlı hataya dayanıklı mesajların nasıl gönderdiğinize değil, hangi mesajlara gönderdiğinize göre tanımlanmasıdır . Başka bir deyişle, uygulama katmanında gevşek bağlantı tanımlanır .
Doğrudan RESTful HTTP ile veya dolaylı olarak AMQP mesaj aracısı ile iletişim kuran iki tarafa bakalım. A Tarafının, görüntüyü keskinleştirecek, sıkıştıracak veya başka şekilde geliştirecek şekilde B Tarafına bir JPEG görüntüsü yüklemek istediğini varsayalım. Taraf A, işlenen görüntüye hemen ihtiyaç duymaz, ancak ileride kullanmak ve geri almak için buna bir referans gerektirir. İşte REST'e girebilecek bir yol:
- Taraf A
POST
, Taraf B'ye aşağıdakilerle birlikte bir HTTP istek iletisi gönderir:Content-Type: image/jpeg
- Parti A görüntüyü işler (eğer büyükse uzun süre) Parti A beklerken muhtemelen başka şeyler yapar
- Taraf B,
201 Created
A Content-Location: <url>
tarafına işlenen görüntüye bağlanan bir başlık içeren bir HTTP yanıt iletisi gönderir
- A Tarafı, işlenmiş görüntüye bir referansı olduğundan, yaptığı işi değerlendirir
- Gelecekte Parti A'nın işlenen görüntüye ihtiyacı olduğunda, önceki
Content-Location
başlıktaki bağlantıyı kullanarak görüntüyü alır
201 Created
Yanıt kodu kendi isteği başarılı oldu sadece bir istemci söyler, o da yeni bir kaynak oluşturmuştur. 201 yanıtında, Content-Location
başlık oluşturulan kaynağa bir bağlantıdır. Bu, RFC 7231 Bölüm 6.3.2 ve 3.1.4.2'de belirtilmiştir.
Şimdi, bu etkileşimin AMQP'nin üstünde varsayımsal bir RPC protokolü üzerinde nasıl çalıştığını görelim:
- Taraf A, bir AMQP mesaj aracısı (Messenger olarak adlandırın) görüntüyü içeren bir mesaj ve işlenmek üzere Taraf B'ye yönlendirmek için talimatlar gönderir, ardından A tarafına görüntü için bir tür adresle yanıt verir
- Parti A bekliyor, muhtemelen başka şeyler yapıyor
- Messenger Parti A'nın orijinal mesajını Parti B'ye gönderir
- Taraf B mesajı iletir
- Taraf B, Messenger'a işlenen görüntünün adresini içeren bir mesaj ve bu mesajı Taraf A'ya yönlendirmek için talimatlar gönderir
- Messenger A Tarafına, B Tarafından işlenen görüntü adresini içeren mesajı gönderir
- A Tarafı, işlenmiş görüntüye bir referansı olduğundan, yaptığı işi değerlendirir
- Gelecekte A Tarafının görüntüye ihtiyacı olduğunda, görüntüyü adresi kullanarak alır (muhtemelen başka bir tarafa mesaj göndererek)
Buradaki problemi görüyor musun? Her iki durumda da, Taraf A kadar bir görüntü adresi alamayan sonra Taraf B görüntüyü işler . Yine de Parti A'nın hemen görüntüye ihtiyacı yoktur ve tüm haklarıyla, işlemin henüz tamamlanması durumunda daha az umursamazdı!
Taraf B'nin A'ya B'nin görüntüyü işleme için kabul ettiğini söyleyerek AMQP davasında bunu kolayca düzeltebiliriz ve A, işlem tamamlandıktan sonra görüntünün nerede olacağı için bir adres verir . Daha sonra Taraf B, gelecekte görüntü işlemenin tamamlandığını belirten bir mesaj A'ya gönderebilir. AMQP kurtarmaya mesajlaşma!
Tahmin et ne hariç: REST ile aynı şeyi başarabilirsiniz . AMQP örneğinde, "işlenen görüntü burada" mesajını "görüntü işleniyor, daha sonra alabilirsiniz" mesajıyla değiştirdik. RESTful HTTP'de bunu yapmak için 202 Accepted
kodu Content-Location
tekrar kullanırız:
- Taraf A
POST
, Taraf B'ye aşağıdakilerle birlikte bir HTTP mesajı gönderir:Content-Type: image/jpeg
- Taraf B derhal
202 Accepted
, işlemenin tamamlanıp tamamlanmadığını ve işlenince görüntünün nerede bulunacağını açıklayan bir tür "eşzamansız işlem" içeriği içeren bir yanıt gönderir . Ayrıca Content-Location: <link>
, bir 202 Accepted
yanıtta, yanıt gövdesi ne olursa olsun temsil edilen kaynağa bir bağlantı olan bir başlık da dahildir . Bu durumda, bu eşzamansız işlemimizin bir bağlantısı olduğu anlamına gelir!
- A Tarafı, işlenmiş görüntüye bir referansı olduğundan, yaptığı işi değerlendirir
- Gelecekte, Taraf A'nın işlenen görüntüye ihtiyacı olduğunda, öncelikle işlemenin tamamlanıp tamamlanmadığını belirlemek için başlıkta bağlı olan zaman uyumsuz işlem kaynağını alır
Content-Location
. Öyleyse, A Tarafı daha sonra işlenen görüntüyü elde etmek için zaman uyumsuz işlemin bağlantısını kullanır.
Buradaki tek fark AMQP modelinde, B Tarafının görüntü işleme tamamlandığında A Tarafına bilgi vermesidir. Ancak REST modelinde, Parti A, işlemenin görüntüye gerçekten ihtiyaç duymadan hemen önce yapılıp yapılmadığını kontrol eder. Bu yaklaşımlar eşit olarak ölçeklendirilebilir . Sistem büyüdükçe, hem asenkron AMQP'de hem de asenkron REST stratejilerinde gönderilen mesajların sayısı, eşdeğer asimptotik karmaşıklıkla artar. Tek fark, istemcinin sunucu yerine fazladan bir mesaj göndermesidir.
Ancak REST yaklaşımının mantığı daha da birkaç hilesi var: dinamik keşif ve protokol görüşmesi . Hem senkronizasyon hem de zaman uyumsuz REST etkileşimlerinin nasıl başladığını düşünün. Taraf A , aynı talebi Taraf B'ye de gönderdi ; tek fark, Taraf B'nin yanıt verdiği belirli bir başarı mesajıdır. Taraf A , görüntü işlemenin eşzamanlı mı yoksa eşzamansız mı olduğunu seçmek isterse? A Tarafı, B Tarafının zaman uyumsuz işleyebildiğini bile bilmiyorsa ne olur?
HTTP aslında bunun için standart bir protokole sahip! Buna HTTP Tercihleri, özellikle respond-async
RFC 7240 Bölüm 4.1 tercihi denir . Taraf A, eşzamansız bir yanıt istiyorsa, Prefer: respond-async
ilk POST isteğine sahip bir başlık içerir . Taraf B bu talebi yerine getirmeye karar verirse 202 Accepted
, a Preference-Applied: respond-async
. Aksi takdirde, Taraf B basitçe Prefer
başlığı yoksayar ve 201 Created
normalde olduğu gibi geri gönderir .
Bu, Taraf A'nın sunucu ile pazarlık yapmasına ve konuştuğu görüntü işleme uygulamasına dinamik olarak adapte olmasına izin verir . Ayrıca, açık bağlantıların kullanılması A Tarafının B dışında herhangi bir taraf hakkında bilgi sahibi olması gerekmediği anlamına gelir: AMQP mesaj komisyoncusu yok, görüntü adresini gerçekte nasıl resim verisine dönüştüreceğini bilen gizemli bir C Partisi, ikinci B-Async yok hem eşzamanlı hem de eşzamansız isteklerin yapılması gerekiyorsa, parti vb. Basitçe neye ihtiyacı olduğunu, isteğe bağlı olarak neyi seveceğini açıklar ve ardından durum kodlarına, yanıt içeriğine ve bağlantılara tepki verir. EkleCache-Control
Verilerin yerel kopyalarının ne zaman saklanacağı konusunda açık talimatlar için üstbilgiler ve artık sunucular, istemcilerin hangi kaynakların yerel (hatta çevrimdışı!) kopyalarını tutabileceği konusunda pazarlık yapabilir. REST'te gevşek bağlı hataya dayanıklı mikro servisler bu şekilde oluşturulur.