Ejemplo n.º 1
0
 private function initSocket()
 {
     $zmq_context = new \ZMQContext();
     $this->zmq_socket = $zmq_context->getSocket(\ZMQ::SOCKET_REP);
     $this->zmq_socket->bind('ipc:///tmp/ebussola-job-schedule.ipc');
     chmod('/tmp/ebussola-job-schedule.ipc', 0777);
 }
Ejemplo n.º 2
0
 /**
  * @param string $protocol
  * @param string $encoding
  * @param bool   $synchronous
  * @param array  $endpoint
  */
 public function __construct($protocol, $encoding, $synchronous = false, array $endpoint = [])
 {
     parent::__construct($protocol, $encoding, $synchronous, $endpoint);
     list($type, $dsn, $force, $mode) = array_values($this->endpoint);
     $this->context = new \ZMQContext();
     $this->socket = new \ZMQSocket($this->context, $type);
     $this->socket->bind($dsn, $force);
     $this->mode = $mode;
 }
Ejemplo n.º 3
0
 public function connect()
 {
     $context = new \ZMQContext();
     $socket = new \ZMQSocket($context, \ZMQ::SOCKET_SUB);
     $socket->bind($this->dsn());
     return $socket;
 }
Ejemplo n.º 4
0
function broker_task()
{
    //  Prepare our context and sockets
    $context = new ZMQContext();
    $frontend = new ZMQSocket($context, ZMQ::SOCKET_ROUTER);
    $backend = new ZMQSocket($context, ZMQ::SOCKET_ROUTER);
    $frontend->bind("tcp://*:5555");
    $backend->bind("tcp://*:5556");
    //  Initialize poll set
    $poll = new ZMQPoll();
    $poll->add($frontend, ZMQ::POLL_IN);
    $poll->add($backend, ZMQ::POLL_IN);
    $read = $write = array();
    while (true) {
        $events = $poll->poll($read, $write);
        foreach ($read as $socket) {
            $zmsg = new Zmsg($socket);
            $zmsg->recv();
            if ($socket === $frontend) {
                $zmsg->push("W");
                $zmsg->set_socket($backend)->send();
            } elseif ($socket === $backend) {
                $zmsg->pop();
                $zmsg->push("C");
                $zmsg->set_socket($frontend)->send();
            }
        }
    }
}
 public function collect(OutputInterface $output)
 {
     $context = new \ZMQContext();
     $resultsQueue = new \ZMQSocket($context, \ZMQ::SOCKET_PULL);
     $resultsQueue->bind(Spider::ZMQ_RESULTS_QUEUE_BIND_DSN);
     $statusQueue = new \ZMQSocket($context, \ZMQ::SOCKET_PUSH);
     $statusQueue->bind(Spider::ZMQ_STATUS_QUEUE_BIND_DSN);
     $tstart = microtime(true);
     $collectedResults = 0;
     $expectedResults = PHP_INT_MAX;
     $output->writeln('Collecting Task results');
     while ($collectedResults < $expectedResults) {
         $string = $resultsQueue->recv();
         if ($string === Spider::ZMQ_COMMAND_BATCH_START) {
             //  Wait for start of batch
         } elseif (stripos($string, Spider::ZMQ_COMMAND_BATCH_END) === false) {
             $output->writeln('Got task result: ' . substr($string, 0, 20) . ' ...');
             file_put_contents($this->resultsTargetPath . '/' . md5($string) . '.result', $string);
             // TODO: use Symfony/Filesystem
             $output->writeln('Collected results so far: ' . ++$collectedResults);
         } else {
             $expectedResults = (int) explode('%', $string)[1];
             $output->writeln('[INFO] Trying to collect ' . $expectedResults . ' as requested by Task Loader');
         }
     }
     $tend = microtime(true);
     $totalMsec = ($tend - $tstart) * 1000;
     $output->writeln('Task results collecting finished. Got ' . $collectedResults . ' results');
     $output->writeln("Total elapsed time: {$totalMsec} msec");
     $output->writeln('Sending Task Result Collector info');
     $statusQueue->send($collectedResults);
 }
Ejemplo n.º 6
0
 /**
  * Start the worker and wait for requests
  */
 public function listen()
 {
     $context = new \ZMQContext();
     $server = new \ZMQSocket($context, \ZMQ::SOCKET_PULL);
     $server->bind('tcp://127.0.0.1:' . ($this->defaultPort + $this->client->getId() - 1));
     $this->logger->info('Client worker ' . $this->client . ' is ready');
     while (true) {
         $request = $server->recv();
         $this->logger->debug('Client worker ' . $this->client . ' receiving request : ' . $request);
         // Check if the input is valid, ignore if wrong
         $request = json_decode($request, true);
         if (!$this->isValidInput($request)) {
             $this->logger->error('Client worker ' . $this->client . ' received an invalid input');
             continue;
         }
         try {
             // Call the right method in the client and push to redis the result
             $result = call_user_func_array(array($this->client, $request['command']), $request['parameters']);
         } catch (ClientNotReadyException $e) {
             $this->logger->warning('Client worker ' . $this->client . ' received a request (#' . $request['invokeId'] . ') whereas the client is not ready. This is normal in case of client reconnection process. Ignoring.');
             continue;
         }
         $key = $this->key . '.client.commands.' . $request['invokeId'];
         $this->redis->rpush($key, serialize($result));
         $this->redis->expire($key, $this->expire);
     }
 }
Ejemplo n.º 7
0
 /**
  * Run ZMQ interface for generator
  * 
  * Req-rep pattern; msgs are commands:
  * 
  * GEN    = Generate ID
  * STATUS = Get status string
  */
 public function run()
 {
     $context = new \ZMQContext();
     $receiver = new \ZMQSocket($context, \ZMQ::SOCKET_REP);
     $bindTo = 'tcp://*:' . $this->port;
     echo "Binding to {$bindTo}\n";
     $receiver->bind($bindTo);
     while (TRUE) {
         $msg = $receiver->recv();
         switch ($msg) {
             case 'GEN':
                 try {
                     $response = $this->generator->generate();
                 } catch (\Exception $e) {
                     $response = "ERROR";
                 }
                 break;
             case 'STATUS':
                 $response = json_encode($this->generator->status());
                 break;
             default:
                 $response = 'UNKNOWN COMMAND';
                 break;
         }
         $receiver->send($response);
     }
 }
Ejemplo n.º 8
0
 /**
  * @return void
  */
 protected function init()
 {
     $this->logger->info("Running " . self::class . " on " . str_replace("\n", "", `hostname; echo ' - ';uname -a;`));
     $this->logger->info("The eviction tick rate is set to {$this->config->getEvictionTicksPerSec()}/second.");
     // Create the event loop
     $this->reactLoop = React\EventLoop\Factory::create();
     // Object pool
     $this->queue = new PriorityHashQueue();
     // In default mode the latest data will be replaced for a given key. In DATA_MODE_APPEND the data will be appended
     // internally and available within the consumer as array (for instance for reducing purposes)
     //$this->queue->setDataMode(PriorityHashQueue::DATA_MODE_APPEND);
     // Setup ZMQ to send evicted objects.
     $this->zmqContext = new React\ZMQ\Context($this->reactLoop);
     $this->logger->info("Binding inbound ZMQ to '{$this->config->getZmqIn()}'.");
     // Receiver queue for incoming objects
     $this->zmqInboundQueue = $this->zmqContext->getSocket(\ZMQ::SOCKET_PULL);
     $this->zmqInboundQueue->bind($this->config->getZmqIn());
     $this->logger->info("Binding outbound ZMQ to '{$this->config->getZmqOut()}'.");
     // Outgoing queue for evicted objects
     $this->zmqOutboundQueue = $this->zmqContext->getSocket(\ZMQ::SOCKET_PUSH);
     $this->zmqOutboundQueue->bind($this->config->getZmqOut());
     // Register events
     $this->registerInboundEvents();
     $this->registerEvictionEvents();
     $this->registerTimedEvents();
 }
 /**
  * @param \ZMQContext $context
  * @return bool
  */
 public function connect(\ZMQContext $context)
 {
     $this->clientChannel = new \ZMQSocket($context, ZMQ::SOCKET_ROUTER);
     $this->workerChannel = new \ZMQSocket($context, ZMQ::SOCKET_ROUTER);
     try {
         $this->clientChannel->bind("tcp://*:{$this->config->getClientPort()}");
         $this->workerChannel->bind("tcp://*:{$this->config->getWorkerPort()}");
         return true;
     } catch (\ZMQSocketException $e) {
         return false;
     } catch (\ZMQException $e) {
         return false;
     } catch (\Exception $e) {
         return false;
     }
 }
Ejemplo n.º 10
0
 /**
  * @param $context
  * @param $endpoint
  * @return Zmsg
  */
 private function createPublisher($context, $endpoint)
 {
     $publisher = new \ZMQSocket($context, \ZMQ::SOCKET_PUB);
     $publisher->setSockOpt(\ZMQ::SOCKOPT_SNDHWM, 1);
     $publisher->setSockOpt(\ZMQ::SOCKOPT_LINGER, 0);
     $publisher->bind($endpoint);
     return new Zmsg($publisher);
 }
Ejemplo n.º 11
0
 /**
  * @param array[string]string $connUris
  */
 private function initSockets(array $connUris)
 {
     // Create context
     $this->reactLoop = ReactFactory::create();
     /** @var ReactZmqContext|\ZMQContext $reactZmqContext */
     $reactZmqContext = new ReactZmqContext($this->reactLoop);
     $this->hbSocket = $reactZmqContext->getSocket(\ZMQ::SOCKET_REP);
     $this->hbSocket->bind($connUris['hb']);
     $this->iopubSocket = $reactZmqContext->getSocket(\ZMQ::SOCKET_PUB);
     $this->iopubSocket->bind($connUris['iopub']);
     $this->controlSocket = $reactZmqContext->getSocket(\ZMQ::SOCKET_ROUTER);
     $this->controlSocket->bind($connUris['control']);
     $this->stdinSocket = $reactZmqContext->getSocket(\ZMQ::SOCKET_ROUTER);
     $this->stdinSocket->bind($connUris['stdin']);
     $this->shellSocket = $reactZmqContext->getSocket(\ZMQ::SOCKET_ROUTER);
     $this->shellSocket->bind($connUris['shell']);
 }
Ejemplo n.º 12
0
 protected function setupPullSocket($queueId)
 {
     $connect = true;
     if (!empty($this->pull)) {
         $endpoints = $this->pull->getendpoints();
         if (!empty($endpoints["bind"][0]) && $endpoints["bind"][0] != $queueId) {
             $this->pull->unbind($endpoints["bind"][0]);
         } else {
             $connect = false;
         }
     } else {
         $this->pull = $this->socketFactory->createPullSocket();
     }
     if ($connect) {
         $this->pull->bind($queueId);
     }
 }
Ejemplo n.º 13
0
 /**
  * @param $context
  * @param $endpoint
  * @return Zmsg
  */
 private function createCollector($context, $endpoint)
 {
     $receiver = new \ZMQSocket($context, \ZMQ::SOCKET_SUB);
     $receiver->setSockOpt(\ZMQ::SOCKOPT_LINGER, 0);
     $receiver->setSockOpt(\ZMQ::SOCKOPT_SUBSCRIBE, "");
     $receiver->bind($endpoint);
     return $receiver;
 }
Ejemplo n.º 14
0
 /**
  * Binds broker to endpoint
  *
  * We use a single socket for both clients and workers.
  *
  * @param   string   $endpoint
  * @return  Broker
  */
 public function bind($endpoint)
 {
     $this->endpoint = $endpoint;
     $this->socket->bind($this->endpoint);
     if ($this->verbose) {
         $this->log("ZMQDEBUG", "MDP broker/0.1.1 is active at %s", $this->endpoint);
     }
     return $this;
 }
Ejemplo n.º 15
0
 /**
  * @return null
  */
 protected function initSockets()
 {
     $this->replyToReplyStack = $this->context->getSocket(\ZMQ::SOCKET_REP);
     $this->replyToReplyStack->bind($this->pulsarSocketsParams->getReplyToReplyStackSocketAddress());
     $this->publisher = $this->context->getSocket(\ZMQ::SOCKET_PUB);
     $this->publisher->bind($this->pulsarSocketsParams->getPublishSocketAddress());
     $this->pullActionInfo = $this->context->getSocket(\ZMQ::SOCKET_PULL);
     $this->pullActionInfo->bind($this->pulsarSocketsParams->getPullSocketAddress());
     return null;
 }
Ejemplo n.º 16
0
 /**
  * @return null
  */
 public function startCommunication()
 {
     $this->initLoop();
     $this->context = new \ZMQContext();
     $this->pulsarRequestSocket = $this->context->getSocket(\ZMQ::SOCKET_REQ);
     $this->performersReplySocket = $this->context->getSocket(\ZMQ::SOCKET_REP);
     $this->initStreams();
     $replyStackErrorDtoAlreadySent = false;
     /**
      * Receive sockets params from Pulsar and start cyclical communication
      */
     $this->readStream->on(EventsConstants::DATA, function ($data) use($replyStackErrorDtoAlreadySent) {
         $replyStackDto = null;
         $replyStackDto = @unserialize($data);
         if ($replyStackDto !== false && $replyStackDto instanceof ReplyStackDto) {
             $this->pulsarRequestSocket->connect($replyStackDto->getReplyStackVsPulsarSocketAddress());
             $this->performersReplySocket->bind($replyStackDto->getReplyStackVsPerformersSocketAddress());
             $this->moduleDto = $replyStackDto;
             $initDto = new InitStartMethodDto();
             $initDto->setShutDownArg('warning');
             $this->initStartMethods($initDto);
             //TODO: make resolver of ways of ReplyStack logging
             //$this->logger->debug("ReplyStack receive initDto from Pulsar.");
             $this->loop->nextTick([$this, 'startStackWork']);
         } else {
             if ($replyStackErrorDtoAlreadySent === false) {
                 $replyStackErrorDtoAlreadySent = true;
                 $replyStackError = new ReplyStackErrorDto();
                 $replyStackError->setErrorLevel(ErrorsConstants::CRITICAL);
                 $replyStackError->setErrorReason(PulsarErrorConstants::REPLY_STACK_RECEIVE_NOT_CORRECT_DTO);
                 //write to Pulsar's allotted STDIN about critical error
                 $this->writeStream->write(serialize($replyStackError));
                 $this->loop->nextTick(function () {
                     $this->loop->stop();
                 });
             }
         }
     });
     $this->loop->run();
     return null;
 }
Ejemplo n.º 17
0
 public function testComplex()
 {
     $context = new \ZMQContext();
     $output = new \ZMQSocket($context, \ZMQ::SOCKET_DEALER);
     $output->bind("inproc://zmsg_selftest");
     $input = new \ZMQSocket($context, \ZMQ::SOCKET_ROUTER);
     $input->connect("inproc://zmsg_selftest");
     //  Test send and receive of single-part message
     $zmsgo = new Zmsg($output);
     $zmsgo->setLast("Hello");
     $this->assertTrue($zmsgo->getLast() == "Hello");
     $zmsgo->send();
     $zmsgi = new Zmsg($input);
     $zmsgi->recv();
     $this->assertTrue($zmsgi->parts() == 2);
     $this->assertTrue($zmsgi->getLast() == "Hello");
     //  Test send and receive of multi-part message
     $zmsgo = new Zmsg($output);
     $zmsgo->setLast("Hello");
     $zmsgo->wrap("address1", "");
     $zmsgo->wrap("address2");
     $this->assertTrue($zmsgo->parts() == 4);
     $zmsgo->send();
     $zmsgi = new Zmsg($input);
     $zmsgi->recv();
     $this->assertTrue($zmsgi->parts() == 5);
     $zmsgi->unwrap();
     $this->assertTrue($zmsgi->unwrap() == "address2");
     $zmsgi->setLast(sprintf("%s%s", 'W', "orld"));
     $this->assertTrue($zmsgi->getLast() == "World");
     //  Pull off address 1, check that empty part was dropped
     $zmsgi->unwrap();
     $this->assertTrue($zmsgi->parts() == 1);
     //  Check that message body was correctly modified
     $part = $zmsgi->pop();
     $this->assertTrue($part == "World");
     $this->assertTrue($zmsgi->parts() == 0);
     // Test load and save
     $zmsg = new Zmsg();
     $zmsg->setLast("Hello");
     $zmsg->wrap("address1", "");
     $zmsg->wrap("address2");
     $this->assertTrue($zmsg->parts() == 4);
     $fh = fopen(sys_get_temp_dir() . "/zmsgtest.zmsg", 'w');
     $zmsg->save($fh);
     fclose($fh);
     $fh = fopen(sys_get_temp_dir() . "/zmsgtest.zmsg", 'r');
     $zmsg2 = new Zmsg();
     $zmsg2->load($fh);
     assert($zmsg2->getLast() == $zmsg->getLast());
     fclose($fh);
     $this->assertTrue($zmsg2->parts() == 4);
 }
Ejemplo n.º 18
0
function publisher()
{
    $context = new ZMQContext();
    //  Prepare publisher
    $publisher = new ZMQSocket($context, ZMQ::SOCKET_PUB);
    $publisher->bind("tcp://*:5556");
    while (true) {
        //  Send current clock (msecs) to subscribers
        $publisher->send(microtime(true));
        usleep(1000);
        //  1msec wait
    }
}
Ejemplo n.º 19
0
 public function handlerAction()
 {
     try {
         // setup the ZMQ content so as to avoid issues with conflicts
         $ctx = new \ZMQContext();
         // create a SOCKET_REP server
         $server = new \ZMQSocket($ctx, \ZMQ::SOCKET_REP);
         //  configure the server socket to not wait at close time
         // this is intended to minimise the possibility of messages being received and not handled
         // however as is mentioned in the TODO below they should be handle them explicitly
         $server->setSockOpt(\ZMQ::SOCKOPT_LINGER, 0);
         // bind it to tcp on port 5454
         $server->bind('tcp://*:5454');
         // create a Poll object to enable us to utilize the REQUEST_TIMEOUT functionality
         $poll = new \ZMQPoll();
         $poll->add($server, \ZMQ::POLL_IN);
         // initialise the read/write buffers for polling
         $read = $write = array();
         // get the time that we start the loop
         $start = time();
         do {
             // this instruction will wait for a message or the timeout to occur
             $events = $poll->poll($read, $write, REQUEST_TIMEOUT);
             // @TODO since exiting the loop will happens after this point a race condition exists
             // We need to consider solutions that will ensure ALL messages to $server are processed
             // if the loop will exit after this iteration.
             // one could check the $events variable as this contains the number of events
             // however in this situation we only want to process the $read resources and can
             // just loop through an array (if it is empty nothing will be done)
             foreach ($read as $socket) {
                 $message = $socket->recv();
                 $server->send($message . ' World');
             }
             // ensure that even when a message is processed the handler
             // does not timeout until the REQUEST_TIMEOUT period
             // has elapsed
             $active = time() - $start < REQUEST_TIMEOUT / 1000.0;
         } while ($active);
     } catch (Exception $e) {
         // handle the exception
         // @TODO
     }
     // exit the handler
     die('This handler has timed out');
 }
Ejemplo n.º 20
0
function server_task()
{
    //  Launch pool of worker threads, precise number is not critical
    for ($thread_nbr = 0; $thread_nbr < 5; $thread_nbr++) {
        $pid = pcntl_fork();
        if ($pid == 0) {
            server_worker();
            exit;
        }
    }
    $context = new ZMQContext();
    //  Frontend socket talks to clients over TCP
    $frontend = new ZMQSocket($context, ZMQ::SOCKET_ROUTER);
    $frontend->bind("tcp://*:5570");
    //  Backend socket talks to workers over ipc
    $backend = new ZMQSocket($context, ZMQ::SOCKET_DEALER);
    $backend->bind("ipc://backend");
    //  Connect backend to frontend via a queue device
    //  We could do this:
    //      $device = new ZMQDevice($frontend, $backend);
    //  But doing it ourselves means we can debug this more easily
    $read = $write = array();
    //  Switch messages between frontend and backend
    while (true) {
        $poll = new ZMQPoll();
        $poll->add($frontend, ZMQ::POLL_IN);
        $poll->add($backend, ZMQ::POLL_IN);
        $poll->poll($read, $write);
        foreach ($read as $socket) {
            $zmsg = new Zmsg($socket);
            $zmsg->recv();
            if ($socket === $frontend) {
                //echo "Request from client:";
                //echo $zmsg->__toString();
                $zmsg->set_socket($backend)->send();
            } else {
                if ($socket === $backend) {
                    //echo "Request from worker:";
                    //echo $zmsg->__toString();
                    $zmsg->set_socket($frontend)->send();
                }
            }
        }
    }
}
Ejemplo n.º 21
0
 /**
  * Starts an endless running service
  */
 public function start()
 {
     $context = new \ZMQContext();
     $zmq = new \ZMQSocket($context, \ZMQ::SOCKET_REP);
     $zmq->bind($this->socket);
     while (true) {
         try {
             $message = '' . $zmq->recv();
             $object = json_decode($message, true);
             $method = $object['method'];
             $args = $object['params'];
             $id = $object['id'];
             $response = $this->handleRequest($id, $method, $args);
             $zmq->send(json_encode($response));
         } catch (\Exception $e) {
         }
     }
 }
Ejemplo n.º 22
0
 protected function declareReplyToPm()
 {
     $this->replyToPmSocket = $this->context->getSocket(\ZMQ::SOCKET_REP);
     $this->replyToPmSocket->bind($this->loadManagerDto->getPmLmSocketsParams()->getPmLmRequestAddress());
     $this->replyToPmSocket->on(EventsConstants::ERROR, function (\Exception $e) {
         $this->logger->error(LoggingExceptions::getExceptionString($e));
     });
     $this->replyToPmSocket->on(EventsConstants::MESSAGE, function ($receivedDtoContainer) {
         /**
          * @var DtoContainer $dtoContainer
          */
         $dtoContainer = unserialize($receivedDtoContainer);
         $this->processReceivedControlDto($dtoContainer->getDto());
         $this->receivePmInfo = true;
         $this->replyToPmSocket->send(serialize($this->dtoContainer));
     });
     return null;
 }
Ejemplo n.º 23
0
function step2()
{
    $pid = pcntl_fork();
    if ($pid == 0) {
        step1();
        exit;
    }
    $context = new ZMQContext();
    //  Bind to ipc: endpoint, then start upstream thread
    $receiver = new ZMQSocket($context, ZMQ::SOCKET_PAIR);
    $receiver->bind("ipc://step2.ipc");
    // Wait for signal
    $receiver->recv();
    // Signal downstream to step 3
    $sender = new ZMQSocket($context, ZMQ::SOCKET_PAIR);
    $sender->connect("ipc://step3.ipc");
    $sender->send("");
}
Ejemplo n.º 24
0
 public function load($inputStream, OutputInterface $output)
 {
     $context = new \ZMQContext();
     $tasksQueue = new \ZMQSocket($context, \ZMQ::SOCKET_PUSH);
     $tasksQueue->bind(Spider::ZMQ_TASKS_QUEUE_BIND_DSN);
     $statusQueue = new \ZMQSocket($context, \ZMQ::SOCKET_PULL);
     $statusQueue->connect(Spider::ZMQ_STATUS_QUEUE_DSN);
     /*
      * http://zguide.zeromq.org/php:all#advanced-request-reply
      * We have to synchronize the start of the batch with all workers being up and running.
      * This is a fairly common gotcha in ZeroMQ and there is no easy solution.
      * The zmq_connect method takes a certain time.
      * So when a set of workers connect to the ventilator, the first one to successfully connect will get a whole load of messages
      * in that short time while the others are also connecting.
      * If you don't synchronize the start of the batch somehow, the system won't run in parallel at all.
      * Try removing the wait in the ventilator, and see what happens.
      */
     $output->writeln('Giving workers some time to connect');
     sleep(3);
     //  The first message is "BATCH_START%" and signals start of batch
     $tasksQueue->send(Spider::ZMQ_COMMAND_BATCH_START);
     $taskCount = 0;
     while (($task = fgets($inputStream)) !== false) {
         $task = trim(preg_replace('/\\s\\s+/', ' ', $task));
         $tasksQueue->send($task);
         ++$taskCount;
     }
     $tasksQueue->send(Spider::ZMQ_COMMAND_BATCH_END . $taskCount);
     // send info for result collector how many results it should expect
     $output->writeln("<info>Total count of Tasks put in the Queue: {$taskCount}</info>");
     sleep(1);
     //  Give 0MQ time to deliver
     $output->writeln('Waiting for acknowledgement from Task Result Collector');
     $output->writeln('Info from Task Result Collector: ' . $statusQueue->recv());
     $output->writeln('<info>Informing all workers to stop</info>');
     for ($i = 0; $i < 10; ++$i) {
         $tasksQueue->send(Spider::ZMQ_COMMAND_WORKER_QUIT);
     }
 }
Ejemplo n.º 25
0
<?php

/*
 * Simple request-reply broker
 * @author Ian Barber <ian(dot)barber(at)gmail(dot)com>
 */
//  Prepare our context and sockets
$context = new ZMQContext();
$frontend = new ZMQSocket($context, ZMQ::SOCKET_ROUTER);
$backend = new ZMQSocket($context, ZMQ::SOCKET_DEALER);
$frontend->bind("tcp://*:5559");
$backend->bind("tcp://*:5560");
//  Initialize poll set
$poll = new ZMQPoll();
$poll->add($frontend, ZMQ::POLL_IN);
$poll->add($backend, ZMQ::POLL_IN);
$readable = $writeable = array();
//  Switch messages between sockets
while (true) {
    $events = $poll->poll($readable, $writeable);
    foreach ($readable as $socket) {
        if ($socket === $frontend) {
            //  Process all parts of the message
            while (true) {
                $message = $socket->recv();
                //  Multipart detection
                $more = $socket->getSockOpt(ZMQ::SOCKOPT_RCVMORE);
                $backend->send($message, $more ? ZMQ::MODE_SNDMORE : null);
                if (!$more) {
                    break;
                    //  Last message part
Ejemplo n.º 26
0
<?php

/*
 * Lazy Pirate server
 * Binds REQ socket to tcp://*:5555
 * Like hwserver except:
 * - echoes request as-is
 * - randomly runs slowly, or exits to simulate a crash.
 * 
 * @author Ian Barber <ian(dot)barber(at)gmail(dot)com>
 */
$context = new ZMQContext();
$server = new ZMQSocket($context, ZMQ::SOCKET_REP);
$server->bind("tcp://*:5555");
$cycles = 0;
while (true) {
    $request = $server->recv();
    $cycles++;
    //  Simulate various problems, after a few cycles
    if ($cycles > 3 && rand(0, 3) == 0) {
        echo "I: simulating a crash", PHP_EOL;
        break;
    } else {
        if ($cycles > 3 && rand(0, 3) == 0) {
            echo "I: simulating CPU overload", PHP_EOL;
            sleep(5);
        }
    }
    printf("I: normal request (%s)%s", $request, PHP_EOL);
    sleep(1);
    // Do some heavy work
Ejemplo n.º 27
0
<?php

/**
 * Created by PhpStorm.
 * User: henrygrech-cini
 * Date: 30/10/2014
 * Time: 22:46
 */
$ctx = new ZMQContext();
$server = new ZMQSocket($ctx, ZMQ::SOCKET_REP);
$server->bind('tcp://*:5454');
while (true) {
    $message = $server->recv();
    $server->send($message . ' World');
}
Ejemplo n.º 28
0
    // Socket to talk to dispatcher
    $receiver = new ZMQSocket($context, ZMQ::SOCKET_REP);
    $receiver->connect("ipc://workers.ipc");
    while (true) {
        $string = $receiver->recv();
        printf("Received request: [%s]%s", $string, PHP_EOL);
        // Do some 'work'
        sleep(1);
        // Send reply back to client
        $receiver->send("World");
    }
}
//  Launch pool of worker threads
for ($thread_nbr = 0; $thread_nbr != 5; $thread_nbr++) {
    $pid = pcntl_fork();
    if ($pid == 0) {
        worker_routine();
        exit;
    }
}
//  Prepare our context and sockets
$context = new ZMQContext();
//  Socket to talk to clients
$clients = new ZMQSocket($context, ZMQ::SOCKET_ROUTER);
$clients->bind("tcp://*:5555");
//  Socket to talk to workers
$workers = new ZMQSocket($context, ZMQ::SOCKET_DEALER);
$workers->bind("ipc://workers.ipc");
//  Connect work threads to client threads via a queue
$device = new ZMQDevice($clients, $workers);
$device->run();
Ejemplo n.º 29
0
function main()
{
    for ($client_nbr = 0; $client_nbr < NBR_CLIENTS; $client_nbr++) {
        $pid = pcntl_fork();
        if ($pid == 0) {
            client_thread();
            return;
        }
    }
    for ($worker_nbr = 0; $worker_nbr < NBR_WORKERS; $worker_nbr++) {
        $pid = pcntl_fork();
        if ($pid == 0) {
            worker_thread();
            return;
        }
    }
    $context = new ZMQContext();
    $frontend = new ZMQSocket($context, ZMQ::SOCKET_ROUTER);
    $backend = new ZMQSocket($context, ZMQ::SOCKET_ROUTER);
    $frontend->bind("ipc://frontend.ipc");
    $backend->bind("ipc://backend.ipc");
    //  Logic of LRU loop
    //  - Poll backend always, frontend only if 1+ worker ready
    //  - If worker replies, queue worker as ready and forward reply
    //    to client if necessary
    //  - If client requests, pop next worker and send request to it
    //  Queue of available workers
    $available_workers = 0;
    $worker_queue = array();
    $writeable = $readable = array();
    while ($client_nbr > 0) {
        $poll = new ZMQPoll();
        //  Poll front-end only if we have available workers
        if ($available_workers > 0) {
            $poll->add($frontend, ZMQ::POLL_IN);
        }
        //  Always poll for worker activity on backend
        $poll->add($backend, ZMQ::POLL_IN);
        $events = $poll->poll($readable, $writeable);
        if ($events > 0) {
            foreach ($readable as $socket) {
                //  Handle worker activity on backend
                if ($socket === $backend) {
                    //  Queue worker address for LRU routing
                    $worker_addr = $socket->recv();
                    assert($available_workers < NBR_WORKERS);
                    $available_workers++;
                    array_push($worker_queue, $worker_addr);
                    //  Second frame is empty
                    $empty = $socket->recv();
                    assert(empty($empty));
                    //  Third frame is READY or else a client reply address
                    $client_addr = $socket->recv();
                    if ($client_addr != "READY") {
                        $empty = $socket->recv();
                        assert(empty($empty));
                        $reply = $socket->recv();
                        $frontend->send($client_addr, ZMQ::MODE_SNDMORE);
                        $frontend->send("", ZMQ::MODE_SNDMORE);
                        $frontend->send($reply);
                        // exit after all messages relayed
                        $client_nbr--;
                    }
                } elseif ($socket === $frontend) {
                    //  Now get next client request, route to LRU worker
                    //  Client request is [address][empty][request]
                    $client_addr = $socket->recv();
                    $empty = $socket->recv();
                    assert(empty($empty));
                    $request = $socket->recv();
                    $backend->send(array_shift($worker_queue), ZMQ::MODE_SNDMORE);
                    $backend->send("", ZMQ::MODE_SNDMORE);
                    $backend->send($client_addr, ZMQ::MODE_SNDMORE);
                    $backend->send("", ZMQ::MODE_SNDMORE);
                    $backend->send($request);
                    $available_workers--;
                }
            }
        }
    }
    // Clean up our worker processes
    foreach ($worker_queue as $worker) {
        $backend->send($worker, ZMQ::MODE_SNDMORE);
        $backend->send("", ZMQ::MODE_SNDMORE);
        $backend->send('END');
    }
    sleep(1);
}
Ejemplo n.º 30
0
$endpoint = sprintf("ipc://%s-cloud.ipc", $self);
$cloudfe->setSockOpt(ZMQ::SOCKOPT_IDENTITY, $self);
$cloudfe->bind($endpoint);
//  Connect cloud backend to all peers
$cloudbe = $context->getSocket(ZMQ::SOCKET_XREP);
$cloudbe->setSockOpt(ZMQ::SOCKOPT_IDENTITY, $self);
for ($argn = 2; $argn < $_SERVER['argc']; $argn++) {
    $peer = $_SERVER['argv'][$argn];
    printf("I: connecting to cloud backend at '%s'%s", $peer, PHP_EOL);
    $endpoint = sprintf("ipc://%s-cloud.ipc", $peer);
    $cloudbe->connect($endpoint);
}
//  Bind state backend / publisher to endpoint
$statebe = new ZMQSocket($context, ZMQ::SOCKET_PUB);
$endpoint = sprintf("ipc://%s-state.ipc", $self);
$statebe->bind($endpoint);
//  Connect statefe to all peers
$statefe = $context->getSocket(ZMQ::SOCKET_SUB);
$statefe->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, "");
for ($argn = 2; $argn < $_SERVER['argc']; $argn++) {
    $peer = $_SERVER['argv'][$argn];
    printf("I: connecting to state backend at '%s'%s", $peer, PHP_EOL);
    $endpoint = sprintf("ipc://%s-state.ipc", $peer);
    $statefe->connect($endpoint);
}
//  Prepare monitor socket
$monitor = new ZMQSocket($context, ZMQ::SOCKET_PULL);
$endpoint = sprintf("ipc://%s-monitor.ipc", $self);
$monitor->bind($endpoint);
//  Prepare local frontend and backend
$localfe = new ZMQSocket($context, ZMQ::SOCKET_XREP);