Mikro hizmetler için hizmetler arası iletişim tasarlama

Azure DevOps

Mikro hizmetler arasındaki iletişim verimli ve sağlam olmalıdır. Tek bir iş etkinliğini tamamlamak için etkileşim kuran çok sayıda küçük hizmetle bu bir zorluk olabilir. Bu makalede, zaman uyumsuz mesajlaşma ile zaman uyumlu API'ler arasındaki dengeleri inceleyeceğiz. Ardından, dayanıklı hizmetler arası iletişim tasarlamanın bazı zorluklarına göz atacağız.

Zorluklar

Hizmetten hizmete iletişimden kaynaklanan başlıca zorluklardan bazıları aşağıdadır. Bu makalenin devamında açıklanan hizmet tanımlamaları, bu zorlukların çoğunu ele almak için tasarlanmıştır.

Dayanıklılık. Herhangi bir mikro hizmetin onlarca, hatta yüzlerce örneği olabilir. Bir örnek çeşitli nedenlerle başarısız olabilir. Donanım hatası veya VM yeniden başlatma gibi düğüm düzeyinde bir hata olabilir. Bir örnek kilitlenebilir veya isteklere boğulabilir ve yeni istekleri işleyemeyebilir. Bu olaylardan herhangi biri bir ağ çağrısının başarısız olmasına neden olabilir. Hizmet-hizmet ağ çağrılarının daha dayanıklı hale getirmesine yardımcı olabilecek iki tasarım deseni vardır:

  • Yeniden deneyin. Ağ çağrısı, kendi kendine giden geçici bir hata nedeniyle başarısız olabilir. Çağıran, hemen başarısız olmak yerine işlemi genellikle belirli bir sayıda yeniden denemelidir veya yapılandırılmış bir zaman aşımı süresi geçene kadar. Ancak, bir işlem bir kez etkili değilse, yeniden denemeler istenmeyen yan etkilere neden olabilir. Özgün çağrı başarılı olabilir, ancak arayan hiçbir zaman yanıt almaz. Çağıran yeniden denenirse, işlem iki kez çağrılabilir. Genellikle POST veya PATCH yöntemlerini yeniden denemek güvenli değildir, çünkü bunların bir kez etkili olacağı garanti edilmez.

  • Devre Kesici. Bekleyen istekler kuyrukta biriktiğinden çok fazla başarısız istek bir performans sorununa neden olabilir. Bu engellenen isteklerde bellek, iş parçacıkları, veritabanı bağlantıları ve benzeri önemli sistem kaynakları bulunabilir ve bu durum da zincirleme hatalara neden olabilir. Devre Kesici düzeni, bir hizmetin başarısız olma olasılığı olan bir işlemi tekrar tekrar denemesini engelleyebilir.

Yük dengeleme. "A" hizmeti "B" hizmetini çağırdığında, isteğin çalışan bir "B" hizmeti örneğine ulaşması gerekir. Kubernetes'te kaynak türü, Service bir pod grubu için kararlı bir IP adresi sağlar. Hizmetin IP adresine yönelik ağ trafiği, iptable kuralları aracılığıyla bir pod'a iletilir. Varsayılan olarak rastgele bir pod seçilir. Hizmet ağı (aşağıya bakın), gözlemlenen gecikme süresine veya diğer ölçümlere göre daha akıllı yük dengeleme algoritmaları sağlayabilir.

Dağıtılmış izleme. Tek bir işlem birden çok hizmete yayılabilir. Bu, sistemin genel performansını ve sistem durumunu izlemeyi zorlaştırabilir. Her hizmet günlükler ve ölçümler oluştursa bile, bunları birbirine bağlamanın bir yolu olmadan sınırlı kullanımdadır. Günlüğe kaydetme ve izleme makalesinde dağıtılmış izleme hakkında daha fazla bilgi verilmektedir, ancak burada bunu bir sınama olarak belirteceğiz.

Hizmet sürümü oluşturma. Bir ekip bir hizmetin yeni bir sürümünü dağıttığında, buna bağlı olan diğer hizmetleri veya dış istemcileri bozmaktan kaçınmalıdır. Ayrıca, bir hizmetin birden çok sürümünü yan yana çalıştırmak ve istekleri belirli bir sürüme yönlendirmek isteyebilirsiniz. Bu sorunla ilgili daha fazla bilgi için bkz. API Sürümü Oluşturma .

TLS şifrelemesi ve karşılıklı TLS kimlik doğrulaması. Güvenlik nedeniyle, hizmetler arasındaki trafiği TLS ile şifrelemek ve arayanların kimliğini doğrulamak için karşılıklı TLS kimlik doğrulamasını kullanmak isteyebilirsiniz.

Zaman uyumlu ve zaman uyumsuz mesajlaşma karşılaştırması

Mikro hizmetlerin diğer mikro hizmetlerle iletişim kurmak için kullanabileceği iki temel mesajlaşma düzeni vardır.

  1. Zaman uyumlu iletişim. Bu düzende bir hizmet, HTTP veya gRPC gibi bir protokol kullanarak başka bir hizmetin kullanıma açık olduğu bir API'yi çağırır. Çağıran alıcıdan yanıt beklediğinden bu seçenek zaman uyumlu bir mesajlaşma düzenidir.

  2. Zaman uyumsuz ileti geçirme. Bu düzende, bir hizmet yanıt beklemeden ileti gönderir ve bir veya daha fazla hizmet iletiyi zaman uyumsuz olarak işler.

Zaman uyumsuz G/Ç ile zaman uyumsuz protokol arasında ayrım yapmak önemlidir. Zaman uyumsuz G/Ç, G/Ç tamamlanırken çağıran iş parçacığının engellenmediği anlamına gelir. Bu, performans açısından önemlidir, ancak mimari açısından bir uygulama ayrıntısıdır. Zaman uyumsuz protokol, gönderenin yanıt beklemediği anlamına gelir. HTTP istemcisi istek gönderirken zaman uyumsuz G/Ç kullanabilse de HTTP zaman uyumlu bir protokoldür.

Her desenin dengeleri vardır. İstek/yanıt iyi anlaşılmış bir paradigma olduğundan API tasarlamak, mesajlaşma sistemi tasarlamaktan daha doğal görünebilir. Ancak, zaman uyumsuz mesajlaşmanın mikro hizmetler mimarisinde yararlı olabilecek bazı avantajları vardır:

  • Azaltılmış bağlantı. İletiyi gönderenin tüketici hakkında bilgi sahibi olması gerekmez.

  • Birden çok abone. Bir pub/sub modeli kullanarak birden çok tüketici olayları almak için abone olabilir. Bkz . Olay temelli mimari stili.

  • Hata yalıtımı. Tüketici başarısız olursa, gönderen yine de ileti gönderebilir. İletiler, tüketici kurtarıldığında alınır. Her hizmetin kendi yaşam döngüsü olduğundan, bu özellik özellikle mikro hizmetler mimarisinde yararlıdır. Bir hizmet, herhangi bir zamanda kullanılamaz duruma gelebilir veya daha yeni bir sürümle değiştirilebilir. Zaman uyumsuz mesajlaşma aralıklı kapalı kalma süresini işleyebilir. Öte yandan zaman uyumlu API'ler, aşağı akış hizmetinin kullanılabilir olmasını gerektirir veya işlem başarısız olur.

  • Yanıt verme hızı. Yukarı akış hizmeti, aşağı akış hizmetlerinde beklemediği takdirde daha hızlı yanıt verebilir. Bu özellikle mikro hizmetler mimarisinde yararlıdır. Hizmet bağımlılıkları zinciri varsa (A hizmeti B'yi çağırır, C'yi çağırır vb.), zaman uyumlu çağrıları beklemek kabul edilemez miktarda gecikmeye neden olabilir.

  • Yük dengeleme. Kuyruk, alıcıların iletileri kendi hızlarında işleyebilmesi için iş yükünü dengelemek için bir arabellek görevi görebilir.

  • İş akışları. Kuyruklar, iş akışındaki her adımdan sonra iletiyi işaret ederek iş akışını yönetmek için kullanılabilir.

Ancak, zaman uyumsuz mesajlaşmayı etkili bir şekilde kullanmanın bazı zorlukları da vardır.

  • Mesajlaşma altyapısıyla bağlantı. Belirli bir mesajlaşma altyapısının kullanılması, bu altyapıyla sıkı bir bağlantı olmasına neden olabilir. Daha sonra başka bir mesajlaşma altyapısına geçmek zor olacaktır.

  • Gecikme süresi. İleti kuyrukları dolarsa bir işlem için uçtan uca gecikme süresi yüksek olabilir.

  • Maliyet. Yüksek aktarım hızlarında mesajlaşma altyapısının parasal maliyeti önemli olabilir.

  • Karmaşıklık. Zaman uyumsuz mesajlaşmayı işlemek önemsiz bir görev değildir. Örneğin yinelenen iletileri yinelenenleri kaldırarak veya işlemleri bir kez etkili hale getirerek işlemeniz gerekir. Zaman uyumsuz mesajlaşma kullanarak istek yanıtı semantiği uygulamak da zordur. Yanıt göndermek için başka bir kuyruğa ve istek ile yanıt iletilerini ilişkilendirmenin bir yoluna ihtiyacınız vardır.

  • İşleme hızı. İletiler kuyruk semantiği gerektiriyorsa, kuyruk sistemde bir performans sorununa dönüşebilir. Her ileti için en az bir kuyruk işlemi ve bir dequeue işlemi gerekir. Ayrıca kuyruk semantiği genellikle mesajlaşma altyapısında bir tür kilitleme gerektirir. Kuyruk yönetilen bir hizmetse, kuyruk kümenin sanal ağına dış olduğundan ek gecikme olabilir. İletileri toplu işleyerek bu sorunları azaltabilirsiniz, ancak bu da kodu karmaşıklaştırır. İletilerde kuyruk semantiği gerekmiyorsa, kuyruk yerine olay akışı kullanabilirsiniz. Daha fazla bilgi için bkz . Olay temelli mimari stili.

İnsansız Hava Aracı ile Teslimat: Mesajlaşma düzenlerini seçme

Bu çözüm İnsansız Hava Aracı ile Teslimat örneğini kullanır. Havacılık ve uçak endüstrileri için idealdir.

Bu konuları göz önünde bulundurarak geliştirme ekibi İnsansız Hava Aracı ile Teslimat uygulaması için aşağıdaki tasarım seçimlerini yaptı:

  • Alma hizmeti, istemci uygulamalarının teslimatları zamanlamak, güncelleştirmek veya iptal etmek için kullandığı bir genel REST API'yi kullanıma sunar.

  • Alma hizmeti, Zamanlayıcı hizmetine zaman uyumsuz iletiler göndermek için Event Hubs kullanır. Alma için gereken yük dengelemeyi uygulamak için zaman uyumsuz iletiler gereklidir.

  • Hesap, Teslimat, Paket, İnsansız Hava Aracı ve Üçüncü Taraf Taşıma hizmetlerinin tümü dahili REST API'lerini kullanıma sunar. Scheduler hizmeti, kullanıcı isteğini gerçekleştirmek için bu API'leri çağırır. Zaman uyumlu API'leri kullanmanın bir nedeni, Zamanlayıcı'nın aşağı akış hizmetlerinin her birinden yanıt alması gerektiğidir. Aşağı akış hizmetlerinden herhangi birinde hata, işlemin tamamının başarısız olduğu anlamına gelir. Ancak, olası bir sorun arka uç hizmetleri çağrılarak ortaya çıkabilecek gecikme süresi miktarıdır.

  • Herhangi bir aşağı akış hizmetinde geçici olmayan bir hata varsa, işlemin tamamı başarısız olarak işaretlenmelidir. Bu durumu işlemek için Zamanlayıcı hizmeti Gözetmen'e zaman uyumsuz bir ileti gönderir, böylece Gözetmen telafi işlemleri zamanlayabilir.

  • Teslim hizmeti, istemcilerin bir teslimin durumunu almak için kullanabileceği bir genel API'yi kullanıma sunar. API ağ geçidi makalesinde, bir API ağ geçidinin temel alınan hizmetleri istemciden nasıl gizleyebileceğini ele almalıyız, böylece istemcinin hangi hizmetlerin hangi API'leri kullanıma sunabileceğini bilmesi gerekmez.

  • İnsansız hava aracı uçuş sırasında İnsansız Hava Aracı hizmeti, insansız hava aracının geçerli konumunu ve durumunu içeren olayları gönderir. Teslim hizmeti, bir teslimin durumunu izlemek için bu olayları dinler.

  • Bir teslimin durumu değiştiğinde, Teslim hizmeti veya DeliveryCompletedgibi DeliveryCreated bir teslim durumu olayı gönderir. Herhangi bir hizmet bu olaylara abone olabilir. Geçerli tasarımda, Teslim Geçmişi hizmeti tek abonedir, ancak daha sonra başka aboneler de olabilir. Örneğin, olaylar gerçek zamanlı bir analiz hizmetine gidebilir. Zamanlayıcı'nın yanıt beklemesi gerekmeyen bir durum olduğundan, daha fazla abone eklemek ana iş akışı yolunu etkilemez.

İnsansız hava aracı iletişiminin diyagramı

Teslimat durumu olaylarının insansız hava aracı konum olaylarından türetildiğini fark edin. Örneğin, bir insansız hava aracı bir teslimat konumuna ulaştığında ve bir paketi teslim ettiğinde, Teslim hizmeti bunu DeliveryCompleted olayına çevirir. Bu, etki alanı modelleri açısından düşünme örneğidir. Daha önce açıklandığı gibi İnsansız Hava Aracı Yönetimi ayrı bir sınırlanmış bağlama aittir. İnsansız hava aracı olayları bir insansız hava aracının fiziksel konumunu gösterir. Öte yandan teslim olayları, farklı bir işletme varlığı olan teslim durumundaki değişiklikleri temsil eder.

Hizmet ağı kullanma

Hizmet ağı, hizmet-hizmet iletişimlerini işleyen bir yazılım katmanıdır. Hizmet kısa çizgileri, önceki bölümde listelenen birçok sorunu ele almak ve bu endişelerin sorumluluğunu mikro hizmetlerden uzaklaştırıp paylaşılan bir katmana taşımak için tasarlanmıştır. Hizmet ağı, kümedeki mikro hizmetler arasındaki ağ iletişimini kesen bir ara sunucu işlevi görür. Şu anda hizmet ağı kavramı, sunucusuz mimariler yerine kapsayıcı düzenleyicileri için geçerlidir.

Not

Hizmet ağı, Uygulama adına ağ istekleri gönderen bir yardımcı hizmet olan Büyükelçi deseninin bir örneğidir.

Şu anda Kubernetes'teki bir hizmet ağı için ana seçenekler Linkerd ve Istio'dur. Bu teknolojilerin her ikisi de hızla gelişiyor. Ancak Linkerd ve Istio'da ortak olan bazı özellikler şunlardır:

  • Gözlemlenen gecikme sürelerine veya bekleyen istek sayısına göre oturum düzeyinde yük dengeleme. Bu, Kubernetes tarafından sağlanan katman 4 yük dengelemesi performansını artırabilir.

  • URL yolu, Konak üst bilgisi, API sürümü veya diğer uygulama düzeyi kurallarına göre katman 7 yönlendirme.

  • Başarısız istekleri yeniden deneyin. Hizmet ağı HTTP hata kodlarını anlar ve başarısız istekleri otomatik olarak yeniden deneyebilir. Maksimum gecikme süresini sınırlamak için bu en fazla yeniden deneme sayısını ve zaman aşımı süresini yapılandırabilirsiniz.

  • Bağlantı hattı kopuyor. Bir örnek istekleri sürekli olarak başarısız olursa hizmet ağı geçici olarak kullanılamaz olarak işaretler. Geri alma döneminden sonra örneği yeniden dener. Ardışık hata sayısı gibi çeşitli ölçütlere göre devre kesiciyi yapılandırabilirsiniz.

  • Hizmet ağı istek hacmi, gecikme süresi, hata ve başarı oranları ve yanıt boyutları gibi hizmetler arası çağrılarla ilgili ölçümleri yakalar. Hizmet ağı, bir istekteki her atlama için bağıntı bilgileri ekleyerek dağıtılmış izlemeyi de etkinleştirir.

  • Hizmet-hizmet çağrıları için karşılıklı TLS Kimlik Doğrulaması.

Hizmet ağı gerekiyor mu? Duruma göre değişir. Hizmet ağı olmadan, bu makalenin başında bahsedilen zorlukların her birini göz önünde bulundurmanız gerekir. Yeniden deneme, devre kesici ve dağıtılmış izleme gibi sorunları bir hizmet ağı olmadan çözebilirsiniz, ancak bir hizmet ağı bu endişeleri tek tek hizmetlerin dışına ve ayrılmış bir katmana taşır. Öte yandan, bir hizmet ağı kümenin kurulumuna ve yapılandırmasına karmaşıklık ekler. İstekler artık hizmet ağı proxy'si üzerinden yönlendirildiğinden ve ek hizmetler artık kümedeki her düğümde çalıştığından performans üzerindeki etkileri olabilir. Üretimde bir hizmet ağı dağıtmadan önce kapsamlı performans ve yük testi yapmanız gerekir.

Dağıtılmış işlemler

Mikro hizmetlerde yaygın bir zorluk, birden çok hizmete yayılan işlemleri doğru şekilde işlemektir. Bu senaryoda genellikle bir işlemin başarısının tümü veya hiçi olur; katılan hizmetlerden biri başarısız olursa işlemin tamamının başarısız olması gerekir.

Dikkate alınması gereken iki durum vardır:

  • Bir hizmet, ağ zaman aşımı gibi geçici bir hatayla karşılaşabilir. Bu hatalar genellikle çağrı yeniden denenerek çözülebilir. Belirli sayıda denemeden sonra da işlem başarısız olursa geçici olmayan bir hata olarak kabul edilir.

  • Geçici olmayan bir hata, tek başına ortadan kalkma olasılığı düşük olan herhangi bir hatadır. Geçici olmayan hatalar, geçersiz giriş gibi normal hata koşullarını içerir. Ayrıca uygulama kodunda veya bir işlemin kilitlenmesinde işlenmeyen özel durumlar da içerir. Bu tür bir hata oluşursa, iş işleminin tamamı hata olarak işaretlenmelidir. Aynı işlemde zaten başarılı olan diğer adımları geri almak gerekebilir.

Geçici olmayan bir hatadan sonra, geçerli işlem kısmen başarısız olmuş durumda olabilir ve burada bir veya daha fazla adım başarıyla tamamlanmıştır. Örneğin, İnsansız Hava Aracı hizmeti zaten bir insansız hava aracı zamanladıysa, insansız hava aracı iptal edilmelidir. Bu durumda, uygulamanın Telafi İşlemi kullanarak başarılı olan adımları geri alması gerekir. Bazı durumlarda, bunun bir dış sistem tarafından, hatta el ile gerçekleştirilen bir işlemle yapılması gerekir.

İşlemleri telafi etme mantığı karmaşıksa, bu işlemden sorumlu ayrı bir hizmet oluşturmayı göz önünde bulundurun. İnsansız Hava Aracı ile Teslimat uygulamasında Scheduler hizmeti başarısız işlemleri ayrılmış bir kuyruğa yerleştirir. Supervisor adlı ayrı bir mikro hizmet bu kuyruktan okur ve telafisi gereken hizmetler üzerinde bir iptal API'sini çağırır. Bu, Zamanlayıcı Aracısı Gözetmen düzeninin bir varyasyonudur. Gözetmen hizmeti, kullanıcıyı kısa mesaj veya e-postayla bilgilendirme veya bir işlem panosuna uyarı gönderme gibi başka eylemler de gerçekleştirebilir.

Gözetmen mikro hizmetini gösteren diyagram

Zamanlayıcı hizmetinin kendisi başarısız olabilir (örneğin, bir düğüm kilitlendiğinden). Bu durumda, yeni bir örnek ortaya çıkıp devralabilir. Ancak, devam etmekte olan tüm işlemler sürdürülmelidir.

Yaklaşımlardan biri, iş akışındaki her adım tamamlandıktan sonra denetim noktasını dayanıklı bir depoya kaydetmektir. Scheduler hizmetinin bir örneği bir işlemin ortasında kilitlenirse, yeni bir örnek önceki örneğin kaldığı yerden devam etmek için denetim noktasını kullanabilir. Ancak denetim noktaları yazmak bir performans yükü oluşturabilir.

Bir diğer seçenek de tüm işlemleri bir kez etkili olacak şekilde tasarlamaktır. bir işlem, ilk çağrıdan sonra ek yan etkiler üretmeden birden çok kez çağrılabiliyorsa bir kez etkili olur. Temel olarak, aşağı akış hizmeti yinelenen çağrıları yoksaymalıdır, bu da hizmetin yinelenen çağrıları algılayabilmesi gerektiği anlamına gelir. Bir kez etkili yöntemler uygulamak her zaman kolay değildir. Daha fazla bilgi için bkz. Bir kez etkili işlemler.

Sonraki adımlar

Doğrudan birbiriyle konuşan mikro hizmetler için iyi tasarlanmış API'ler oluşturmak önemlidir.