Using Akka's Scala framework to block CLI calls

I'm relatively new to Akka and Scala, but I would like to use Akka as a general framework for collecting information from various web tools and cli commands.

I understand the CEO that in the actor’s model, it’s highly advisable not to block the actors. And in the case of HTTP requests, there are asynchronous http clients (such as Spray), which means that I can process requests asynchronously within the framework of Actionor.

However, I'm not sure what works best for combining members with existing blocking API calls, such as the scala ProcessBuilder / ProcessIO libraries. In terms of issuing these CLI commands, I expect a relatively small amount of concurrency, for example. possibly by making a maximum of 10 simultaneous CLI calls on a 12-core computer.

Is it better to have one actor to manage these CLI teams with an actual futures farm that is created as needed? Or would it be easier to just maintain a set of individual contributors supported by PinnedDispatcher? Or something else?

+4
source share
1 answer

From the Akka documentation ( http://doc.akka.io/docs/akka/snapshot/general/actor-systems.html#Blocking_Needs_Careful_Management ):

" Blocking Needs Careful Management

In some cases, it is inevitable to perform blocking operations, i.e. put the stream to sleep for an indefinite time, waiting for an external event to occur. Examples are legacy RDBMS drivers or messaging APIs, and the main reason is that (network) I / O operations occur under covers. When you encounter this, you may be tempted to simply close the blocking call within the Future and work with it instead, but this strategy is too simple: you will most likely find bottles or end memory or threads when the application starts up under heavy load.

A non-exhaustive list of adequate solutions to the “blocking problem” includes the following suggestions:

  • Make a blocking call inside the actor (or a set of participants controlled by the router [Java, Scala]) to configure a thread pool that is designed for this purpose or large enough.
  • Make a blocking call in the future, providing an upper bound on the number of such calls at any given time (sending an unlimited number of tasks of this kind will exhaust the limitations of your memory or thread).
  • Make a blocking call in the future by providing the thread pool with an upper limit on the number of threads suitable for the equipment on which the application is running. Allocate one thread to control the set of blocking resources (for example, an NIO selector that controls several channels) and send events as they appear as actor messages.

The first option is especially suitable for resources that are single-threaded in nature, such as database descriptors, which traditionally can only execute one outstanding query at a time and use internal synchronization to provide this. A common example is the creation of a router for N participants, each of which wraps one database connection and processes requests sent to the router. Then the number N must be configured for maximum throughput, which will depend on which DBMS is deployed on which equipment.

+4
source

Source: https://habr.com/ru/post/1440049/


All Articles