Exemplo n.º 1
0
 /**
  * Makes sure the broker is running.
  * If it isn't running method will start it.
  *
  * @return int  Returns non false if broker is running
  */
 public static function ensureBrokerRunning()
 {
     $client = (new Client(\Scalr::config('scalr.crontab.sockets.broker')))->setTimeout(100)->setRetries(1)->setLogger(\Scalr::getContainer()->logger('Mdp\\Client')->setLevel(\Scalr::config('scalr.crontab.log_level')))->connect();
     $mmiReq = new Zmsg();
     $mmiReq->push("system.healthcheck");
     $mmiRep = $client->send("mmi.service", $mmiReq);
     if ($mmiRep) {
         $ok = $mmiRep->pop();
     } else {
         $ok = false;
         //Make sure another broker process isn't hanging
         self::terminateBroker();
         //Broker has to be started in the separate process
         $op = [];
         $logFile = \Scalr::config('scalr.crontab.log');
         exec(self::getStartBrokerCommand() . ' ' . ($logFile == '/dev/null' ? '> ' : '>> ') . escapeshellcmd($logFile) . ' 2>&1 & echo $!', $op);
         $pid = intval($op[0]);
     }
     return $ok;
 }
Exemplo n.º 2
0
 /**
  * Send request to broker and get reply by hook or crook.
  *
  * Takes ownership of request message and destroys it when sent.
  *
  *
  * @param   string  $service  The name of the service
  * @param   Zmsg    $request  Request message
  * @return  Zmsg    Returns the reply message or NULL if there was no reply.
  */
 public function send($service, Zmsg $request)
 {
     // Prefix request with protocol frames
     // Frame 1: "MDPCxy" (six bytes, MDP/Client)
     // Frame 2: Service name (printable string)
     $request->push($service);
     $request->push(Mdp::CLIENT);
     if ($this->verbose) {
         $this->log("ZMQDEBUG", "send request to '%s' service:\n--\n%s", $service, (string) $request);
     }
     $retries_left = $this->retries;
     $read = $write = array();
     while ($retries_left) {
         $request->setSocket($this->client)->send();
         // Poll socket for a reply, with timeout
         $poll = new ZMQPoll();
         $poll->add($this->client, ZMQ::POLL_IN);
         $events = $poll->poll($read, $write, $this->timeout);
         // If we got a reply, process it
         if ($events) {
             $request->recv();
             if ($this->verbose) {
                 $this->log("ZMQDEBUG", "received reply:\n--\n%s", $request);
             }
             if ($request->parts() < 3) {
                 throw new MdpException(sprintf("Expected more than 2 parts, but %d received", $request->parts()));
             }
             $header = $request->pop();
             if ($header !== Mdp::CLIENT) {
                 throw new MdpException(sprintf("Unexpected header %s, %s is expected", $header, Mdp::CLIENT));
             }
             $replyService = $request->pop();
             if ($replyService != $service) {
                 throw new MdpException(sprintf("Unexpected service %s, %s is expected.", $replyService, $service));
             }
             //Success
             return $request;
         } elseif ($retries_left--) {
             if ($this->verbose) {
                 $this->log("WARN", "no reply, reconnecting...");
             }
             // Reconnect
             $this->connect();
             // Resend message again
             $request->send();
         } else {
             if ($this->verbose) {
                 $this->log("ERROR", "permanent error, abandoning request");
                 break;
             }
         }
     }
 }
Exemplo n.º 3
0
 /**
  * Process message sent to us by a worker
  *
  * @param   string                 $sender The address of the worker
  * @param   \Scalr\System\Zmq\Zmsg $msg    The message
  */
 public function processWorker($sender, $msg)
 {
     $command = $msg->pop();
     $workerReady = isset($this->workers[$sender]);
     $worker = $this->fetchWorker($sender);
     if ($command == Mdp::WORKER_READY) {
         if ($workerReady) {
             // Not first command in session
             $this->deleteWorker($worker, true);
         } elseif (strlen($sender) >= 4 && substr($sender, 0, 4) == 'mmi.') {
             // Reserved service name
             $this->deleteWorker($worker, true);
         } else {
             // Attach worker to service and mark as idle
             $serviceFrame = $msg->pop();
             $worker->service = $this->fetchService($serviceFrame);
             $worker->service->workers++;
             $this->waitWorker($worker);
         }
     } elseif ($command == Mdp::WORKER_REPLY) {
         if ($workerReady) {
             // Remove & save client return envelope and insert the
             // protocol header and service name, then rewrap envelope.
             $client = $msg->unwrap();
             $msg->push($worker->service->name);
             $msg->push(Mdp::CLIENT);
             $msg->wrap($client, "");
             $msg->setSocket($this->socket)->send();
             if ($this->verbose) {
                 $this->log("ZMQDEBUG", "worker replied:\n--\n%s", (string) $msg);
             }
             $this->waitWorker($worker);
         } else {
             $this->deleteWorker($worker, true);
         }
     } elseif ($command == Mdp::WORKER_HEARTBEAT) {
         if ($workerReady) {
             $worker->expiry = microtime(true) + $this->heartbeatExpiry / 1000;
         } else {
             $this->deleteWorker($worker, true);
         }
     } elseif ($command == Mdp::WORKER_DISCONNECT) {
         $this->deleteWorker($worker, true);
         if ($this->verbose) {
             $this->log("ZMQDEBUG", "disconnect worker\n--\n%s", (string) $msg);
         }
     } else {
         if ($this->verbose) {
             $this->log("ERROR", "invalid input message\n--\n%s", (string) $msg);
         }
     }
 }
Exemplo n.º 4
0
 /**
  * Send request to broker and get reply by hook or crook.
  *
  * Takes ownership of request message and destroys it when sent.
  *
  *
  * @param   string  $service  The name of the service
  * @param   Zmsg    $request  Request message
  * @return  Zmsg    Returns the reply message or NULL if there was no reply.
  */
 public function send($service, Zmsg $request)
 {
     // Prefix request with protocol frames
     // Frame 0: empty (REQ emulation)
     // Frame 1: "MDPCxy" (six bytes, MDP/Client x.y)
     // Frame 2: Service name (printable string)
     $request->push($service);
     $request->push(Mdp::CLIENT);
     $request->push("");
     if ($this->verbose) {
         $this->log('ZMQDEBUG', "send request to '%s' service:\n--\n%s", $service, (string) $request);
     }
     $request->setSocket($this->client)->send();
 }
Exemplo n.º 5
0
 /**
  * Checks whether service is registered with the broker
  *
  * @param   string    $serviceName optional The name of the service.
  *
  * @return  int|bool  Returns the number of registered workers if service has been registered with the broker or
  *                    boolean FALSE otherwise
  */
 public function isServiceRegistered($serviceName = null)
 {
     $client = (new Client(\Scalr::config('scalr.crontab.sockets.broker')))->setTimeout(1000)->setRetries(1)->setLogger(\Scalr::getContainer()->logger('Mdp\\Client')->setLevel(\Scalr::config('scalr.crontab.log_level')))->connect();
     $mmiReq = new Zmsg();
     $mmiReq->push($serviceName ?: $this->name);
     $mmiRep = $client->send("mmi.service", $mmiReq);
     if ($mmiRep) {
         $code = $mmiRep->pop();
         $workers = $code == '200' ? (int) $mmiRep->pop() : 0;
     }
     return $mmiRep && $code == '200' ? $workers : (isset($code) ? 0 : false);
 }