API Ağ Geçidi (REST) ​​+ Olay Odaklı Mikro Hizmetler


16

Ben API işlevselliği API ağ geçidi desen göre bir REST API ile maruz kim mikro hizmetlerin bir demet var. Bu mikro hizmetler Spring Boot uygulamaları olduğundan, bu mikro hizmetler arasında RPC tarzı senkron iletişim sağlamak için Spring AMQP kullanıyorum. Şimdiye kadar işler düzgün gidiyor. Ancak, olay güdümlü mikro hizmet mimarileri hakkında daha fazla okuduğum ve Spring Cloud Stream gibi projelere baktığımda, RPC, eşzamanlı yaklaşımla işleri yanlış bir şekilde yapacağım konusunda daha ikna oldum (özellikle bunu ölçeklendirmek için buna ihtiyacım olacağı için) istemci uygulamalarından saniyede yüzlerce veya binlerce talebe yanıt vermek için).

Olay odaklı bir mimarinin arkasındaki noktayı anlıyorum. Tam olarak anlamadığım şey, aslında her talebe cevap bekleyen bir modelin (REST) ​​arkasında otururken böyle bir kalıbın nasıl kullanılacağıdır. Örneğin, bir mikro hizmet ve kullanıcıları depolayan ve yöneten başka bir mikro hizmet olarak API ağ geçidim varsa, GET /users/1tamamen olay güdümlü bir şekilde nasıl bir şey modelleyebilirim ?

Yanıtlar:


9

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 CreatedA 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-Locationbaşlıktaki bağlantıyı kullanarak görüntüyü alır

201 CreatedYanı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-Locationbaş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 Acceptedkodu Content-Locationtekrar 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 Acceptedyanı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ırContent-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-asyncRFC 7240 Bölüm 4.1 tercihi denir . Taraf A, eşzamansız bir yanıt istiyorsa, Prefer: respond-asyncilk 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 Preferbaşlığı yoksayar ve 201 Creatednormalde 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-ControlVerilerin 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.


1

Tamamen olaya dayalı olmanız gerekip gerekmediği elbette sizin özel senaryonuza bağlıdır. Gerçekten olmanız gerektiğini varsayarsak, sorunu şu şekilde çözebilirsiniz:

Farklı olayları dinleyerek ve bilgi yüklerindeki bilgileri yakalayarak verilerin yerel, salt okunur bir kopyasını saklama . Bu, söz konusu uygulama için size tam olarak uygun bir formda depolanan bu veriler için hızlı (er) okumalar sunarken, verilerinizin hizmetler arasında nihayetinde tutarlı olacağı anlamına gelir.

GET /users/1Bu yaklaşımla modellemek için, UserCreatedve UserUpdatedolayları dinleyebilir ve kullanıcı verilerinin faydalı alt kümesini hizmette saklayabilirsiniz. Daha sonra bu kullanıcı bilgilerini almanız gerektiğinde, yerel veri deponuzu sorgulayabilirsiniz.

Bir dakika için, /users/son noktayı ortaya çıkaran hizmetin herhangi bir olay yayınlamadığını varsayalım . Bu durumda, yaptığınız HTTP isteklerine verilen yanıtları önbelleğe alarak benzer bir şey başarabilir ve böylece bir zaman dilimi içinde kullanıcı başına 1'den fazla HTTP isteği yapma ihtiyacını ortadan kaldırabilirsiniz.


Anlıyorum. Peki ya bu senaryoda istemcilere hata işleme (ve raporlama)?
Tony E. Stark

Yani, UserCreatedolay işlenirken oluşan REST istemcilerine nasıl rapor verebilirim (örneğin, yinelenen kullanıcı adı veya e-posta veya veritabanı kesintisi).
Tony E. Stark

Eylemi gerçekleştirdiğiniz yere bağlıdır. Kullanıcı sisteminin içindeyseniz, tüm doğrulama işleminizi yapabilir, orada veri deposuna yazabilir, ardından etkinliği yayınlayabilirsiniz. Aksi takdirde, /users/uç noktaya standart bir HTTP isteği gerçekleştirmenin mükemmel olduğunu kabul ediyorum ve başarılı olursa bu sistemin etkinliğini yayınlamasına izin veriyorum ve yeni varlık
Andy Hunt

0

Olay kaynaklı bir sistemde, durumu, belki bir veritabanını veya bazı verilerin toplu görünümünü değiştiren bir şey normalde eşzamansız yönler devreye girer. Örneğinizi kullanarak, GET / api / kullanıcılarına yapılan bir çağrı, sistemdeki kullanıcı listesinin güncel bir temsiline sahip bir hizmetten gelen yanıtı döndürebilir. Başka bir senaryoda, GET / api / kullanıcılarına yönelik istek, bir hizmetin, kullanıcıların son anlık görüntüsünden başka bir anlık görüntü oluşturmak ve sonuçları döndürmek için olay akışını kullanmasına neden olabilir. Olay güdümlü bir sistem, mutlaka Yanıt İsteği ile tamamen eşzamanlı değildir, ancak hizmetlerin diğer hizmetlerle etkileşim kurması gereken düzeyde olma eğilimindedir. Genellikle bir GET isteğini eşzamansız olarak döndürmek mantıklı değildir ve böylece bir hizmetin yanıtını geri gönderebilirsiniz,

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.