-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multi-threaded server message endpoints #147
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One high-level observation is why are we using a thread-pool, and not assigning a different inproc
address to each thread in our already existing thread pool.
I am concerned that ZeroMQ's scheduling is out of our control, and we rely on setting an arbitrarily adequate number of working threads, and we could always find a corner-case to break it (as it happened with MPI async layer).
As far as I can tell the current execution flow is (correct me if I am wrong):
- Local executor thread blocks due to a distributed coordination operation.
- Underlying transport thread (randomly assigned to this executor) blocks.
- Remote executor thread unlocks the local executor thread, thus sends a message to notify.
- A different transport thread logically unlocks the local transport thread that was locked.
Main concern with this design is that it strongly depends on the availability of a free transport thread, and on ZeroMQ actually scheduling work to threads that are not blocked, which again is out of our control.
My alternative would be to give each executor in faabric an inproc socket, or use a PUB/SUB scheme over the fan-out in-proc fabric with topic being something like appid/<function/snapshot/state>/exec-id
.
Then, implement the distributed coordination operations as transport primitives. This is, use ZeroMQ's blocking functionality to implement distributed barriers.
I have only drafted the idea here, happy to dismiss or discuss offline, as I am sure the reasoning needs a lot of polishing.
Currently our server message endpoints (
FunctionCallServer
,StateServer
, andSnapshotServer
) are backed by a single worker in a single thread, which makes them a potential bottleneck. This is particularly likely in a multi-tenant scenario where we might have a few applications running, all modifying state, chaining functions, or pushing snapshots simultaneously.This PR converts both our "sync" and "async" server endpoints to being multi-threaded via a fan-in/ fan-out approach (i.e. all incoming requests still go to the same socket as before, but under the hood they're shared between several worker threads).
The flow of messages through sockets is:
PUSH
/REQ
from remote host).PULL
/ROUTER
socket).PUSH
/DEALER
connected to aninproc://
socket).PULL
/REP
s connected to theinproc://
socket of the fan-out).Changes:
ROUTER
/DEALER
sockets for fanning out incomingREQ
requests to multiple downstreamREP
s (example in docs).PULL
/PUSH
pair of sockets for fanning out incomingPUSH
requests to multiple downstreamPULL
s (info here).proxy_steerable
. This allows us to stop the proxy programatically without a signal.TERMINATE
message to the proxy, followed by shutdown messages to each worker one-by-one.