Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can my nginx module make a connection in the master process?

Tags:

plugins

nginx

I'm writing an nginx module that wants to subscribe to a zeromq pubsub socket and update an in-memory data-structure based on the messages it receives. To save bandwidth, it makes sense that only one process should make the subscription, and the data structure should be in shm so that all processes can make use of it. To me it seems natural that that one process should be the master (since if it was a worker, the code would have to somehow decide which worker).

But when I call ngx_get_connection from my init_master or init_module callbacks, it segfaults, apparently due to ngx_cycle not being initialized yet. Google searches on plugins doing work in the master process seem pretty pessimistic. Is there a better way to accomplish my goal of making a single outgoing connection to the pubsub socket per server, regardless of how many workers it has?

Here's a sample of code that works in a worker context but not from the master:

void *zmq_context = zmq_ctx_new();
void *control_socket = zmq_socket(zmq_context, ZMQ_SUB);
int control_fd;
size_t fdsize = sizeof(int);
ngx_connection_t *control_connection;

zmq_connect(control_socket, "tcp://somewhere:1234");
zmq_setsockopt(control_socket, ZMQ_SUBSCRIBE, "", 0);
zmq_getsockopt(control_socket, ZMQ_FD, &control_fd, &fdsize);
control_connection = ngx_get_connection(control_fd, cycle->log);
control_connection->read->handler = my_read_handler;
control_connection->read->log = cycle->log;
ngx_add_event(control_connection->read, NGX_READ_EVENT, 0);

and elsewhere

void my_read_handler (ngx_event_t *ev) {
    int events;
    size_t events_size = sizeof(events);

    zmq_getsockopt(control_socket, ZMQ_EVENTS, &events, &events_size);
    while (events & ZMQ_POLLIN) {
        /* ...
           read a message, do something with it
        ... */
        events = 0;
        zmq_getsockopt(control_socket, ZMQ_EVENTS, &events, &events_size);
    }
}
like image 963
hobbs Avatar asked Feb 15 '14 21:02

hobbs


1 Answers

To save bandwidth, it makes sense that only one process should make the subscription, and the data structure should be in shm so that all processes can make use of it. To me it seems natural that that one process should be the master (since if it was a worker, the code would have to somehow decide which worker).

As I already said, all you need is to decline your natural idea and just use one worker process for your purpose.

Which worker? Well, let it be the first one started.

like image 77
VBart Avatar answered Sep 17 '22 23:09

VBart