3

I had been testing an Akka based application for more than a month now. But, if I reflect upon it, I have following conclusions:

  1. Akka actors alone can achieve lot of concurrency. I have reached more than 100,000 messages/sec. This is fine and it is just message passing.
  2. Now, if there is netty layer for connections at one end or you end up with akka actors eventually doing DB calls, REST calls, writing to files, the whole system doesn't make sense anymore. The actors' mailbox gets full and their throughput(here, ability to receive msgs/sec) goes slow.
  3. From a QA perspective, this is like having a huge pipe in which you can forcefully pump lot of water and it can handle. But, if the input hose is bad, or the endpoints cannot handle the pressure, this huge pipe is of no use.

I need answers for the following so that I can suggest or verify in the system:

  1. Should the blocking calls like DB calls, REST calls be handled by actors? Or they good only for message passing?
  2. Can it be like, lets say you have the need of connecting persistently millions of android/ios devices to your akka system. Instead of sockets(so unreliable) etc., can remote actor be implemented as a persistent connection?
  3. Is it ok to do any sort of computation in actor's handleMessage()? Like DB calls etc.

I would request this post to get through by the editors. I cannot ask all of these separately.

spiralarchitect
  • 880
  • 7
  • 19
  • I think you should take a serious look at the hystrix library by netflix. You don't have to use the library but use its techniques. However I'm sure you could combine the library with akka but it might be messy given both want to manage threads. – Adam Gent Mar 24 '15 at 12:00

2 Answers2

1

1) Yes, they can. But this operation should be done in separate (worker) actor, that uses fork-join-pool in combination with scala.concurrent.blocking around the blocking code, it needs it to prevent thread starvation. If target system (DB, REST and so on) supports several concurrent connections, you may use akka's routers for that (creating one actor per connection in pool). Also you can produce several actors for several different tables (resources, queues etc.), depending on your transaction isolation and storage's consistency requirements.

Another way to handle this is using asynchronous requests with acknowledges instead of blocking. You may also put the blocking operation inside some separate future (thread, worker), which will send acknowledge message at the operation's end.

2) Yes, actor may be implemented as a persistence connection. It will be just an actor, which holds connection's state (as actors are stateful). It may be even more reliable using Akka Persistence, which can save connection to some storage.

3) You can do any non-blocking computations inside the actor's receive (there is no handleMessage method in akka). The failures (like no connection to DB) will be managing automatically by Akka Supervising. For the blocking code, see 1.

P.S. about "huge pipe". The backend-application itself is a pipe (which is becoming huge with akka), so nothing can help you to improve performance if environement can't handle it - there is no pumps in this world. But akka is also a "water tank", which means that outer pressure may be stronger than inner. Btw, it means that developer should be careful with mailboxes - as "too much water" may cause OutOfMemory, the way to prevent that is to organize back pressure. It can be done by not acknowledging incoming message (or simply blocking an endpoint's handler) til it proceeded by akka.

Community
  • 1
  • 1
dk14
  • 22,206
  • 4
  • 51
  • 88
  • Thanks for straight forward answers. I will look at the worker actors and if they are implemented. One follow-up question: When you say Actors can be used as persistence connection, do you mean, we need to bundle akka with mobile app? I wanted to know if actors can be replaces with Websockets. – spiralarchitect Mar 25 '15 at 06:18
  • I don't know how actor can replace some protocol. It can only implement it. Of course with assumption that akka-io/spray is used to interact with sockets. About bundling Akka with mobile app - if you communicate through sockets there is no need for Akka at client - it has only to support socket (or any high-level socket-based protocol, like http, web-sockets and so on). Sockets here is just an endpoint - it could be also jms or any other transport. Akka is responsible only for processing, not communication – dk14 Mar 25 '15 at 06:47
0

I'm not sure I can understand all of your question, but in general actors are good also for slow work:

1) Yes, they are perfectly fine. Just create/assign 1 actor per every request (maybe behind an akka router for load balancing), and once it's done it can either mark itself as "free for new work" or self-terminate. Remember to execute the slow code in a future. Personally, I like avoiding the ask/pipe pattern due to the implicit timeouts and exception swallowing, just use tells with request id's, but if your latencies and error rates are low, go for ask/pipe.

2) You could, but in that case I'd suggest having a pool of connections rather than spawning them per-request, as that takes longer. If you can provide more details, I can maybe improve this answer.

3) Yes, but think about this: actors are cheap. Create millions of them, every time there is a blocking part, it should be a different, specialized actors. Bring single-responsibility to the extreme. If you have few, blocking actors, you lose all the benefits.

Diego Martinoia
  • 4,592
  • 1
  • 17
  • 36