I have a web service that up until my addition of server-side web socket 
support, worked fine.

I use akka-http to handle HTTP requests, and a cluster sharding region to 
route messages (sourced from the HTTP request) to actors that handle a 
particular "job" (the job id is the id used for sharding).  The actors are 
using akka persistence to maintain state.  This all works fine.

I recently updated the http handling to accept web socket connections from 
clients. In the initial ws:// request, the above-mentioned "job id" is 
included in the URI. The web socket Flow (modeled after the one found in 
this article: 
 http://blog.scalac.io/2015/07/30/websockets-server-with-akka-http.html) 
routes incoming web socket messages to the "correct" actor (based on the 
akka cluster sharding, by using the sharding region as the target actor). 
 This also works fine.  When the web socket is connected, a message is sent 
to the appropriate actor providing the actor source (to respond to).   My 
cluster sharded actor updates its state to make note of that actor, so it 
can send messages to the websocket.  That is what doesn't work.  When the 
cluster sharded actor tries to send a message to the actorRef it received 
during websocket connection, I get akka errors:

----

background log: info: route: ws-connect

background log: info: route: 
experimentInstanceId=187785cd-0276-4f04-a1a4-12e3d4487b81

background log: info: created new connection: 
org.genecloud.eim.WebSocketConnection@4b496e66

background log: info: [WARN] [10/30/2015 11:23:48.830] 
[ClusterSystem-akka.remote.default-remote-dispatcher-6] 
[akka.cluster.ClusterActorRefProvider] Error while resolving address 
[akka://HttpSystem] due to [No transport is loaded for protocol: [akka], 
available protocols: [akka.tcp]]

background log: info: [INFO] [10/30/2015 11:23:48.831] 
[ClusterSystem-akka.actor.default-dispatcher-20] 
[ExperimentInstance(akka://ClusterSystem)] Web socket connected for 
experiment instance 187785cd-0276-4f04-a1a4-12e3d4487b81

background log: info: [INFO] [10/30/2015 11:23:48.842] 
[ClusterSystem-akka.actor.default-dispatcher-15] 
[akka://HttpSystem/user/$a/flow-28-7-publisherSource-stageFactory-stageFactory-bypassRouter-flexiRoute-actorRefSource-actorRefSource]
 
Message [org.genecloud.eim.WsMessage] from 
Actor[akka://ClusterSystem/system/sharding/ExperimentInstance/86/187785cd-0276-4f04-a1a4-12e3d4487b81#-126303652]
 
to 
Actor[akka://HttpSystem/user/$a/flow-28-7-publisherSource-stageFactory-stageFactory-bypassRouter-flexiRoute-actorRefSource-actorRefSource#1354295246]
 
was not delivered. [2] dead letters encountered. This logging can be turned 
off or adjusted with configuration settings 'akka.log-dead-letters' and 
'akka.log-dead-letters-during-shutdown'.

background log: info: txt=[187785cd-0276-4f04-a1a4-12e3d4487b81] message #1

background log: info: WsIncomingMessage: 
experimentInstanceId=187785cd-0276-4f04-a1a4-12e3d4487b81

background log: info: txt=[187785cd-0276-4f04-a1a4-12e3d4487b81] message #2

background log: info: WsIncomingMessage: 
experimentInstanceId=187785cd-0276-4f04-a1a4-12e3d4487b81

---


The first 3 log messages show the HTTP route accepting the web socket 
connection with path /ws-connect/:JobId.  The WebSocketConnection object 
holds the flow.  The 5th log message shows the cluster sharded actor 
logging a message that the web socket has been connected.  The 4th log 
message is a mystery to me and probably going to cause the issue when the 
cluster sharded actor attempts to send a message back to the actor handling 
the web socket.  The code that sends the message looks like this:

    case WsConnected(experimentInstanceId: String, websocketActor: 
ActorRef) =>

      logger.info(s"Web socket connected for experiment instance $
experimentInstanceId")

      persist(WebSocketConnectedEvent(websocketActor)) { evt =>

        state = state.updated(evt)

        websocketActor ! WsMessage("foo", "bar")

      }

The websocketActor that is supplied in the message came from the Flow, 
where the relevant portion is here in the WebSocketConnection class:

          // Materialized value of Actor

          val actorAsSource = builder.materializedValue.map(actor => 
WsConnected(experimentInstanceId, actor))


I'm not entirely sure where that actor comes from, but it appears that you 
can't send messages back to that actor from a potentially remote, clustered 
actor.  Is there some limitation here that I'm fighting with?


Note: I fully realize that I'm expecting a lot from akka here.  In the 
system I'm building, I'm intended to have multiple akka-http nodes behind a 
load balancer.  A user will therefore send http requests to one of the many 
akka-http nodes. But he will end up establishing a web socket connection 
with exactly one of these nodes (at a time).  Both http and web socket 
messages will get routed to an appropriate worker actor based on a sharded 
id.  That actor may be on some other node (not he one handling the http 
requests and not the one holding the server-side end of the web socket 
connection).  I'm expecting akka to be able to route any message from that 
actor back to the web socket.  Is that possible?


-- Eric


-- 
>>>>>>>>>>      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 akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to