(Migrated) Architecture and redis question

(This message has been automatically imported from the retired mailing list)

I have been through the architecture documentation, including
https://zato.io/docs/architecture/servers.html, and I have a question.

The main servers run under gunicorn, and therefore accept HTTP requests
natively. That’s fine.

However as I understand it certain requests go via redis, for example:

  • invoke_async() from any other service
  • scheduler actions
  • incoming messages from AMQP/0MQ are picked by the singleton receiver
    process and posted into redis

What I don’t understand is how these redis messages get picked up and
acted upon by the servers. Is there a process somewhere which is taking
redis messages and injecting them into the load-balancer as HTTP? Or has
the gunicorn worker been extended so that it listens for redis messages
as well as HTTP - if so, how?

Thanks,

Brian.

On 21/05/15 12:51, Brian Candler wrote:

What I don’t understand is how these redis messages get picked up and
acted upon by the servers. Is there a process somewhere which is taking
redis messages and injecting them into the load-balancer as HTTP? Or has
the gunicorn worker been extended so that it listens for redis messages
as well as HTTP - if so, how?

Hi Brian,

it’s the latter.

Each server (gunicorn worker) has assigned an instance of the WorkerStore.

https://github.com/zatosource/zato/blob/master/code/zato-server/src/zato/server/base/worker.py

This is the central place that dispatches incoming requests, regardless
of their channel - HTTP, AMQP, scheduler, internal pub/sub, anything.

Each such worker, ultimately, uses a BrokerClient to communicate with Redis:

https://github.com/zatosource/zato/blob/master/code/zato-broker/src/zato/broker/client.py

That client contains logic to listen to and send messages between
servers, either 1:any, 1:all, 1:connector.

You’d need to study this class a bit to check out how it does it exactly

  • publish and invoke_async are for sending and on_message for receiving.

With on_message, you’ll eventually find that it uses callbacks - the
callbacks, again ultimately, are defined in WorkerStore.

So for instance:

  • A service wants to notify other servers to reconfigure an HTTP channel
    with new config

  • This is turned into a JSON document with a type of
    CHANNEL.HTTP_SOAP_CREATE_EDIT (as defined in zato.common.broker_message)

  • It is sent to all servers using the BrokerClient above assigned to the
    original server

  • It is then received by all servers using their respective BrokerClient
    instances (including the sending one)

  • Each fires the callback which, basing on the message’s type, finds out
    which method of the WorkerStore to invoke. Here it would be
    on_broker_msg_CHANNEL_HTTP_SOAP_CREATE_EDIT

https://github.com/zatosource/zato/blob/master/code/zato-server/src/zato/server/base/worker.py#L1087

  • That callback does what is needed in a given situation. Here the
    internal cache of channel data would be updated. But each
    on_broker_msg_* callback is dedicated to a specific action so they can
    do various things.

This is how it works in principle. The load-balancer is not employed at
all, it’s all internal communication between servers.