That code is *very* strange, not at all the way I expect things to be set up.
First of all, trying to "get" the cart actor like this is generally not the way you do things in a Cluster Sharded environment. Cluster Sharding allows the actors to rebalance when needed, so it is *not* guaranteed that the ActorRef is going to be consistent from moment to moment -- that's why it's often recommended that you pair it with a persistence solution. Instead of using actorSelection to get the ActorRef and then sending messages to that ActorRef, you should simply be sending the messages to the ShardRegion itself. (What you have here isn't *necessarily* broken, but it's certainly not idiomatic.) Also, your extractShardId() function is kinda broken. Notice how you're never using "numberOfShards"? The way you have this set up, you're creating one shard per entity, which misses the point of cluster sharding -- there are supposed to be a modest number of shards per node. The usual recommendation is that numberOfShards should be (# of nodes * 10), and you should be computing the shardId based on that -- do something like take the hash of the cart_id modulo numberOfShards, and then turn that into a string. Again, this isn't obviously causing your problems, but it's definitely not correct style. More importantly, the way that you're trying to get the ActorRef -- using a hardcoded path -- is *very* broken. Do you have any reason to believe it's working? Is your "reusing actor" message ever actually printing, or is it doing the fallback pathway instead? That fallback makes no sense -- you're mixing apples and oranges, using a hardcoded actor interchangeably with cluster sharding, which is more or less certain to fail. And most broken of all, you seem to be calling ClusterSharding.start() once for every request. I'm kind of surprised that doesn't cause the system to crash outright -- you're supposed to call that *once*, at the beginning of the application on each node, and then use the resulting ShardingRegion for all requests afterwards. Seriously -- go back and reread the Cluster Sharding documentation more carefully. The function as shown above isn't the way Cluster Sharding is supposed to be used, and my only real surprise is that it's even working slightly... On Tue, Apr 18, 2017 at 12:43 AM, <[email protected]> wrote: > > I am sharing the code and process I am following: > > def getOrCreateCartActor(cart_id: UUID): ActorRef = { > var cartActor: ActorRef = null > implicit val timeout = Timeout(50 seconds) > val name = "/user/" + cart_id.toString > > > val extractEntityId: ShardRegion.ExtractEntityId = { > case cart: GetCartId ⇒ (cart.cart_id.toString,cart) > } > > val numberOfShards = 3 > > val extractShardId: ShardRegion.ExtractShardId = { > case cart: GetCartId ⇒ cart.cart_id.toString > case Get(id) ⇒ cart_id.toString > } > > > > try{ > > println("Actor exista") > ClusterSharding(actorSystem).start(typeName = "CartActor",entityProps = > Props[CartActor], > settings = ClusterShardingSettings(actorSystem),extractEntityId = > extractEntityId, > extractShardId = extractShardId) > ClusterSharding(actorSystem).shardRegion("CartActor") > > val path = "/user/"+cart_id.toString > val future = > actorSystem.actorSelection("/user/"+cart_id.toString).resolveOne() > val actorResult = Await.result(future, 1 seconds) > println("Reusing actor") > cartActor = actorResult > > > > } > catch { > case ex: ActorNotFound => { > > println("Actor doesn't exist") > > println("Actor Intialized") > > cartActor = actorSystem.actorOf(props = Props[CartActor], > cart_id.toString) > > } > > > > } > > > > cartActor > > > } > > > > The after that i start three nodes: > > sbt "run -Dhttp.port=9001" > sbt "run -Dhttp.port=9002" > sbt run > > now i send request to port 9000 : > {"operation": "ADDSKUTOCART","cart_id":"18768458-01d5-4f65-b7f8- > abe49ba67775","user_id":"00000000-0000-0000-0000- > 000000000001","sku_id":"9","quantity":3,"price":1.0," > title":"ff","imageUrl":"xv"} > > and Response is: > > {"cart_id":"18768458-01d5-4f65-b7f8-abe49ba67775","user_ > id":"00000000-0000-0000-0000-000000000001","cart_entries":{ > "9":{"sku_id":"9","quantity":1,"price":1.0,"title":"ff"," > imageUrl":"xv"}},"total_numberOf_items":1,"cart_total":1.0} > > now i send request to port 9001 with different sku_id: > > {"operation": "ADDSKUTOCART","cart_id":"18768458-01d5-4f65-b7f8- > abe49ba67775","user_id":"00000000-0000-0000-0000- > 000000000001","sku_id":"10","quantity":3,"price":1.0," > title":"ff","imageUrl":"xv"} > > and Response is: > > {"cart_id":"18768458-01d5-4f65-b7f8-abe49ba67775","user_ > id":"00000000-0000-0000-0000-000000000001","cart_entries":{ > "9":{"sku_id":"9","quantity":1,"price":1.0,"title":"ff"," > imageUrl":"xv"},"10":{"sku_id":"10","quantity":1,"price":1. > 0,"title":"ff","imageUrl":"xv"}},"total_numberOf_items":2," > cart_total":2.0} > > here you can see ,"total_numberOf_items" is 2 > > Now i send request to port 9002 again by changing sku_id: > {"operation": "ADDSKUTOCART","cart_id":"18768458-01d5-4f65-b7f8- > abe49ba67775","user_id":"00000000-0000-0000-0000- > 000000000001","sku_id":"11","quantity":3,"price":1.0," > title":"ff","imageUrl":"xv"} > > and Response comes: > {"cart_id":"18768458-01d5-4f65-b7f8-abe49ba67775","user_ > id":"00000000-0000-0000-0000-000000000001","cart_entries":{ > "9":{"sku_id":"9","quantity":1,"price":1.0,"title":"ff"," > imageUrl":"xv"},"10":{"sku_id":"10","quantity":1,"price":1. > 0,"title":"ff","imageUrl":"xv"},"11":{"sku_id":"11"," > quantity":1,"price":1.0,"title":"ff","imageUrl":"xv"}}, > "total_numberOf_items":3,"cart_total":3.0} > > again "total_numberOf_items" is updated to 3. > > Now as i hit second request to any node say i am hitting request to node > with port number 9000 with again changing sku_id: > > {"operation": "ADDSKUTOCART","cart_id":"18768458-01d5-4f65-b7f8- > abe49ba67775","user_id":"00000000-0000-0000-0000- > 000000000001","sku_id":"12","quantity":3,"price":1.0," > title":"ff","imageUrl":"xv"} > > and response comes: > > {"cart_id":"18768458-01d5-4f65-b7f8-abe49ba67775","user_ > id":"00000000-0000-0000-0000-000000000001","cart_entries":{ > "9":{"sku_id":"9","quantity":1,"price":1.0,"title":"ff"," > imageUrl":"xv"},"12":{"sku_id":"12","quantity":1,"price":1. > 0,"title":"ff","imageUrl":"xv"}},"total_numberOf_items":2," > cart_total":2.0} > > here "total_numberOf_items" = 2 which was supposed to be 4. > > let me know if there is anything i am missing or is there a different way > to do it. > > > > > > > > > > > > On Monday, April 17, 2017 at 8:22:11 PM UTC+5:30, Justin du coeur wrote: >> >> That's *extremely* weird. I mean, the entire point of Cluster Sharding >> is that you are always getting the same Actor for a given ID. Can you show >> the code that you're using to start your sharding region, and to send the >> messages? What do your messages look like, and how are you extracting the >> ID from the message? Are you getting exceptions, and if so, what do they >> look like? >> >> On Mon, Apr 17, 2017 at 1:09 AM, <[email protected]> wrote: >> >>> Implemented using cluster sharding also. same problem everything seems >>> to work for first request on any node in cluster as i hit second request on >>> any node in the cluster it starts fetching data independently. is there a >>> different way to get existing actorref in clustered enviornment than from >>> normal actorsystem. >>> >>> On Wednesday, April 12, 2017 at 6:35:30 PM UTC+5:30, Justin du coeur >>> wrote: >>> >>>> Hmm -- I'm not quite sure what you're expecting this to do, but it >>>> sounds to me like you're using the wrong tool. Have you looked into Akka >>>> Cluster Sharding yet? From your problem description, I suspect it's what >>>> you should be using... >>>> >>>> On Wed, Apr 12, 2017 at 12:38 AM, <[email protected]> wrote: >>>> >>>>> It is first time I am implementing akka clustering so I have no prior >>>>> experience with that. What We want to acheive with akka clustering is that >>>>> when request goes to each node in cluster each node return same instance >>>>> of >>>>> actor (Or actor consist of same data which should just be sum of response >>>>> to all requests to all nodes). But what we all getting is all nodes >>>>> returning different response containing different data as if they are >>>>> working independently. >>>>> >>>>> >>>>> Here I am sharing some code and configuration and exceptions we are >>>>> getting >>>>> >>>>> def getOrCreateCartActor(cart_id: UUID): ActorRef = { >>>>> var cartActor: ActorRef = null >>>>> implicit val timeout = Timeout(50 seconds) >>>>> val name = "/user/" + cart_id.toString >>>>> val roundRobinPool = RoundRobinPool( nrOfInstances = 4) >>>>> >>>>> val clusterRouterPoolSettings = ClusterRouterPoolSettings( >>>>> totalInstances = 4, maxInstancesPerNode = 2, >>>>> allowLocalRoutees = true, useRole = None) >>>>> >>>>> val clusterRouterPool = ClusterRouterPool(roundRobinPool, >>>>> clusterRouterPoolSettings) >>>>> >>>>> val future = actorSystem.actorSelection("/user/" + >>>>> cart_id.toString).resolveOne() >>>>> >>>>> >>>>> try{ >>>>> /*try { >>>>> println("Everything Ok.") >>>>> cartActor = actorSystem.actorOf(ClusterSingletonProxy.props( >>>>> singletonManagerPath = "/user/" + cart_id.toString, >>>>> settings = ClusterSingletonProxySettings(actorSystem)), >>>>> name = cart_id.toString+"Proxy" >>>>> ) >>>>> }catch { >>>>> case ex: InvalidActorNameException => >>>>> if(cartActor == null){ >>>>> println("Everything Not Ok.") >>>>> cartActor = actorSystem.actorOf( >>>>> ClusterSingletonManager.props( >>>>> singletonProps = Props(classOf[CartActor]), >>>>> terminationMessage = PoisonPill, >>>>> settings = ClusterSingletonManagerSettings(actorSystem)), >>>>> //Props[CartActor], >>>>> cart_id.toString) >>>>> } >>>>> }*/ >>>>> val actorResult = Await.result(future, 50 seconds) >>>>> cartActor = >>>>> actorSystem.actorOf(clusterRouterPool.props(Props[CartActor]), >>>>> cart_id.toString) >>>>> >>>>> } >>>>> catch { >>>>> case ex: ActorNotFound => { >>>>> >>>>> >>>>> >>>>> cartActor = >>>>> actorSystem.actorOf(clusterRouterPool.props(Props[CartActor]), >>>>> cart_id.toString) >>>>> } >>>>> } >>>>> >>>>> cartActor >>>>> >>>>> >>>>> } >>>>> >>>>> >>>>> As in comments in code you can see I also tried ClusterSingleton and >>>>> Cluster Pooling using round robin. >>>>> >>>>> Here is configuration : >>>>> >>>>> akka { >>>>> # "akka.log-config-on-start" is extraordinarly useful because it log >>>>> the complete >>>>> # configuration at INFO level, including defaults and overrides, so it >>>>> s worth >>>>> # putting at the very top. >>>>> # >>>>> # Put the following in your conf/logback.xml file: >>>>> # >>>>> # <logger name="akka.actor" level="INFO" /> >>>>> # >>>>> # And then uncomment this line to debug the configuration. >>>>> # >>>>> #log-config-on-start = true >>>>> >>>>> loglevel = DEBUG >>>>> loggers = ["akka.event.slf4j.Slf4jLogger"] >>>>> logging-filter = "akka.event.slf4j.Slf4jLoggingFilter" >>>>> >>>>> actor { >>>>> provider = "akka.cluster.ClusterActorRefProvider" >>>>> debug { >>>>> receive = on >>>>> lifecycle = on >>>>> } >>>>> serializers { >>>>> java = "akka.serialization.JavaSerializer" >>>>> } >>>>> >>>>> } >>>>> // remote { >>>>> // log-remote-lifecycle-events = off >>>>> // netty.tcp { >>>>> // hostname = "127.0.0.1" >>>>> // port = 0 >>>>> // } >>>>> // } >>>>> >>>>> remote { >>>>> enabled-transports = ["akka.remote.netty.tcp"] >>>>> netty.tcp { >>>>> hostname = "127.0.0.1" >>>>> port = 0 >>>>> } >>>>> } >>>>> >>>>> cluster { >>>>> seed-nodes = [ >>>>> "akka.tcp://[email protected]:2551", >>>>> "akka.tcp://[email protected]:2552"] >>>>> >>>>> >>>>> >>>>> >>>>> #//#snippet >>>>> # excluded from snippet >>>>> //auto-down-unreachable-after = 10s >>>>> #//#snippet >>>>> # auto downing is NOT safe for production deployments. >>>>> # you may want to use it during development, read more about it in >>>>> the docs. >>>>> # >>>>> //auto-down-unreachable-after = 10s >>>>> >>>>> // distributed-data { >>>>> // # Actor name of the Replicator actor, /system/ddataReplicator >>>>> // name = ddataReplicator >>>>> // } >>>>> } >>>>> >>>>> //akka.extensions = ["akka.cluster.pubsub.DistributedPubSub"] >>>>> >>>>> } >>>>> >>>>> >>>>> Then i started nodes using: >>>>> >>>>> sbt "run -Dhttp.port=9001 -Dakka.remote.netty.tcp.port=2551" >>>>> sbt "run -Dhttp.port=9002 -Dakka.remote.netty.tcp.port=2552" >>>>> *and main server with* >>>>> sbt run >>>>> >>>>> and then the exception i am getting is: >>>>> >>>>> [error] application - >>>>> >>>>> ! @73ji7p2o9 - Internal server error, for (POST) [/addToCart] -> >>>>> >>>>> play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution >>>>> exception[[InvalidActorNameException: actor name >>>>> [1876845a-01d5-4f15-b7f7-abe49ba6e689] is not unique!]] >>>>> at play.api.http.HttpErrorHandler >>>>> Exceptions$.throwableToUsefulException(HttpErrorHandler.scala:293) >>>>> at play.api.http.DefaultHttpError >>>>> Handler.onServerError(HttpErrorHandler.scala:220) >>>>> at play.api.GlobalSettings$class. >>>>> onError(GlobalSettings.scala:160) >>>>> at play.api.DefaultGlobal$.onError(GlobalSettings.scala:188) >>>>> at play.api.http.GlobalSettingsHt >>>>> tpErrorHandler.onServerError(HttpErrorHandler.scala:100) >>>>> at play.core.server.netty.PlayRequestHandler$$anonfun$2$$ >>>>> anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100) >>>>> at play.core.server.netty.PlayRequestHandler$$anonfun$2$$ >>>>> anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99) >>>>> at scala.concurrent.Future$$anonf >>>>> un$recoverWith$1.apply(Future.scala:344) >>>>> at scala.concurrent.Future$$anonf >>>>> un$recoverWith$1.apply(Future.scala:343) >>>>> at scala.concurrent.impl.Callback >>>>> Runnable.run(Promise.scala:32) >>>>> Caused by: akka.actor.InvalidActorNameException: actor name >>>>> [1876845a-01d5-4f15-b7f7-abe49ba6e689] is not unique! >>>>> at akka.actor.dungeon.ChildrenCon >>>>> tainer$NormalChildrenContainer.reserve(ChildrenContainer.scala:129) >>>>> at akka.actor.dungeon.Children$cl >>>>> ass.reserveChild(Children.scala:130) >>>>> at akka.actor.ActorCell.reserveChild(ActorCell.scala:374) >>>>> at akka.actor.dungeon.Children$class.makeChild(Children.scala: >>>>> 268) >>>>> at akka.actor.dungeon.Children$cl >>>>> ass.attachChild(Children.scala:46) >>>>> at akka.actor.ActorCell.attachChild(ActorCell.scala:374) >>>>> at akka.actor.ActorSystemImpl.actorOf(ActorSystem.scala:729) >>>>> at services.CartService.getOrCrea >>>>> teCartActor(CartService.scala:179) >>>>> at services.CartService.routeMessagesToCart(CartService.scala: >>>>> 82) >>>>> at services.CartService.getCart(CartService.scala:42) >>>>> >>>>> Please let me know if i am missing something. >>>>> >>>>> >>>>> -- >>>>> >>>>>>>>>> Read the docs: http://akka.io/docs/ >>>>> >>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/c >>>>> urrent/additional/faq.html >>>>> >>>>>>>>>> Search the archives: https://groups.google.com/grou >>>>> p/akka-user >>>>> --- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "Akka User List" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to [email protected]. >>>>> To post to this group, send email to [email protected]. >>>>> Visit this group at https://groups.google.com/group/akka-user. >>>>> For more options, visit https://groups.google.com/d/optout. >>>>> >>>> >>>> -- >>> >>>>>>>>>> Read the docs: http://akka.io/docs/ >>> >>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/c >>> urrent/additional/faq.html >>> >>>>>>>>>> Search the archives: https://groups.google.com/grou >>> p/akka-user >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "Akka User List" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> To post to this group, send email to [email protected]. >>> Visit this group at https://groups.google.com/group/akka-user. >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- > >>>>>>>>>> Read the docs: http://akka.io/docs/ > >>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/ > current/additional/faq.html > >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user > --- > You received this message because you are subscribed to the Google Groups > "Akka User List" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at https://groups.google.com/group/akka-user. > For more options, visit https://groups.google.com/d/optout. > -- >>>>>>>>>> Read the docs: http://akka.io/docs/ >>>>>>>>>> Check the FAQ: >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups "Akka User List" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.
