0
votes

As far as I can tell from documentation, ZeroMQ sockets are not supposed to be used (e.g. read from/written to) from different threads.

That in turn prevents me from using a ZMQ socket in an Akka Actor running on the default dispatcher (no guarantee about which thread will be executing my receive method).

Would using a PinnedDispatcher allow me to use such socket safely inside an Actor, provided that I take care not to block (at least not for excessive amounts of time)?

This dispatcher dedicates a unique thread for each actor using it; i.e. each actor will have its own thread pool with only one thread in the pool

via: https://doc.akka.io/docs/akka/2.5/dispatchers.html#types-of-dispatchers

I am using JeroMQ 0.4.0 and Akka 2.5. I realize that Akka used to have a ZeroMQ extension but that seems mostly abandoned.

1
Do you have an answer to your question already? Does your approach (using PinnedDispatcher) work? I also need to integrate ZMQ communication with Akka 2.5.Jonny Dee
I do not recall having any significant problems, but I cannot confirm with 100% certainty. I haven’t worked on that project for over a year and I do not have access to it anymore. Good luck, though!Patryk Koryzna

1 Answers

-1
votes

Well, a thread-safeness comes at cost .

ZeroMQ, since the very earliest version ( you refer to API ver. 2.1, while there are API versions past 4.2+ released and available in 2018/Q2+ ), was being built under a shared set of values a.k.a. a Zen-of-Zero, which strives to make things happen as-efficient-as-possible, in a resource-friendly manner and having acquired only a reasonable amount ( best none at all ) latency.


May see recent efforts to add thread-safety in ZeroMQ 4.2+ re-factoring

yet, this does not mean, this could be achieved cost-free, does it?

No one would be harmed, if using proper tools in a proper manner, would he?

Yet, no one may ignore a principal uncertainty of which ZeroMQ API version will appear in the domain of deployment, so relying on a feature available in newer API versions need not prove itself to be valid for each ( remote ) agents met during the life-span, so be cautious.

Anyway, the Akka note warns, that as-is compatibility was frozen onto API v.2 level:

The currently used version of zeromq-scala-bindings is only compatible with zeromq 2; zeromq 3 is not supported.


So, how ?

If indeed in a need to mix several different event-loops ( as indicated above ), I would opt for delegating the task to a set of independently operating ( be it colocated or distributed ) Context()-instances, rather than trying to share any Socket()-AccessPoint-level instances or trying to use a "pinned"-promise, just-mediated by an external ( concurrently co-existent ) non-ZeroMQ event-loop framework.

Clean "share-nothing" ZeroMQ designs are way safer and way faster, than trying an art of juggling more and more design-artifacts ( and if your domain requires QA-procedures, the more if design validation and verification proofs are to get delivered before an acceptance may even get scheduled -- try to just imagine the costs of testing, QA / verification proofs for a wild mix of toys just wished to have a deterministic, non-blocking, error-free and robust/resilient field operations )

Beware :
ZeroMQ Socket()-instance is not a tcp-socket-as-you-know-it. Best read about the main conceptual differences in ZeroMQ hierarchy in less than a five seconds or other posts and discussions here.

Context()-instances have their own I/O-thread-pools under their own domain-of-control, also having a "DMA"-alike mapper between a respective Context's Socket()-instance permitted affinity to the respective Context's (groups of) I/O-thread(s), so a global view on "pinning" may not affect the intended resource-mapping preferences.


Last, but not least - Akka-port specific configurations ,
that do not match the ZeroMQ native API defaults :

#####################################
# Akka ZeroMQ Reference Config File #
#####################################

# This is the reference config file that contains all the default settings.
# Make your edits/overrides in your application.conf.

akka {

  zeromq {

    # The default timeout for a poll on the actual zeromq socket.
    poll-timeout = 100ms

    # Timeout for creating a new socket
    new-socket-timeout = 5s

    socket-dispatcher {
      # A zeromq socket needs to be pinned to the thread that created it.
      # Changing this value results in weird errors and race conditions within
      # zeromq
      executor = thread-pool-executor
      type = "PinnedDispatcher"
      thread-pool-executor.allow-core-timeout = off
    }
  }
}