2014-10-20 9 views
7

Akka Cluster-Sharding, bir kullanım durumu ile iyi uyuşuyor gibi görünüyor Akka düğümleri boyunca tek bir durum halindeki kalıcı aktörler oluşturmak zorundayım.Akka cluster-sharding: Can Entry aktörleri dinamik sahne var

Bunu oluşturmak için argüman gerektiren bir Giriş aktör türüne sahip olmanızın mümkün olup olmadığı net değil. Ya da Giriş aktörünün bu bilgiyi nasıl aldığını yeniden gözden geçirmem gerekebilir. ClusterSharding.start Oysa

Object Account { 
    def apply(region: String, accountId: String): Props = Props(new Account(region, accountId)) 
} 

class Account(val region: String, val accountId: String) extends Actor with PersistentActor { ... } 

tüm kayıt aktörleri oluşturmak için tek bir aksesuvar örneği alır.

akka cluster-sharding itibaren

:

val counterRegion: ActorRef = ClusterSharding(system).start(
    typeName = "Counter", 
    entryProps = Some(Props[Counter]), 
    idExtractor = idExtractor, 
    shardResolver = shardResolver) 

Ve o zaman idExtractor nasıl tanımladığına dayalı mesajı alır giriş aktör giderir.

def getEntry(id: EntryId): ActorRef = { 
val name = URLEncoder.encode(id, "utf-8") 
context.child(name).getOrElse { 
    log.debug("Starting entry [{}] in shard [{}]", id, shardId) 

    val a = context.watch(context.actorOf(entryProps, name)) 
    idByRef = idByRef.updated(a, id) 
    refById = refById.updated(id, a) 
    state = state.copy(state.entries + id) 
    a 
} 

}

Ben bunun yerine bölge dışında benim Giriş aktör rakam var ve olmalıdır görünüyor: onu görülebilir kırığın kaynak kodundan verilen bir giriş aktör örneği için adı olarak id kullanır Bu, verilmiş olan isme göre hesaplanır, ancak bu, şimdi, değerleri doğrudan elde etmek yerine bir dizgeden ayrıştıracağım şimdi biraz hacky hissettiriyor. Bu en iyi seçeneğim mi?

cevap

10

Sizinkiyle çok benzer bir durumdayım. Tam bir cevabım yok, ama ben ve okuyucularla yaptığım/denediğim/düşündüğümü paylaşabiliyorum.

Seçenek 1) Daha önce de belirttiğiniz gibi, adınızı nasıl adlandıracağınız ve yolu nasıl ayrıştığınız ile ilgili kimlik, parça ve bölge bilgilerini ayıklayabilirsiniz. Yukarı doğru, a) 'dır. Downsides dürtüleri a) Akka, UTF-8 olarak aktör yollarını kodlar, böylece standart url karakteri olmayan bir ayırıcı olarak kullanırsanız (|| veya w/e gibi), önce onu çözmeniz gerekir utf8'den. Akka utf8'in kodlama yöntemi olarak kodlanmış olduğunu unutmayın, kodlama formatını bir işlevdeki gibi çıkarmanın bir yolu yoktur, bu yüzden yarın akka değiştiğinde kodunuzu da uyarlamanız gerekir. b) Sisteminiz artık homomorfizmi koruyamıyor ("kulağa hacky gibi geliyor" demek). Bu, verilerinizin bir gün, bilgi ayırıcı dizenizi anlamlı veriler olarak içerebileceği ve sisteminizin dağılmasına neden olabileceği riskini eklediğiniz anlamına gelir.

Seçenek 2) Eğer yoksa, Sharding oyuncuyu doğurur. Bu nedenle kodunuzu, kurucu parametrelerinizi içeren başlatılmamış aktörlere her zaman bir init mesajı göndermeye zorlayabilirsiniz. Kişisel kanatlı bir aktörler tür içlerinde bir şey olacak:

val par1: Option[param1Type] = None 

def receive = { 
    case init(par1value) => par1 = Some(par1value) 
    case query(par1) => sender ! par1 
} 

Ve dönüş Hiçbiri ise her zaman önce sorgu mesajı ve ardından init mesajı gönderebilirsiniz Bölgeyi erişim aktör

. Bu, bölge erişim aktörünüzün başlatılmış aktörlerin bir listesini içermediğini varsayar, ki bu durumda sadece init ile doğabilir ve normal olarak kullanabilirsiniz. Eğer başlatılmış aktörlerin listesini)

Seçenek 3) korumak değilse a) (2x mesajlar alır: baş doğru

Downside "hissediyor") a) b zarif olmasıdır BU SEÇENEKLER TEST EDİLDİ VE ÇALIŞMIYOR. İnsanları aynı şeyi denemek için zaman kaybetmekten kaçınmak için burada bırakacağım. Bu işe yarayıp yaramadığımı bilmiyorum, çünkü bu senaryoyu üretimde özel kısıtlamalar ile kullanıyorum ve süslü şeyler yapmaya izin verilmiyor^_^Denemekten çekinmeyin ve lütfen bir pm ile haber verin veya yorum yapın! Temel olarak,

val counterRegion: ActorRef = ClusterSharding(system).start(
    typeName = "Counter", 
    entryProps = Some(Props[Counter]), 
    idExtractor = idExtractor, 
    shardResolver = shardResolver) 

ile bölgenizi başlamak Ne, bulunduğunuz bölgeyi oluşturma aktör gibi bir şey yaparsanız:

var providedPar1 = v1 
def providePar1 = providedPar1 

val counterRegion: ActorRef = ClusterSharding(system).start(
    typeName = "Counter", 
    entryProps = Some(Props(classOf[Counter], providePar1), 
    idExtractor = idExtractor, 
    shardResolver = shardResolver) 

Ve sonra her yaratılması için providedPar1 değerini değiştirmek? Bunun dezavantajı, o seçenekte, işe yaradığı% 100 emin oluncaya ya da yeni, yanlış değere erişme riskiyle karşı karşıya kalabildiğiniz sürece, sağlananParl'in değerini değiştirmekten kaçınmanız gerekir. (yarış koşulları!)

Genel olarak 2. seçenek ile daha iyi durumdasınız, ancak çoğu senaryoda 1'in getirdiği riskler küçüktür ve basitlik (ve performans) avantajları göz önüne alındığında bunları hafifletebilirsiniz.

Umarım bu rant yardımcı olur, nasıl çalıştığını 3 deneyerseniz bana bildirin!

+1

Fikirler için teşekkürler. Sadece ima ettiğimiz sorunun ilk kısmına doğrudan bir cevap olarak, ClusterSharding'in dinamik destekleri desteklemek için yerleşik bir yolu yoktur. Bu yüzden, cevabınızı 'benim en iyi seçeneğim bu mu?' Sorusuna ilişkin olarak bağlamsallaştırıyor. İyi cevap verdiğine inanıyorum. – Rich

+0

Evet, tamamen kaldırılmasının ya da çalışmayan olarak işaretlenmesinin daha iyi olacağından emin değildim, bu yüzden akka'daki biri onu alacak * göz kırpıyor * (ya da en azından insanlar bunun bir seçenek olmadığını ve israf etmeyeceklerini biliyorlar denemek için zaman). Ayrıca, Guice ile bir şey elde etmek ve bir InjectedProps içine hack almak mümkün olabilir, bir yere böyle bir şey görmüştüm maalesef detayları hatırlamıyorum. –