Eşzamanlılık ve Hata Toleransı Kolaylaştırıldı: Örneklerle Bir Akka Eğitimi

Yayınlanan: 2022-03-11

Meydan okuma

Eşzamanlı programlar yazmak zordur. İplikler, kilitler, yarış koşulları vb. ile uğraşmak hataya oldukça açıktır ve okunması, test edilmesi ve bakımı zor olan kodlara yol açabilir.

Bu nedenle çoğu, çoklu iş parçacığından tamamen kaçınmayı tercih eder. Bunun yerine, ihtiyaç duyulan eşzamanlı veya eşzamansız işlemleri işlemek için harici hizmetlere (veritabanları, kuyruklar vb.) güvenerek yalnızca tek iş parçacıklı süreçleri kullanırlar. Bu yaklaşım bazı durumlarda meşru bir alternatif olsa da, uygulanabilir bir seçenek olmadığı birçok senaryo vardır. Ticaret veya bankacılık uygulamaları veya gerçek zamanlı oyunlar gibi birçok gerçek zamanlı sistem, tek iş parçacıklı bir işlemin tamamlanmasını bekleme lüksüne sahip değildir (cevaba şimdi ihtiyaçları var!). Diğer sistemler o kadar bilgi işlem veya kaynak açısından yoğundur ki, kodlarına paralelleştirme eklemeden çalışması çok fazla zaman (bazı durumlarda saatler hatta günler) alır.

Oldukça yaygın bir tek iş parçacıklı yaklaşım (örneğin, Node.js dünyasında yaygın olarak kullanılır), olaya dayalı, engelleyici olmayan bir paradigma kullanmaktır. Bu, bağlam anahtarlarından, kilitlerden ve engellemeden kaçınarak performansa yardımcı olsa da, aynı anda birden çok işlemci kullanma sorunlarını çözmez (bunu yapmak, birden çok bağımsız işlemi başlatmayı ve bunlar arasında koordinasyon yapmayı gerektirir).

Bu, eşzamanlı bir uygulama oluşturmak için ipliklerin, kilitlerin ve yarış koşullarının derinliklerine yolculuk yapmaktan başka seçeneğiniz olmadığı anlamına mı geliyor?

Akka çerçevesi sayesinde cevap hayır. Bu öğretici, Akka örneklerini tanıtır ve eşzamanlı, dağıtılmış uygulamaların uygulanmasını kolaylaştırma ve basitleştirme yollarını araştırır.

Akka Çerçevesi nedir?

Bu gönderi, Akka'yı tanıtıyor ve eşzamanlı, dağıtılmış uygulamaların uygulanmasını nasıl kolaylaştırdığını ve basitleştirdiğini araştırıyor.

Akka, JVM üzerinde yüksek düzeyde eşzamanlı, dağıtılmış ve hataya dayanıklı uygulamalar oluşturmak için bir araç takımı ve çalışma zamanıdır. Akka, hem Scala hem de Java için sağlanan dil bağlamalarıyla Scala'da yazılmıştır.

Akka'nın eşzamanlılığı ele alma yaklaşımı, Aktör Modelini temel alır. Aktör tabanlı bir sistemde, her şey bir aktördür, aynı şekilde nesne yönelimli tasarımda her şey bir nesnedir. Yine de önemli bir fark - özellikle tartışmamızla ilgili - Aktör Modelinin eş zamanlı bir model olarak hizmet etmek üzere özel olarak tasarlanmış ve tasarlanmış olmasıdır, oysa nesne yönelimli model değildir. Daha spesifik olarak, bir Scala aktör sisteminde aktörler, herhangi bir sıralılık varsayımı olmaksızın etkileşimde bulunur ve bilgi paylaşır. Aktörlerin birbirleriyle bilgi paylaştığı ve birbirlerine görev verdikleri mekanizma mesaj iletmedir.

İleti dizileri oluşturma ve zamanlama, ileti alma ve gönderme, yarış koşulları ve senkronizasyonu ele almanın tüm karmaşıklığı, şeffaf bir şekilde ele alınması için çerçeveye havale edilir.

Akka, aktörler ile altta yatan sistem arasında, aktörlerin yalnızca mesajları işlemesi gereken bir katman oluşturur. İleti dizileri oluşturma ve zamanlama, ileti alma ve gönderme, yarış koşulları ve senkronizasyonu ele almanın tüm karmaşıklığı, şeffaf bir şekilde ele alınması için çerçeveye havale edilir.

Akka, Reaktif Manifesto'ya sıkı sıkıya bağlıdır. Reaktif uygulamalar, geleneksel çok iş parçacıklı uygulamaları aşağıdaki gereksinimlerden bir veya daha fazlasını karşılayan bir mimariyle değiştirmeyi amaçlar:

  • Olay odaklı. Actors'ı kullanarak, istekleri eşzamansız olarak işleyen ve yalnızca engelleme yapmayan işlemleri kullanan kod yazılabilir.
  • Ölçeklenebilir. Akka'da hem mesaj geçişi hem de konum şeffaflığı sayesinde kodu değiştirmeden düğüm eklemek mümkündür.
  • esnek. Herhangi bir uygulama hatalarla karşılaşacak ve zamanın bir noktasında başarısız olacaktır. Akka, kendi kendini iyileştirme sistemini kolaylaştırmak için “denetleme” (hata toleransı) stratejileri sunar.
  • Duyarlı. Günümüzün yüksek performanslı ve hızlı yanıt veren uygulamalarının birçoğunun kullanıcıya hızlı geri bildirim vermesi ve bu nedenle olaylara son derece zamanında tepki vermesi gerekir. Akka'nın engelleme yapmayan, mesaja dayalı stratejisi bunu başarmaya yardımcı olur.

Akka'da Aktör Nedir?

Bir aktör, esasen, mesajları alan ve bunları işlemek için harekete geçen bir nesneden başka bir şey değildir. Mesajın kaynağından ayrılmıştır ve tek sorumluluğu, aldığı mesajın türünü doğru bir şekilde tanımak ve buna göre harekete geçmektir.

Bir aktör, bir mesaj aldıktan sonra aşağıdaki eylemlerden birini veya birkaçını gerçekleştirebilir:

  • Bazı işlemleri kendisi yürütün (hesaplamalar yapmak, kalıcı veriler, harici bir web hizmetini aramak vb.)
  • Mesajı veya türetilmiş bir mesajı başka bir aktöre iletin
  • Yeni bir aktör oluşturun ve mesajı ona iletin

Alternatif olarak, oyuncu, uygun gördüğü takdirde mesajı tamamen görmezden gelmeyi seçebilir (yani, eylemsizliği seçebilir).

Bir aktör uygulamak için, akka.actor.Actor özelliğini genişletmek ve alma yöntemini uygulamak gerekir. Bir aktöre bir mesaj gönderildiğinde, bir aktörün alma yöntemi (Akka tarafından) çağrılır. Tipik uygulaması, mesaj türünü belirlemek ve buna göre tepki vermek için aşağıdaki Akka örneğinde gösterildiği gibi kalıp eşleştirmeden oluşur:

 import akka.actor.Actor import akka.actor.Props import akka.event.Logging class MyActor extends Actor { def receive = { case value: String => doSomething(value) case _ => println("received unknown message") } }

Model eşleştirme, geri aramalara dayalı karşılaştırılabilir bir uygulamaya kıyasla "daha temiz" ve gezinmesi daha kolay kod üretme eğiliminde olan mesajları işlemek için nispeten zarif bir tekniktir. Örneğin, basit bir HTTP istek/yanıt uygulamasını düşünün.

İlk olarak, JavaScript'te geri arama tabanlı bir paradigma kullanarak bunu uygulayalım:

 route(url, function(request){ var query = buildQuery(request); dbCall(query, function(dbResponse){ var wsRequest = buildWebServiceRequest(dbResponse); wsCall(wsRequest, function(wsResponse) { sendReply(wsResponse); }); }); });

Şimdi bunu kalıp eşleştirme tabanlı bir uygulamayla karşılaştıralım:

 msg match { case HttpRequest(request) => { val query = buildQuery(request) dbCall(query) } case DbResponse(dbResponse) => { var wsRequest = buildWebServiceRequest(dbResponse); wsCall(dbResponse) } case WsResponse(wsResponse) => sendReply(wsResponse) }

Geri arama tabanlı JavaScript kodu kuşkusuz kompakt olsa da, okuması ve gezinmesi kesinlikle daha zordur. Buna karşılık, model eşleştirmeye dayalı kod, hangi vakaların değerlendirildiğini ve her birinin nasıl ele alındığını hemen daha belirgin hale getirir.

Aktör Sistemi

Karmaşık bir problemi alıp yinelemeli olarak daha küçük alt problemlere bölmek genel olarak sağlam bir problem çözme tekniğidir. Bu yaklaşım, bakımı nispeten kolay olan, çok az yedekli veya hiç yedekli temiz, modülerleştirilmiş kod verme eğiliminde olduğundan, bilgisayar biliminde (Tek Sorumluluk İlkesi ile tutarlı olarak) özellikle faydalı olabilir.

Aktör tabanlı bir tasarımda, bu tekniğin kullanılması, oyuncuların Aktör Sistemi olarak bilinen hiyerarşik bir yapı içinde mantıksal olarak düzenlenmesini kolaylaştırır. Aktör sistemi, aktörlerin birbirleriyle etkileşime girdiği altyapıyı sağlar.

Akka çerçevesinde aktör sisteminin çalışma şekline bir örnek.

Akka'da bir aktörle iletişim kurmanın tek yolu bir ActorRef . Bir ActorRef , diğer nesnelerin o aktörün dahili ve durumuna doğrudan erişmesini veya bunları manipüle etmesini engelleyen bir aktöre yapılan bir referansı temsil eder. Mesajlar, aşağıdaki sözdizimi protokollerinden biri kullanılarak bir ActorRef aracılığıyla bir aktöre gönderilebilir:

  • ! (“anlat”) – mesajı gönderir ve hemen geri döner
  • ? (“sor”) – mesajı gönderir ve olası bir yanıtı temsil eden bir Gelecek döndürür

Her aktörün, gelen mesajlarının teslim edildiği bir posta kutusu vardır. Varsayılan uygulama FIFO olmak üzere, seçilebilecek birden fazla posta kutusu uygulaması vardır.

Bir aktör, birden çok mesajı işlerken durumu korumak için birçok örnek değişkeni içerir. Akka, bir aktörün her örneğinin kendi hafif iş parçacığında çalışmasını ve mesajların birer birer işlenmesini sağlar. Bu şekilde, geliştiricinin senkronizasyon veya yarış koşulları hakkında açıkça endişelenmesine gerek kalmadan her aktörün durumu güvenilir bir şekilde korunabilir.

Her oyuncuya, Akka Actor API aracılığıyla görevlerini yerine getirmesi için aşağıdaki faydalı bilgiler sağlanır:

  • sender : şu anda işlenmekte olan mesajın göndericisine bir ActorRef
  • context : aktörün içinde çalıştığı bağlamla ilgili bilgi ve yöntemler (örneğin, yeni bir aktör başlatmak için bir actorOf yöntemini içerir)
  • supervisionStrategy : hatalardan kurtulmak için kullanılacak stratejiyi tanımlar
  • self : oyuncunun kendisi için ActorRef
Akka, bir aktörün her örneğinin kendi hafif iş parçacığında çalışmasını ve mesajların birer birer işlenmesini sağlar. Bu şekilde, geliştiricinin senkronizasyon veya yarış koşulları hakkında açıkça endişelenmesine gerek kalmadan her aktörün durumu güvenilir bir şekilde korunabilir.

Bu öğreticileri birbirine bağlamaya yardımcı olması için, bir metin dosyasındaki sözcük sayısını saymanın basit bir örneğini ele alalım.

Akka örneğimizin amaçları doğrultusunda, sorunu iki alt göreve ayıracağız; yani, (1) tek bir satırdaki sözcük sayısını sayan bir "alt" görev ve (2) dosyadaki toplam sözcük sayısını elde etmek için bu satır başına sözcük sayımlarını toplayan bir "üst" görev.

Ana aktör dosyadan her satırı yükleyecek ve sonra o satırdaki kelimeleri sayma görevini bir alt oyuncuya devredecektir. Çocuk bittiğinde, ebeveyne sonucu ile birlikte bir mesaj gönderir. Ebeveyn, (her satır için) kelime sayılarıyla birlikte mesajları alacak ve dosyanın tamamındaki toplam kelime sayısı için bir sayaç tutacak ve tamamlandıktan sonra çağırıcısına geri dönecektir.

(Aşağıda sağlanan Akka öğretici kod örneklerinin yalnızca öğretici olması amaçlandığını ve bu nedenle tüm uç koşulları, performans optimizasyonları vb. ile mutlaka ilgilenmediğini unutmayın. Ayrıca, aşağıda gösterilen kod örneklerinin eksiksiz bir derlenebilir sürümü şurada mevcuttur: bu özü.)

Önce alt StringCounterActor sınıfının örnek bir uygulamasına bakalım:

 case class ProcessStringMsg(string: String) case class StringProcessedMsg(words: Integer) class StringCounterActor extends Actor { def receive = { case ProcessStringMsg(string) => { val wordsInLine = string.split(" ").length sender ! StringProcessedMsg(wordsInLine) } case _ => println("Error: message not recognized") } }

Bu aktörün çok basit bir görevi vardır: ProcessStringMsg mesajlarını (bir metin satırı içeren) tüketmek, belirtilen satırdaki kelime sayısını saymak ve sonucu bir StringProcessedMsg mesajı aracılığıyla göndericiye döndürmek. ! öğesini kullanmak için sınıfımızı uyguladığımızı unutmayın. (“tell”) yöntemi, StringProcessedMsg mesajını göndermek için (yani mesajı göndermek ve hemen geri dönmek için).

Tamam, şimdi dikkatimizi üst WordCounterActor sınıfına çevirelim:

 1. case class StartProcessFileMsg() 2. 3. class WordCounterActor(filename: String) extends Actor { 4. 5. private var running = false 6. private var totalLines = 0 7. private var linesProcessed = 0 8. private var result = 0 9. private var fileSender: Option[ActorRef] = None 10. 11. def receive = { 12. case StartProcessFileMsg() => { 13. if (running) { 14. // println just used for example purposes; 15. // Akka logger should be used instead 16. println("Warning: duplicate start message received") 17. } else { 18. running = true 19. fileSender = Some(sender) // save reference to process invoker 20. import scala.io.Source._ 21. fromFile(filename).getLines.foreach { line => 22. context.actorOf(Props[StringCounterActor]) ! ProcessStringMsg(line) 23. totalLines += 1 24. } 25. } 26. } 27. case StringProcessedMsg(words) => { 28. result += words 29. linesProcessed += 1 30. if (linesProcessed == totalLines) { 31. fileSender.map(_ ! result) // provide result to process invoker 32. } 33. } 34. case _ => println("message not recognized!") 35. } 36. }

Burada pek çok şey oluyor, bu yüzden her birini daha ayrıntılı olarak inceleyelim (aşağıdaki tartışmada atıfta bulunulan satır numaralarının yukarıdaki kod örneğine dayandığını unutmayın)

İlk olarak, işlenecek dosyanın adının WordCounterActor yapıcısına (satır 3) iletildiğine dikkat edin. Bu, aktörün yalnızca tek bir dosyayı işlemek için kullanılacağını gösterir. Bu aynı zamanda, örnek yalnızca bir kez kullanıldığından (yani tek bir dosyayı işlemek için) iş yapıldığında durum değişkenlerini ( totalLines running linesProcessed ve result ) sıfırlama gereğini ortadan kaldırarak geliştirici için kodlama işini basitleştirir. ve sonra atılır.

Ardından, WordCounterActor iki tür iletiyi işlediğini gözlemleyin:

  • StartProcessFileMsg (satır 12)
    • Başlangıçta WordCounterActor başlatan harici aktörden alındı.
    • Alındığında, WordCounterActor önce fazlalık bir istek almadığını kontrol eder.
    • İstek fazlaysa, WordCounterActor bir uyarı oluşturur ve başka bir şey yapılmaz (satır 16).
    • İstek gereksiz değilse:
      • WordCounterActor , gönderene bir başvuruyu fileSender örnek değişkeninde saklar (bunun bir Seçenek[ Option[Actor] ] yerine bir Option[ActorRef] olduğuna dikkat edin - 9. satıra bakın). Bu ActorRef , daha sonra son StringProcessedMsg (aşağıda açıklandığı gibi bir StringCounterActor alt öğesinden alınan) işlerken ona erişmek ve yanıt vermek için gereklidir.
      • WordCounterActor daha sonra dosyayı okur ve dosyadaki her satır yüklendiğinde, bir StringCounterActor çocuğu oluşturulur ve işlenecek satırı içeren bir mesaj ona iletilir (21-24 satırlar).
  • StringProcessedMsg (satır 27)
    • Bir alt StringCounterActor kendisine atanan satırı işlemeyi tamamladığında alındı.
    • Alındığında, WordCounterActor dosya için satır sayacını artırır ve dosyadaki tüm satırlar işlenmişse (yani, totalLines ve linesProcessed eşit olduğunda), nihai sonucu orijinal fileSender gönderir (satır 28-31).

Akka'da aktörler arası iletişimin tek mekanizmasının mesaj geçişi olduğuna bir kez daha dikkat edin. Mesajlar, aktörlerin paylaştığı tek şeydir ve aktörler potansiyel olarak aynı mesajlara eşzamanlı olarak erişebildiğinden, yarış koşullarından ve beklenmedik davranışlardan kaçınmak için bunların değişmez olmaları önemlidir.

Scala'daki vaka sınıfları, desen eşleştirme yoluyla özyinelemeli bir ayrıştırma mekanizması sağlayan normal sınıflardır.

Bu nedenle, varsayılan olarak değişmez olduklarından ve model eşleştirmeyle ne kadar sorunsuz bir şekilde bütünleştiklerinden, mesajları vaka sınıfları biçiminde iletmek yaygındır.

Tüm uygulamayı çalıştırmak için örneği kod örneğiyle sonlandıralım.

 object Sample extends App { import akka.util.Timeout import scala.concurrent.duration._ import akka.pattern.ask import akka.dispatch.ExecutionContexts._ implicit val ec = global override def main(args: Array[String]) { val system = ActorSystem("System") val actor = system.actorOf(Props(new WordCounterActor(args(0)))) implicit val timeout = Timeout(25 seconds) val future = actor ? StartProcessFileMsg() future.map { result => println("Total number of words " + result) system.shutdown } } }
Eşzamanlı programlamada, bir "gelecek", henüz bilinmeyen bir sonuç için esasen bir yer tutucu nesnedir.

Bu sefer nasıl olduğuna dikkat edin ? Mesaj göndermek için kullanılan yöntem. Bu şekilde, arayan kişi, mevcut olduğunda nihai sonucu yazdırmak ve ActorSystem'i kapatarak programdan çıkmak için döndürülen Future'ı kullanabilir.

Akka hata toleransı ve süpervizör stratejileri

Bir aktör sisteminde, her aktör kendi çocuklarının süpervizörüdür. Bir aktör bir mesajı ele alamazsa, kendisini ve tüm çocuklarını askıya alır ve genellikle bir istisna şeklinde amirine bir mesaj gönderir.

Akka'da gözetmen stratejileri, sisteminizin hataya dayanıklı davranışını tanımlamak için birincil ve doğrudan mekanizmadır.

Akka'da bir süpervizörün çocuklarından kendisine sızan istisnalara tepki verme ve bunları ele alma şekline süpervizör stratejisi denir. Süpervizör stratejileri, sisteminizin hataya dayanıklı davranışını tanımladığınız birincil ve basit mekanizmadır.

Bir başarısızlığı belirten bir mesaj bir süpervizöre ulaştığında, aşağıdaki eylemlerden birini gerçekleştirebilir:

  • Çocuğu (ve çocuklarını) içsel durumunu koruyarak devam ettirin. Bu strateji, alt durum hata tarafından bozulmadığında uygulanabilir ve doğru şekilde çalışmaya devam edebilir.
  • İç durumunu temizleyerek çocuğu (ve çocuklarını) yeniden başlatın. Bu strateji, az önce açıklananın tersi senaryoda kullanılabilir. Alt durum hata nedeniyle bozulmuşsa, Gelecekte kullanılmadan önce durumunun sıfırlanması gerekir.
  • Çocuğu (ve çocuklarını) kalıcı olarak durdurun. Bu strateji, hata durumunun düzeltilemeyeceğine inanılan, ancak başarısız olan çocuğun yokluğunda tamamlanabilecek olan operasyonun geri kalanını tehlikeye atmadığı durumlarda kullanılabilir.
  • Kendini durdur ve hatayı yükselt. Süpervizör hatayla nasıl başa çıkacağını bilmediğinde çalıştırılır ve bu nedenle başarısızlık kendi süpervizörüne iletilir.

Ayrıca, bir Aktör, eylemi sadece başarısız olan çocuklara veya kardeşlerine de uygulamaya karar verebilir. Bunun için önceden tanımlanmış iki strateji vardır:

  • OneForOneStrategy : Belirtilen eylemi yalnızca başarısız olan alt öğeye uygular
  • AllForOneStrategy : Belirtilen eylemi tüm alt öğelerine uygular

İşte OneForOneStrategy kullanarak basit bir örnek:

 import akka.actor.OneForOneStrategy import akka.actor.SupervisorStrategy._ import scala.concurrent.duration._ override val supervisorStrategy = OneForOneStrategy() { case _: ArithmeticException => Resume case _: NullPointerException => Restart case _: IllegalArgumentException => Stop case _: Exception => Escalate }

Herhangi bir strateji belirtilmemişse, aşağıdaki varsayılan strateji kullanılır:

  • Aktör başlatılırken bir hata oluştuysa veya oyuncu öldürüldüyse, oyuncu durdurulur.
  • Başka tür bir istisna varsa, aktör basitçe yeniden başlatılır.

Bu varsayılan stratejinin Akka tarafından sağlanan uygulaması aşağıdaki gibidir:

 final val defaultStrategy: SupervisorStrategy = { def defaultDecider: Decider = { case _: ActorInitializationException ⇒ Stop case _: ActorKilledException ⇒ Stop case _: Exception ⇒ Restart } OneForOneStrategy()(defaultDecider) }

Akka, özel denetçi stratejilerinin uygulanmasına izin verir, ancak Akka belgelerinin uyardığı gibi, yanlış uygulamalar engellenen aktör sistemleri (yani kalıcı olarak askıya alınan aktörler) gibi sorunlara yol açabileceğinden dikkatli olun.

Konum şeffaflığı

Akka mimarisi konum şeffaflığını destekler ve aktörlerin aldıkları mesajların nereden kaynaklandığı konusunda tamamen bağımsız olmalarını sağlar. Mesajın göndericisi, aktörle aynı JVM'de veya ayrı bir JVM'de (aynı düğümde veya farklı bir düğümde çalışıyor) bulunabilir. Akka, bu vakaların her birinin oyuncu (ve dolayısıyla geliştirici) için tamamen şeffaf bir şekilde ele alınmasını sağlar. Tek uyarı, birden çok düğüm üzerinden gönderilen iletilerin serileştirilebilir olması gerektiğidir.

Akka mimarisi konum şeffaflığını destekler ve aktörlerin aldıkları mesajların nereden kaynaklandığı konusunda tamamen bağımsız olmalarını sağlar.

Actor sistemleri, herhangi bir özel kod gerektirmeden dağıtılmış bir ortamda çalışacak şekilde tasarlanmıştır. Akka, yalnızca mesaj gönderilecek düğümleri belirten bir yapılandırma dosyasının ( application.conf ) varlığını gerektirir. İşte basit bir yapılandırma dosyası örneği:

 akka { actor { provider = "akka.remote.RemoteActorRefProvider" } remote { transport = "akka.remote.netty.NettyRemoteTransport" netty { hostname = "127.0.0.1" port = 2552 } } }

Birkaç ayrılık ipucu…

Akka çerçevesinin eşzamanlılık ve yüksek performans elde edilmesine nasıl yardımcı olduğunu gördük. Ancak, bu eğitimde belirtildiği gibi, Akka'nın gücünden sonuna kadar yararlanmak için sisteminizi tasarlarken ve uygularken akılda tutulması gereken birkaç nokta vardır:

  • Mümkün olan en geniş ölçüde, her bir aktöre mümkün olan en küçük görev verilmelidir (Tek Sorumluluk İlkesi izlenerek daha önce tartışıldığı gibi)
  • Aktörler olayları (yani, mesajları işleme) eşzamansız olarak ele almalı ve engellememelidir, aksi takdirde performansı olumsuz etkileyebilecek bağlam değişimleri meydana gelecektir. Spesifik olarak, aktörü engellememek için bir Gelecekte engelleme işlemleri (IO vb.) gerçekleştirmek en iyisidir; yani:

     case evt => blockingCall() // BAD case evt => Future { blockingCall() // GOOD }
  • Mesajlarınızın hepsinin değişmez olduğundan emin olun, çünkü onları birbirine ileten aktörler aynı anda kendi dizilerinde koşarlar. Değişken mesajların beklenmeyen davranışlarla sonuçlanması muhtemeldir.
  • Düğümler arasında gönderilen iletiler serileştirilebilir olması gerektiğinden, iletiler ne kadar büyükse, serileştirmenin, göndermenin ve seri durumdan çıkarmanın o kadar uzun süreceğini ve bunun da performansı olumsuz yönde etkileyebileceğini akılda tutmak önemlidir.

Çözüm

Scala'da yazılan Akka, karmaşıklığın çoğunu geliştiriciden gizleyerek yüksek düzeyde eşzamanlı, dağıtılmış ve hataya dayanıklı uygulamaların geliştirilmesini basitleştirir ve kolaylaştırır. Akka'nın hakkını tam anlamıyla yerine getirmek, bu tek öğreticiden çok daha fazlasını gerektirecektir, ancak umarım bu giriş ve örnekleri, daha fazlasını okumak istemeniz için yeterince büyüleyici olmuştur.

Amazon, VMWare ve CSC, Akka'yı aktif olarak kullanan lider şirketlere sadece birkaç örnektir. Daha fazla bilgi edinmek ve Akka'nın projeniz için de doğru cevap olup olmayacağını keşfetmek için resmi Akka web sitesini ziyaret edin.