function worker_thread() { $context = new ZMQContext(); $worker = $context->getSocket(ZMQ::SOCKET_REQ); $worker->connect("ipc://backend.ipc"); // Tell broker we're ready for work $worker->send("READY"); while (true) { $zmsg = new Zmsg($worker); $zmsg->recv(); // Additional logic to clean up workers. if ($zmsg->address() == "END") { exit; } printf("Worker: %s\n", $zmsg->body()); $zmsg->body_set("OK"); $zmsg->send(); } }
$poll = new ZMQPoll(); $poll->add($backend, ZMQ::POLL_IN); // Poll frontend only if we have available workers if ($available_workers) { $poll->add($frontend, ZMQ::POLL_IN); } $events = $poll->poll($read, $write); foreach ($read as $socket) { $zmsg = new Zmsg($socket); $zmsg->recv(); // Handle worker activity on backend if ($socket === $backend) { // Use worker address for LRU routing assert($available_workers < MAX_WORKERS); array_push($worker_queue, $zmsg->unwrap()); $available_workers++; // Return reply to client if it's not a READY if ($zmsg->address() != "READY") { $zmsg->set_socket($frontend)->send(); } } elseif ($socket === $frontend) { // Now get next client request, route to next worker // REQ socket in worker needs an envelope delimiter // Dequeue and drop the next worker address $zmsg->wrap(array_shift($worker_queue), ""); $zmsg->set_socket($backend)->send(); $available_workers--; } } // We never exit the main loop }
// Poll frontend only if we have available workers if ($queue->size()) { $poll->add($frontend, ZMQ::POLL_IN); } $events = $poll->poll($read, $write, HEARTBEAT_INTERVAL * 1000 * 1000); // microseconds if ($events > 0) { foreach ($read as $socket) { $zmsg = new Zmsg($socket); $zmsg->recv(); // Handle worker activity on backend if ($socket === $backend) { $identity = $zmsg->unwrap(); // Return reply to client if it's not a control message if ($zmsg->parts() == 1) { if ($zmsg->address() == "READY") { $queue->s_worker_delete($identity); $queue->s_worker_append($identity); } else { if ($zmsg->address() == 'HEARTBEAT') { $queue->s_worker_refresh($identity); } else { printf("E: invalid message from %s%s%s", $identity, PHP_EOL, $zmsg->__toString()); } } } else { $zmsg->set_socket($frontend)->send(); $queue->s_worker_append($identity); } } else { // Now get next client request, route to next worker
// If we have no workers anyhow, wait indefinitely try { $events = $poll->poll($readable, $writeable, $capacity ? 1000000 : -1); } catch (ZMQPollException $e) { break; } if ($events > 0) { foreach ($readable as $socket) { $zmsg = new Zmsg($socket); // Handle reply from local worker if ($socket === $localbe) { $zmsg->recv(); // Use worker address for LRU routing $worker_queue[] = $zmsg->unwrap(); $capacity++; if ($zmsg->address() == "READY") { continue; } } else { if ($socket === $cloudbe) { // We don't use peer broker address for anything $zmsg->recv()->unwrap(); } } // Route reply to cloud if it's addressed to a broker for ($argn = 2; $argn < $_SERVER['argc']; $argn++) { if ($zmsg->address() == $_SERVER['argv'][$argn]) { $zmsg->set_socket($cloudfe)->send(); $zmsg = null; } }