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);
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With