Mikro servisler: Olağan tutarlılığı kullanma


22

Bir kullanıcının şifresini güncelleyen bir fonksiyonumuz olduğunu varsayalım.

'Şifreyi Güncelle' düğmesine tıklandığında, diğer 3 servisin abone olduğu bir konuya bir UpdatePasswordEvent gönderilir:

  1. Kullanıcı şifresini gerçekten güncelleyen bir servis
  2. Kullanıcının şifre geçmişini güncelleyen bir servis
  3. Kullanıcıya şifresinin değiştirildiğini bildiren bir e-posta gönderen bir servis.

Nihai tutarlılık hakkında anladığım şeye dayanarak, tüm bu hizmetler (tüketiciler) aynı anda olayı alacak ve onları iyi bir senaryoda verilerin tutarlı olmasına yol açacak şekilde ayrı ayrı işleyecek.

Ancak, bir hizmet etkinliği işleyemezse ne olur? örneğin ani bağlantı kesme, veritabanı hatası, vb ... Bu işlem hatalarını ele almak için iyi bir kalıp / uygulama nedir?

Herhangi bir etkinliğin işlenmemesi durumunda, "geri alma hizmetlerinin" işini yapacağı ve verileri geri döndüreceği bir konuda bir GeridöngüYeni oluşturulacak bir RollbackTopic oluşturmayı düşünüyordum


11
Gönderilmiş bir e-postayı geri alamazsınız :-)
Laiv

2
Çünkü hepsi aynı hizmetin bir parçası olmalı. Mikro servis monolitlere karşıdır, bu onları "fiziksel olarak" mümkün olduğunca az tasarlamanız gerektiği anlamına gelmez. Bu doğrudan ilişkili olmasa da, bu soruyu ve iki en iyi cevabı
okumalısınız

1
Kullanıcının parolasını veritabanında eşzamanlı olarak güncellemeyi düşünebilirsiniz, böylece kullanıcıya anında geri bildirimde bulunabilirsiniz ve parolanın bir konuda değiştiği mesajını göndermek zorunda kalmadan bir mesaj göndererek diğer hizmetleri eşzamansız tetikleyerek şifreyi içerir.
cr3

İşlemin tamamlandığını kullanıcıya bildiren e-posta mı, yoksa birisinin (umarım ki) şifreyi değiştirdiğini kullanıcıya bildirmek mi? “Sen olmasaydın, o zaman harekete geçmen gerekiyor”. İkincisi ise sadece şimdi e-posta gönderin, elinizden geldiğince.
ctrl-alt-delor

Yanıtlar:


29

Nihai tutarlılık hakkında anladığım şeye dayanarak, tüm bu hizmetler (tüketiciler) aynı anda olayı alacak ve iyi bir senaryoda verilerin tutarlı olmasına yol açacak şekilde ayrı ayrı işleyecek.

Hayır, mutlaka değil. Yorum yaptığım gibi, gönderilen bir e-postayı geri alamayız, bu nedenle bir tür "sıralamaya" ihtiyacımız var. IPC üzerinde olaya dayalı veri yönetimi orchestation ait muaf değildir 1 .

Örneğin, önceki işlemler başarıyla tamamlanmadıkça ve e-posta hizmeti bunun bir kanıtını almadıkça e-posta gönderilmemelidir. 3

Ancak, bir hizmet etkinliği işleyemezse ne olur? örneğin ani bağlantı kesme, veritabanı hatası, vb ... Bu işlem hatalarını ele almak için iyi bir kalıp / uygulama nedir?

Dağıtılmış hesaplamanın yanlışlarına merhaba deyin . Her şeyi karmaşık yapan şeylerdir ve her zamanki gibi onlarla başa çıkacak gümüş mermiler yoktur.

Kayıp Gemiyi arama yolculuğumuza başlamadan önce, önce organizasyona sormayı düşünmeliyiz. Çoğunlukla çözüm, kuruluşun gerçek dünyada bu sorunlarla nasıl karşılaştığı ile ilgilidir .

Bazı veriler eksik veya eksik olduğunda ne yapar?

Farklı departmanların, tamamen uygulanacak çözümü oluşturan farklı çözümleri olduğunu fark edeceğiz.

Her neyse, burada izlenecek stratejimizde bize yardımcı olabilecek bazı uygulamalar.

Nihai tutarlılık

Sistemin her zaman tutarlı bir durumda olmasını sağlamak yerine, bunun gelecekte sistemin bir noktada alacağını kabul edebiliriz. Bu yaklaşım özellikle uzun ömürlü ticari operasyonlar için kullanışlıdır.

Sistemin tutarlılığa ulaşması, sistemden sisteme değişir. Otomatik işlemlerden bir tür insan müdahalesine kadar içerebilir. Örneğin, tipik olarak daha sonra tekrar deniyor veya Müşteri Hizmetleri ile iletişim kuruyor .

Tüm işlemleri iptal et

Dengeleme işlemleri yoluyla sistemi tekrar tutarlı bir duruma getirin . Ancak, bu işlemlerin de başarısız olabileceğini, tutarsızlığın çözülmesinin daha zor olduğu bir noktaya neden olabileceklerini hesaba katmamız gerekir. Ve yine, gönderilen bir e-postayı geri alamayız.

Düşük sayıda işlem için, bu yaklaşım uygulanabilir, çünkü telafi edici işlemlerin sayısı da düşüktür. IPC'de yer alan birkaç ticari işlem olsaydı, her biri için bir telafi edici işlem yapılması zor olurdu.

Biz gidersek işlemleri telafi biz bulacaksınız devre kesici tasarımı deseni çok yararlı olduğu - ve zorunlu söylemeye cesaret edemez -

Dağıtılmış işlemler

Buradaki fikir, İşlem Yöneticisi olarak bilinen genel bir yönetim süreci boyunca, tek bir işlem içinde birden fazla işlemi yaymaktır . Dağıtılmış işlemlerin işlenmesi için ortak bir algoritma İki aşamalı işlemdir .

Dağıtılmış işlemlerin temel kaygısı, kullanım ömrü boyunca kaynakları kilitlemeye güvenmeleridir ve bildiğimiz gibi, İşlem Yöneticisi için de işler ters gidebilir .

İşlem Yöneticileri tehlikeye girerse, farklı sınırlanmış bağlamların her yerinde birkaç kilitle sonuçlanabilir, bu da mesajların sıralanması nedeniyle beklenmeyen davranışlarla sonuçlanabilir. 2

Ayrıştırma işlemleri Niye ya?

Mevcut bir sistemi parçalara ayırıyorsanız ve gerçekten tek bir işlem sınırı içinde olmak isteyen bir kavramlar topluluğu buluyorsanız, belki de onları sonuna kadar bırakın.

Sam Newman

Yukarıdaki argümanlara uygun olarak, Sam - Yapı Mikro Şebekeleri kitabında - eğer gerçekten, gerçekten tutarlı bir sonuç elde edemezsek , işlemi şimdi bölmekten kaçınmamız gerektiğini belirtir.

Bazı işlemleri iki veya daha fazla işleme ayırmayı göze alamazsak, bu işlemlerin muhtemelen sınırlandırılmış içeriğe ya da en azından modellenmeye devam eden enine kesitli bir içeriğe ait olduğu söylenebilir.

Örneğin, bizim durumumuzda, biz bu işlem gerçekleştirebilmeyi 1. malumunuzdur ve 2. sıkıca birbirlerine ilişkilidir ve muhtemelen ikisi de aynı sınırlı bağlam ait olabilir Hesaplar , Kullanıcılar , Register , her neyse ...

Her iki işlemi de aynı işlemin sınırları içerisinde tutmayı düşünün. Tüm işlemi idare etmeyi kolaylaştıracak. Ayrıca, her bir işlemin kritiklik seviyesi de ağırlıktadır. Muhtemelen, işlem # 2 başarısız olursa, tüm işlemden ödün vermemelidir. Şüphe durumunda kuruluşa sorunuz .


1: Düşündüğünüz tür bir düzenleme değil. ESB’nin ortasyonundan bahsetmiyorum. Hizmetlerin doğru olaya tepki göstermesini sağlamaktan bahsediyorum.

2: Dağıtılmış işlemlerle ilgili ilginç Sam Newman'ın düşüncelerini bulabilirsiniz .

3: David Parker'ın bu konuyla ilgili cevabını kontrol edin.


3
Çok iyi cevap. Sadece dağıtılmış işlemler kullanılırken ortaya çıkan riskleri dikkate almanın önemini vurgulayacağım - özellikle kilitlenmeler ve sistem durdurmaları üreten kaynak kilitleme. Yaklaşık 3 yıl önce çalıştığım bir e-ticaret ürününde DT'leri mesajlaşma sistemi ile değiştirmek zorunda kaldık, çünkü sistemlerde mevcut olan kullanıcı sayısı nedeniyle sistem hatalara çok açıktı. DT'lerle ilgili sorunlar çoğunlukla bir kullanıcı tabanı büyüdüğünde ortaya çıkar.
Andy

7

Senin durumunda her üç şeyi de aynı anda işleyemezsin. İhtiyacınız olan bir süreç. İşte son derece basitleştirilmiş bir örnek:

Komuta ve etkinlik düzenleme

Durum değiştirme işlemlerinin her zaman tutarlı bir varlık üzerinde yapılması GEREKEN olduğunu bilmek önemlidir. Güçlü tutarlılığı garanti edemezseniz , bir ana kayıtta yapılmalıdır.

Sisteminiz, sisteminizde herhangi bir olay meydana gelmeden önce, değişikliklerin önce işlem güvenliği ile sürdürülmesinin GEREKEN olduğunu garanti etmelidir. Bu, yükseltilmiş bir olayın gerçekten olanların bir teyidi olmasını sağlamak içindir.

Sürecin olduğu gibi bazı zorlu kısımlar var ve bariz olanları görmezden geleceğim - örneğin: Peki ya değiştirilmiş parolası olan bir kullanıcıya devam ederken veritabanı sunucunuz ölürse? Sadece UpdatePassword'ü tekrar yayınlayın. Ancak, bazı parçaların sizin tarafınızdan halledilmesi gerekir ve bunlar:

  • ileti çoğaltmayı işleme,
  • e-posta gönderme

Bir sistemde, işlem orkestratörü (PO) içsel durumu içeren - aynı zamanda kelimenin tam anlamıyla - başka bir varlıktan başka bir şey değildir ve devletler arasında geçişleri mümkün kılar, bir tür durum makinesi gibi etkili bir şekilde hareket eder. İç durum sayesinde mesaj çoğaltma işlemlerini kaldırabilirsiniz.

PO bir Newdurumda olduğunda ve işlediğinde UserPasswordHasBeenUpdated, durumunu değiştirir UserPasswordHasBeenUpdated(veya hangi devlet adı sizin için çalışırsa). Eğer PO hala bir UserPasswordHasBeenUpdatedbaşkasında UserPasswordHasBeenUpdatedolsaydı ve bir başkası gelirse, PO bir yineleme olduğunu bilerek mesajı tamamen görmezden gelirdi. Benzer mekanizmalar diğer devletler için de uygulanacaktı.

E-postanın gerçek gönderimini kullanmak biraz daha zordur. Burada iki seçeneğiniz var:

  1. en fazla bir kere gönder
  2. en az bir kere gönder.

En çok bir kez gönder

Bu seçenekle, PO UserPasswordHistoryHasBeenSaveddurumuna ulaştığında durum değişikliğine bir tepki olarak e-posta gönderme komutu gönderilir. Sisteminiz UserPasswordHistoryHasBeenSavede-postayı göndermeden önce durumun devam etmesini sağlar, yani yinelenen ileti e-postayı yeniden göndermeyi tetiklemez. Bu yaklaşımla PO için doğru durumun kaydedildiğinden emin olursunuz, ancak sonraki işlemleri garanti edemezsiniz.

En az bir kere gönder

Ben bunun için giderdim.

UserPasswordHistoryHasBeenSavedE-postayı bir tepki olarak kaydetmek ve göndermek yerine, önce e-postayı göndermeye çalışırsınız. Gönderme işlemi başarısız olursa, PO'nun durumu hiçbir zaman olarak değiştirilmez UserPasswordHistoryHasBeenSavedve aynı türden başka bir mesaj hala işlenir. E-postanın gönderilmesi gerçekten başarılı olursa, ancak sisteminiz yeni UserPasswordHistoryHasBeenSaveddurumuyla birlikte PO’ya devam ederken başarısız olur , bir UserPasswordHistoryHasBeenSavedkez daha e-postayı gönderme komutunu tetikler ve kullanıcı birden çok kez almış olur .

Senin durumunda kullanıcının gerçekten e-postayı aldığından emin olmak istiyorsun. Bu yüzden ikinci seçeneği ilk tercih edeceğim.


2

Kuyruk sistemleri, düşündüğünüz kadar kırılgan değildir.

Üç süreci de ilişkisel bir db'ye yazıyorsak, ortadaki bir işlemin başarısızlığını ele almak için bir işlem kullanabiliriz.

Nihai taahhüt olmadan, kısmi çalışmalar reddedilir.

Sıra tabanlı sistemlerde, orta işlem hatalarını ele almak için kuyruktan bir mesaj okuduğunuzda benzer seçeneklere sahip olacaksınız.

Örneğin Amazon SQS okunan mesajları gizler. Son bir Sil komutu gönderilmedikçe, mesaj yeniden belirecek veya ölü bir sıraya alınacaktır.

Benzer şekilde 'işlemleri' çeşitli şekillerde uygulayabilirsiniz, esas olarak başarılı işlemin onayı alıncaya kadar mesajın bir kopyasını tutar. Onay zamanında alınmazsa. mesajı tekrar gönderebilir veya manuel dikkat için saklayabilirsiniz.

Potansiyel olarak, bu hatalı mesajları izleyen, ilgili mesajları ve geçmiş durumu bilen ve bir geri alma işlemi gerçekleştiren bir 'geri alma servisi' oluşturabilirsiniz.

Ancak! Sadece hatalı mesajları tekrar göndermek daha iyidir. Bütün bunlardan sonra kenar dava olma eğilimindedir. Bir sunucu feci bir şekilde başarısız oldu ya da belirli bir ileti türünü işlerken bir hata oluştu.

Hata bildirildiğinde, servis tamir edilebilir ve mesajlar başarıyla işlenir. Sistemi bir bütün olarak tutarlı bir duruma getirmek.


2

Burada karşılaştığınız şey iki general sorunudur . Temelde: bir mesajın alındığından ve bu mesaja cevap geldiğinden nasıl emin olabilirsiniz? Çoğu durumda, mükemmel bir çözüm yoktur. Aslında, dağıtılmış bir sistemde , mesajların tam olarak bir kez teslim edilmesini sağlamak çoğu zaman imkansızdır .

İlk belirgin bir açıklama, şifreyi değiştiren hizmetin şifre değiştirme olayını göndermesi gerektiğidir. Bu şekilde, parola geçmişi ve posta gönderme hizmetleri yalnızca, neden değiştiğine bakılmaksızın parola gerçekten değiştiğinde tetiklenir.

Sorununuzu gerçekten çözmek için dağıtılmış işlemleri dikkate almam, bunun yerine en az bir kez mesaj gönderimine ve başarılı işlem yönüne bakıyorum.

  • En azından bir kere

    Parola değiştirme olayının aslında tüm tüketiciler tarafından görülmesini sağlamak için, mesajların "en az bir kez" tarzında tüketilebileceği dayanıklı bir iletişim kanalı kullanmanız gerekir. Tüketiciler, yalnızca tamamen işlediklerinde tüketildiği gibi bir mesajı kabul eder. Örneğin, bir tarihçe girişi yazarken parola geçmişi hizmeti çökerse, yeniden başlattıktan sonra aynı parola değiştirme olayını yeniden okur ve tekrar dene, bu olayı kendi başına tarihe yazıldıktan sonra salt okunur olarak kabul eder. Mesajlar onaylanıncaya kadar tekrar gönderme yeteneğine bağlı olarak bir mesaj sırası çözümü seçmelisiniz.

  • Idempotence

    En az bir kez teslimat gerçekleştirildikten sonra, bir mesaj tüketicinin kesintiye uğratılmasından ve daha sonra yeniden işlenmesinden önce bir mesajın kısmen işlenmesi sırasında meydana gelen yinelenen eylemler sorunu var. Her hizmeti tasarlayarak çözülmesi gerekir, bu yüzden iddiasızdır. Yaptığı yazılar ya olumsuz etkiler olmadan birden çok kez olabilir ya da bir eylemi birden fazla kez yapmaktan kaçındığı ve hangi eylemleri gerçekleştirdiği kendi deposunu saklar. Posta gönderme durumunda, muhtemelen doğru bir şekilde davranmasını sağlamaya değmeyeceğini ve ara sıra iki kez gönderilen bir postanın iyi olabileceğini göreceksiniz.

Her durumda, hizmetlerinizi ne kadar mikro yaptığınıza dikkat edin. Parola geçmişi hizmetinizin gerçekten parola değiştirme hizmetinden bağımsız olması gerekiyor mu?


1

Cevapların çoğuna katılmıyorum.

  1. E-postayı şimdi gönderin “Birisi şifrenizi değiştirdi. Sen olsaydın bir şey yapmana gerek kalmazdı. Panik değilse. ”Bu geldiğinde gelir.
  2. Şifreyi değiştir. Sonunda tutarlı olmana rağmen. Bu oturumun kullanıcı tarafından yapılan değişiklikleri görmesini sağlamak istiyorsunuz.

Ekleyebileceğiniz başka tutarlılık vaatleri var.

  • Değişikliklerin zaman sırasına göre yapıldığından emin olun.
  • Bir kullanıcının asla geri alma işlemi görmediğinden emin olun, ancak diğer kullanıcılar hala değişikliği göremiyor olabilir.
  • Diğerleri var

Bu ilave tutarlılıkların, başvuru işlemlerine bağlı olarak uygulanması gerekecektir.


“Tarihi güncelle” derken ne demek istediğinizi anlamadım ama lütfen geçmişi değiştirmeyin. Eğer DAG’ı yeni uzatıyorsanız, bu durum şu andaki durumun değişmesine neden olmalıdır. Bağımsız değiller. Eğer öyleyse, olanları yansıtan tarihe güvenemezsiniz. (ve son ama en az, şifreler bkz saklamayın değil nasıl mağaza şifrelerine )


E-postayı başlangıçta gönderebilirseniz, yaklaşımınız iyidir. E-postayla birlikte bir şeyler göndermek zorundaysanız. Belki de tutarlılık sağlandıktan sonra elde edilebilecek bir tür bağlantı / veri olabilir, o zaman önce e-postayı gönderemezsiniz. Ben de böyle yorumladım consider asking the organization first.. Muhtemelen haklısın. Ancak, geri alamayacağımız olayları şartlandırmanın önemli olduğunu tespit ettim. Örneğin son kullanıcıya bildirimler. Kullanıcı verilerinin gerçek durumuna ilişkin bildirimde bulunmak, kötü bir izlenim bırakabilir.
Laiv

Bununla birlikte, bu özel senaryoda (şifre değişikliği bildirimi), bu yaklaşıma katılıyorum dedi. İhtiyaçları karşıladığı anda.
Laiv
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.