Mikro hizmetler için en çok kabul edilen işlem stratejisi nedir?


80

Gördüğüm en önemli sorunlardan biri, mikro hizmetlere sahip bir sistemde ortaya çıkıyor, işlemlerin farklı hizmetlere yayıldıklarında çalışma şekli. Kendi mimarimiz içinde, bunu çözmek için dağıtılmış işlemleri kullanıyoruz, ancak kendi sorunları ile geliyorlar. Özellikle çıkmazlar şu ana kadar bir acı oldu.

Diğer bir seçenek, sisteminizdeki akışları bilen ve tüm sisteminize yayılan bir arka plan işlemi olarak sizin için geri dönüşler ile ilgilenecek bir tür ısmarlama işlem yöneticisi gibi görünmektedir (bu nedenle diğer hizmetlerin geri alınmasını sağlayacaktır. ve eğer aşağılarsa, daha sonra onlara bildir).

Kabul edilen başka bir seçenek var mı? Bunların her ikisinin de dezavantajları vardır. Birincisi kilitlenmelere ve bir sürü başka soruna neden olabilir, ikincisi veri tutarsızlığına yol açabilir. Daha iyi seçenekler var mı?


Emin olmak için, bu aynı anda birçok müşteri tarafından aynı anda mı yoksa sadece bir defa mı kullanılıyor?
Marcel

2
Bu soruyu kendine has bir soruyla sormaya çalışıyordum, Marcel. Ancak her ikisini de yapacak kadar büyük bir sistem kullandığımızı varsayalım ve ikisini de destekleyen bir mimariye sahip olmak istiyoruz.
Kristof

4
Bu kötü ifade edilmiş, ancak çok önemli bir sorudur. Çoğu kişi "işlemler" hakkında düşündüğünde, işlemlerin atomikliği, izolasyonu veya dayanıklılık yönleri hakkında değil, yalnızca münhasırlığı düşünürler. Asıl soru, "Bir mikro hizmet mimarisi verilen bir ACID uyumlu sistemi nasıl yaratıyorsunuz? Sadece tutarlılığı uygulamak ve ACID'nin geri kalan kısmını kullanmak gerçekten yararlı değil. Kötü verileri sevmiyorsanız.
Jeff Fischer

10
Daha az "kötü ifadeli" yapmak için sorumu her zaman değiştirmeyi deneyebilirsiniz, Jeff Fischer.
Kristof,

Bu soru ve tartışma, SO hakkındaki diğer soru ile yakından ilgilidir .
Paulo Merson

Yanıtlar:


42

Genel yaklaşım, bu mikro hizmetleri mümkün olduğunca izole etmek - tek bir birim olarak ele almaktır. Daha sonra işlemler bir bütün olarak hizmet kapsamında geliştirilebilir (yani normal DB işlemlerinin bir parçası değil, yine de serviste dahili DB işlemleri olsa da).

İşlemlerin nasıl gerçekleştiğini ve hizmetleriniz için nasıl bir anlam ifade ettiğini düşünün, orijinal işlemi gerçekleştiren bir geri alma mekanizması ya da gerçek işlemi taahhüt ettiği söylenene kadar orijinal işlemi ayıran 2 aşamalı bir taahhüt sistemi uygulayabilirsiniz. Tabii ki bu iki sistem de kendi sisteminizi uyguladığınız anlamına geliyor, ancak o zaman zaten mikro hizmetlerinizi uyguluyorsunuz.

Finansal hizmetler her zaman bu tür işler yapar - parayı bankamdan bankanıza taşımak istersem, DB'de yapacağınız tek bir işlem yoktur. Her iki bankanın da hangi sistemde çalıştığını bilmiyorsunuz, bu nedenle her birine mikro hizmetleriniz gibi etkili davranmalısınız. Bu durumda, bankam paramı hesabımdan bir tutma hesabına aktaracak ve bankanıza bir miktar paraları olduğunu söyleyecektir, eğer bu başarısız olursa, bankam hesabımı göndermeye çalıştıkları parayla iade edecektir.


5
Geri ödemenin asla başarısız olamayacağını varsayıyorsunuz.
Sanjeev Kumar Dangi 11

9
@SanjeevKumarDangi daha az muhtemeldir ve başarısız olsa bile, holding hesabı ve gerçek hesap bankanın kontrolünde olduğu için kolayca kullanılabilir.
gldraphael

30

Standart bilgeliğin asla mikro hizmet sınırlarını aşacak işlemlere sahip olmadığını düşünüyorum. Herhangi bir veri setinin gerçekten başkalarının atomik olarak tutarlı olması gerekiyorsa, bu iki şey birbirine aittir.

Bu, bir sistemi tamamen tasarlayana kadar hizmetlere bölmenin çok zor olmasının nedenlerinden biridir. Hangi modern dünyada muhtemelen yazılı anlamına gelir ...


37
Bu tür bir yaklaşım, tüm mikro servislerin sonunda tek bir monolitik uygulamaya birleştirilmesine çok iyi yol açabilir.
Slava Fomin II

4
Bu doğru yaklaşım. Aslında basit: Hizmetler arasında bir işleme ihtiyacınız varsa, hizmetleriniz yanlıştır: onları yeniden tasarlayın! @SlavaFominII söyledikleriniz sadece bir mikro hizmet sisteminin nasıl tasarlandığını bilmiyorsanız geçerlidir. Kendinizi mikro hizmet yaklaşımı ile savaşırken bulursanız, yapma, monolith'iniz kötü bir mikro hizmet tasarımından daha iyi olacaktır. Yalnızca doğru servis sınırlarını bulduğunuzda, monolit'i servislere ayırmanız gereken zamandır. Aksi takdirde, mikro hizmetleri kullanmak doğru mimari bir seçim değildir, sadece yutturmaca izler.
Francesc Castells

@FrancescCastells Eğer hizmetlerimiz gerçekten diğer hizmetler arasında işlem gerektiriyorsa, sınırlı bağlamları görmezden gelmemiz ve hizmetlerimizi tek bir işlemle sonuçlanacak şekilde modellememiz gerektiği anlamına geliyor mu? Ben mikro hizmetlerde yeni bir kız çocuğum, hala saf görünüyorsa sorumu affetmeye devam ediyorum ....: D: D
Bilbo Baggins

@BilboBaggins Sınırlı bağlamları görmezden geldiğinin tersini kastediyorum. Tanım olarak işlemlerin birçoğu boyunca değil sınırlı bir bağlamda gerçekleşir. Bu nedenle, mikro hizmetlerinizi sınırlı bağlamlarınızla birlikte doğru tasarlarsanız, işlemleriniz birden fazla hizmeti kapsamamalıdır. İhtiyacınız olan şeylerin bir zamanlar işlem değil, işlerin düzgün gitmediği durumlarda nihai tutarlılığın ve uygun telafi edici işlemlerin daha iyi ele alınması olduğunu unutmayın.
Francesc Castells

Ben senin fikrini anlamıyorum, bunu bir sohbette tartışabileceğimiz bir şans var mı?
Bilbo Baggins

17

Eğer uygulamanızda tutarlılık güçlü bir gereklilikse, mikro hizmetlerin daha iyi bir yaklaşım olup olmadığını kendinize sormalısınız. Martin Fowler’ın dediği gibi :

Mikro-servisler, merkezi olmayan veri yönetimi konusundaki haklı ısrarları nedeniyle nihai tutarlılık sorunlarını ortaya koymaktadır. Bir monolith ile, bir çok şeyi tek bir işlemle birlikte güncelleyebilirsiniz. Mikro hizmetlerin güncellenmesi için birden fazla kaynak gerekir ve dağıtılmış işlemler kaşlarını çatar (iyi sebeplerden dolayı). Şimdi, geliştiricilerin tutarlılık sorunlarının farkında olmaları ve kodun pişman olacağı herhangi bir şey yapmadan önce işlerin ne zaman senkronize edilmediğini tespit etmeleri gerekir.

Fakat belki de sizin durumunuzda Uygunluk durumundaki Tutarlılığı feda edebilirsiniz.

İş süreçleri genellikle düşündüğünüzden daha fazla tutarsızlığa karşı daha toleranslıdır, çünkü işletmeler genellikle mevcudiyeti daha fazla ödüllemektedir.

Ancak, mikro hizmetlerde dağıtılmış işlemler için bir strateji olup olmadığını da kendime soruyorum, ancak maliyetler çok yüksek. Martin Fowler ve CAP teoreminin her zaman mükemmel makalesiyle size iki sentimi vermek istedim .


1
Dağıtılmış ticari işlemlerde, tutarlılık bazen bir iş akışı motoru veya dikkatle tasarlanmış bir sıra gibi bir düzenleme katmanı eklenerek ele alınmaktadır. Bu katman tüm iki aşamayı taahhüt eder ve geri alır ve mikro hizmetlerin belirli iş mantığına odaklanmasını sağlar. Ancak CAP’a dönersek, bulunabilirliğe ve tutarlılığa yatırım yapmak performansı mağdur eder. Mikro hizmetler, OOP'taki işinizi içeren birçok ayrık sınıfla nasıl karşılaştırılır?
Greg,


1
+1. Bir mikro hizmet bağlamında, verinin tüm “çeken” görünümlerinin somutlaştırılmış görünümler olarak uygulanabilmesi için neden işlemlerin hiç istendiğini merak ediyorum. Örneğin, eğer bir mikro hizmet bir hesaptan ve diğer kredilerden başka bir hesaba borçlar uygularsa, bakiye görünümleri yalnızca eşleşmemiş kredilerin ve borçların maddileşmiş görünümün tamponunda olacağı kredi çiftlerini ve borçlarını dikkate alacaktır.
Sentinel

16

Buradaki cevapların en az birinde ve ayrıca web üzerinde başka bir yerde önerildiği gibi, iki varlık arasında tutarlılığa ihtiyaç duymanız durumunda normal bir işlem içinde varlıkları birlikte sürdüren bir mikro hizmet tasarlamak mümkündür.

Ancak aynı zamanda, işletmelerin gerçekten aynı mikro hizmete ait olmadıkları, örneğin satış kayıtlarını ve sipariş kayıtlarını (satışın gerçekleşmesi için bir şeyler sipariş ettiğinizde) durumunuz iyi olabilir. Bu gibi durumlarda, iki mikro hizmet arasında tutarlılığı sağlamak için bir yol isteyebilirsiniz.

Geleneksel olarak dağıtılmış işlemler kullanılmıştır ve deneyimlerime göre, kilitlemenin sorun olacağı bir boyuta ölçeklenene kadar iyi çalışırlar. Kilitlemeyi rahatlatabilirsiniz, böylece yalnızca ilgili kaynaklar (örneğin satılan ürün) bir devlet değişikliği kullanılarak "kilitlenir", ancak burası zorlaşmaya başladığı yerdir, çünkü tüm bölgeleri inşa etmeniz gereken bölgeye giriyorsunuzdur. Bunu yapmanın mantığı, kendin yapmak yerine, bir veritabanını sizin için idare edeceğini söylemek.

Bu karmaşık konuyu ele almak için kendi işlem çerçevelerini oluşturma yoluna giren şirketlerle çalıştım, ancak bunu önermiyorum çünkü pahalı ve olgunlaşması zaman alıyor.

Tutarlılık sağlayan sisteminize cıvatalanabilen ürünler var. Bir iş süreci motoru iyi bir örnektir ve genellikle tutarlılığı eninde sonunda ve tazminat kullanarak ele alırlar . Diğer ürünler benzer şekilde çalışır. Genelde müşteri (ler) in yanında tutarlılık ve işlemlerle uğraşan ve asıl iş işlemlerini yapmak için (mikro) hizmetleri çağıran bir yazılım katmanıyla sonuçlanırsınız . Böyle bir ürün, Java EE çözümleriyle kullanılabilecek genel bir JCA konektörüdür (şeffaflık için: Ben yazarım). Daha fazla ayrıntı ve burada ortaya konan konuların daha derin bir tartışması için http://blog.maxant.co.uk/pebble/2015/08/04/1438716480000.html adresine bakın .

İşlemleri ve tutarlılığı ele almanın bir başka yolu, bir çağrıyı bir mikro hizmete yapılan çağrıya bir mesaj kuyruğu gibi işlem gören bir şeye sarmaktır. Satış kayıt / sipariş kayıt örneğini yukarıdan alın - satış mikro servisinin, satışa veri tabanına yazılan işlemle ilgili olan sipariş sistemine bir mesaj göndermesine izin verebilirsiniz. Sonuç, çok iyi ölçeklenen asenkron bir çözümdür . Ağ soketleri gibi teknolojileri kullanarak, çoğu zaman asenkron çözümleri büyütmekle ilgili olan engelleme sorununu bile çözebilirsiniz. Bunun gibi kalıplarla ilgili daha fazla fikir edinmek için makalelerimden bir başkasına bakın: http://blog.maxant.co.uk/pebble/2015/08/11/1439322480000.html .

Hangi çözümü seçerseniz seçin, sisteminizin yalnızca küçük bir bölümünün tutarlı olması gereken şeyleri yazacağını bilmek önemlidir - çoğu erişimin salt okunur olması muhtemeldir. Bu nedenle, işlem yönetimini yalnızca sistemin ilgili bölümlerine yerleştirin, böylece yine de iyi ölçeklenebilir.


Bu süre zarfında, sürecin her adımının tamamen işlemsel olduğu, süreci asenkronize bir süreç haline getirmeyi ciddiye alması gerektiğini söyleyebilirim. Detaylar için buraya bakın: blog.maxant.co.uk/pebble/2018/02/18/1518974314273.html
Ant Kutschera

"Satış rekoru / sipariş kaydı örneğini yukarıdan yapın - satış mikro servisinin, satışı veritabanına yazan aynı işlemde işlenen sipariş sistemine bir mesaj göndermesine izin verebilirsiniz." Önerdiğiniz şeyin temel olarak dağıtılmış bir işlem olup olmadığından emin değilsiniz, bu durumda, geri alma senaryosunu nasıl ele alırsınız? Örneğin mesaj, mesaj kuyruğuna geçer ancak DB tarafında geri alınır.
Mart’ta

@sactiw aklıma iki aşamalı bir işlem yapıp yapmadığımdan emin değilim, ancak şimdi bundan kaçınıyorum ve bunun yerine işletme verilerimi yazdım ve bir işlemin kuyruğumun DB'sine bir işlemde kuyruğa eklenmesi gerektiği gerçeğini yazdım. . "Fact" aka a "komutu", işlem tamamlandıktan sonra otomatik bir yeniden deneme mekanizması kullanılarak zaman uyumsuz olarak işlenir. Örnek için 2018-03-10 tarihli blog makalesine bakın. Uygulaması daha kolay olduğu sürece geri alma stratejisi lehine geri alma veya telafi etmekten kaçının.
Ant Kutschera


1

Benim rahat ettiğimden daha fazla taviz veren birçok çözüm var. Kullanım durumunuz farklı bankalar arasında para taşımak gibi karmaşıksa, daha keyifli alternatifler imkansız olabilir. Ancak, ortak senaryoda neler yapabileceğimize bakalım, burada mikro hizmet kullanımının veritabanı veritabanı işlemlerimizle etkileşime girdiği görülebilir.

Seçenek 1: Mümkünse, işlem gereksiniminden kaçının

Daha önce açık ve belirtilmiş, ancak başarabilirsek ideal. Bileşenler aslında aynı mikro hizmete ait miydi? Veya işlem gereksiz olacak şekilde sistem (ler) ini yeniden tasarlayabilir miyiz? Muhtemel olmayan işlemeyi kabul etmek en uygun fedakarlıktır.

Seçenek 2: Bir sıra kullanın

Diğer hizmetin ne yapmasını istediğimizde başaracağına kesin olarak karar verirsek, bir tür kuyruk aracılığıyla arayabiliriz. Sıraya alınan öğe daha sonra alınmaz, ancak öğenin sıraya alındığından emin olabiliriz .

Örneğin, bir varlık eklemek ve tek bir işlem olarak bir e-posta göndermek istediğimizi söyleyin. Posta sunucusunu aramak yerine, e-postayı bir tabloda sıraya koyarız.

Begin transaction
Insert entity
Insert e-mail
Commit transaction

Net bir dezavantajı, çoklu mikro servislerin aynı tabloya erişmesi gerekmesidir.

Seçenek 3: Dış işi en son, işlemi tamamlamadan önce yapın

Bu yaklaşım, işlem yapmanın başarısız olma ihtimalinin düşük olduğu varsayımına dayanmaktadır.

Begin transaction
Insert entity
Insert another entity
Make external call
Commit transaction

Sorgular başarısız olursa, harici arama henüz gerçekleşmedi. Dış arama başarısız olursa, işlem asla gerçekleştirilmez.

Bu yaklaşım yalnızca bir dış görüşme yapabileceğimiz ve son olarak yapılması gereken sınırlamalarla gelir (yani sonuçlarını sorgularımızda kullanamayız).

Seçenek 4: Bekleyen bir durumda bir şeyler oluşturun

Yayınlandığı gibi burada , biz, birden microservices farklı bileşenleri oluşturmak bekleme durumunda her olmayan transactionally sahip olabilir.

Herhangi bir doğrulama yapılır, ancak kesin bir durumda hiçbir şey oluşturulmaz. Her şey başarıyla oluşturulduktan sonra, her bir bileşen etkinleştirilir. Genellikle, bu işlem çok basittir ve yanlış giden bir şey olma olasılığı o kadar küçüktür ki, aktivasyonu işlemsiz olarak yapmayı bile tercih edebiliriz.

En büyük dezavantajı muhtemelen bekleyen öğelerin varlığını hesaba katmamız gerektiğidir. Herhangi bir seçim sorgusu, bekleyen verilerin eklenip eklenmeyeceğini dikkate almalıdır. Çoğu bunu görmezden gelmeli. Ve güncellemeler tamamen başka bir hikaye.

Seçenek 5: Mikro hizmetin sorgusunu paylaşmasına izin verin

Diğer seçeneklerin hiçbiri sizin için yapmıyor mu? Öyleyse sıradışı olsun .

Şirkete bağlı olarak, bu kabul edilemez olabilir. Farkındayım. Bu sıra dışı. Kabul edilebilir değilse, başka bir rotaya gidin. Ancak bu durumunuza uygunsa, sorunu basit ve güçlü bir şekilde çözer. Sadece en kabul edilebilir uzlaşma olabilir.

Sorguları birden fazla mikro hizmetten basit ve tek bir veritabanı işlemine dönüştürmenin bir yolu var.

Sorguyu yerine çalıştırmak yerine döndürün.

Begin transaction
Execute our own query
Make external call, receiving a query
Execute received query
Commit transaction

Ağ üzerinden, her mikro hizmetin her bir veritabanına erişebilmesi gerekir. Bunu gelecekteki ölçeklendirme konusunda da aklınızda bulundurun.

İşlemde yer alan veritabanları aynı sunucudaysa, bu normal bir işlem olacaktır. Farklı sunuculardalarsa, dağıtılmış bir işlem olur. Kod ne olursa olsun aynıdır.

Sorgu, bağlantı türü, parametreleri ve bağlantı dizesi dahil olmak üzere alınır. Akışı okunabilir kılarak, temiz bir çalıştırılabilir Command sınıfına sarabiliriz: Mikro hizmet çağrısı, işlemimizin bir parçası olarak yürüttüğümüz bir Komutla sonuçlanır.

Bağlantı dizesi, kaynak mikro hizmetin bize verdiği şeydir, bu nedenle tüm amaç ve amaçlar için, sorgunun hala bu mikro hizmet tarafından gerçekleştirildiği kabul edilir. Sadece fiziksel olarak müşteri mikro servisini yönlendiriyoruz. Bu bir fark yaratır mı? Başka bir sorgu ile aynı işleme koymamızı sağlıyor.

Eğer uzlaşma kabul edilebilirse, bu yaklaşım bize bir mikro hizmet mimarisinde, bir monolith uygulamasının basit işlemselliğini verir.


0

Servis sınırlarınızı belirlemekle - sorunların ayrıştırılması ile başlardım . Doğru yapıldığında, hiçbir zaman hizmetler arasında işlem yapmanız gerekmez.

Farklı hizmetlerin kendi verileri, davranışları, motivasyon güçleri, hükümeti, iş kuralları vb. Vardır. İşletmenizin sahip olduğu üst düzey yetenekleri listelemek iyi bir başlangıçtır. Örneğin, pazarlama, satış, muhasebe, destek. Bir başka başlangıç ​​noktası örgütsel yapıdır, ancak bir ihtirasın olduğunu unutmayın - bazı nedenlerden dolayı (örneğin siyasi) en uygun işletme ayrıştırma planı olmayabilir. Daha katı bir yaklaşım Değer zinciri analizidir . Unutmayın, hizmetleriniz insanları da içerebilir, kesinlikle bir yazılım değildir. Servisler birbirleriyle olaylarla iletişim kurmalıdır .

Bir sonraki adım bu hizmetleri kesmektir. Sonuç olarak hala nispeten bağımsız topaklar elde edersiniz . Bir tutarlılık birimini temsil ediyorlar. Başka bir deyişle, içlerinin tutarlı ve ACID olması gerekir. Agregalar birbirleriyle de olaylarla iletişim kurar.

Etki alanınızın önce tutarlılık gerektirdiğini düşünüyorsanız, tekrar düşünün. Büyük ve görev kritik sistemlerin hiçbiri bu akılda tutularak inşa edilmemiştir. Hepsi dağılmış ve sonunda tutarlı. Pat Helland'ın klasik makalesini kontrol et .

İşte size dağıtılmış bir sistemin nasıl oluşturulacağı hakkında bazı pratik ipuçları.

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.