2

I am working on a distributed application that uses the Manager Worker pattern. The application's manager node submits work to worker nodes through a WorkerNode object (allowing WorkerNode to be treated as the server itself).

The manager node can also submit work to its' internal WorkPool this is currently done by calling the WorkPool class explicitly without making HTTP calls.

I am at the point to where I am writing a lot of code to ensure 'local work' is submitted to the WorkPool class on the manager node and that 'remote work' is submitted to the remote WorkPool class over HTTP (using the WorkerNode object).

This is causing some awkward edge cases developers need to worry about like distributing WorkUnit objects evenly across nodes.

Proposed design:

Treat all work pools as if they are remote. I can control the local work pool through a WorkerNode that is assigned an address of localhost. This also requires the manager node to have the worker nodes routes added to the application at runtime (flask blueprint so it's easy).

Drawbacks:

The manager nodes makes requests to itself. Possibly causing caching issues, new devs saying "what the heck", or network issues when a reverse proxy server is added later.

Improvements:

Work pool is completely abstracted and there are no edge cases when submitting, retrieving, or killing units of work in the pools.

Unit testing my WorkRouter class becomes very easy.

Interfacing with local work pools or remote work pools is done through the same object type keeping code DRY.

Similar Question: Is it bad design to internally call API endpoints from within the API instance?

This question seems to have nothing related to distributed systems and so using the service layer is an appropriate answer when dealing with a single stateless application.

1 Answers1

1

I have thought about this all morning :)

Having the API call itself is not an elegant solution. However, making this abstraction has many benefits and can be done by putting further responsibility onto the WorkerNode class.

The WorkerNode class is now responsible for interfacing with service layer logic when running on the manager node. The class is smart enough to know where it is running based on its' UUID value. We can add a simple check in the classes interface to branch off using the service layer or HTTP protocol.

Now the WorkRouter class can iterate through each WorkerNode and has no edge cases on interfacing further with other service layer logic.