Пример #1
0
 public function run($daemon = false)
 {
     if ($daemon) {
         ProcessUtil::daemon();
     }
     $rand = mt_rand();
     $title = $this->title_;
     $ipcs = array(sprintf('ipc:///%s/ipc%d_%s_0.sock', $this->sock_dir_, $rand, $this->title_), sprintf('ipc:///%s/ipc%d_%s_1.sock', $this->sock_dir_, $rand, $this->title_));
     ProcessUtil::setTitle(sprintf('%s<controller>', $title));
     PeriodicGc::enable(300);
     $controller = new Controller();
     $controller->run(array('groups' => array(array('proxy' => array('routine' => function () use($ipcs, $title) {
         ProcessUtil::setTitle(sprintf('%s<proxy>', $title));
         $proxy = new Proxy($this->listen_addr_, $ipcs);
         $proxy->run();
     }), 'worker' => array('routine' => function () use($ipcs, $title) {
         ProcessUtil::setTitle(sprintf('%s<worker>', $title));
         if (isset($this->init_callback_)) {
             if (false === call_user_func($this->init_callback_)) {
                 \ServerBench\syslog_error('init_callback returns false.');
                 return;
             }
         }
         $worker = new Worker($ipcs, $this->message_callback_);
         $worker->run();
     }, 'num' => $this->process_num_ < 1 ? 1 : $this->process_num_)))), $this->dir_);
 }
Пример #2
0
 public function run()
 {
     $acceptor = $this->acceptor_;
     $ipc0 = $this->ipc0_;
     $ipc1 = $this->ipc1_;
     $timer = Timer::getInstance();
     $poller = new ZMQPoll();
     $poller->add($acceptor, ZMQ::POLL_IN);
     $poller->add($ipc1, ZMQ::POLL_IN);
     $loop = Loop::getInstance();
     $loop->start();
     while ($loop->running()) {
         // not execute timer too many times
         $timer->execute(64);
         $writable = [];
         $readable = [];
         try {
             if ($timer->isEmpty()) {
                 $events = $poller->poll($readable, $writable, $this->max_wait_ms_);
             } else {
                 $nearest_delta_ms = $timer->nearestDeltaTimeMs();
                 if ($this->max_wait_ms_ > 0 && $this->max_wait_ms_ < $nearest_delta_ms) {
                     $real_wait_ms = $this->max_wait_ms_;
                 } else {
                     if ($nearest_delta_ms < 0) {
                         $nearest_delta_ms = 0;
                     }
                     $real_wait_ms = $nearest_delta_ms;
                 }
                 $events = $poller->poll($readable, $writable, $real_wait_ms);
             }
         } catch (ZMQPollException $e) {
             if (4 == $e->getCode()) {
                 continue;
             }
             throw $e;
         }
         if ($events > 0) {
             foreach ($readable as $socket) {
                 if ($socket === $ipc1) {
                     while (true) {
                         try {
                             $msg = $socket->recvMulti(ZMQ::MODE_NOBLOCK);
                             if (false === $msg) {
                                 // would block
                                 break;
                             }
                             if (count($msg) !== 3 || !empty($msg[1])) {
                                 \ServerBench\syslog_error('invalid msg(%s) from worker.', [var_export($msg, true)]);
                                 break;
                             }
                             $rc = false;
                             do {
                                 try {
                                     $rc = $acceptor->sendmulti([$msg[0], '', $msg[2]], ZMQ::MODE_NOBLOCK);
                                 } catch (ZMQSocketException $e) {
                                     if (4 == $e->getCode()) {
                                         continue;
                                     }
                                     throw $e;
                                 }
                                 break;
                             } while (true);
                             if (false === $rc) {
                                 \ServerBench\syslog_error('sending\'s mq is out of memory, msg(%s) would lose', [$msg[2]]);
                             }
                         } catch (ZMQSocketException $e) {
                             if (4 == $e->getCode()) {
                                 continue;
                             }
                             throw $e;
                         }
                     }
                 } elseif ($socket === $acceptor) {
                     // acceptor
                     for ($i = 0; $i < 4096; ++$i) {
                         try {
                             $msg = $acceptor->recvMulti(ZMQ::MODE_NOBLOCK);
                             if (false === $msg) {
                                 break;
                             }
                             if (count($msg) !== 3 || !empty($msg[1])) {
                                 \ServerBench\syslog_error('invalid msg(%s) from client.', [var_export($msg, true)]);
                                 break;
                             }
                             $rc = false;
                             do {
                                 try {
                                     $rc = $ipc0->sendmulti([$msg[0], '', $msg[2]], ZMQ::MODE_NOBLOCK);
                                 } catch (ZMQSocketException $e) {
                                     if (4 == $e->getCode()) {
                                         continue;
                                     }
                                 }
                                 break;
                             } while (true);
                             if (false === $rc) {
                                 \ServerBench\syslog_error('ipc0\'s mq is out of memory, msg(%s) would lose.', [var_export($msg, true)]);
                             }
                         } catch (ZMQSocketException $e) {
                             if (4 == $e->getCode()) {
                                 continue;
                             }
                             throw $e;
                         }
                     }
                 } else {
                     // unexpected branch.
                 }
             }
         }
     }
 }
Пример #3
0
}
$pid = getmypid();
\ServerBench\syslog_info('pid of controller is %d', [$pid]);
$pidfile = $arguments->get('pidfile');
if (isset($pidfile)) {
    $realpath_pidfile = realpath($pidfile);
    if (file_exists($realpath_pidfile) && file_get_contents($pidfile) != '') {
        \ServerBench\syslog_error('there is a running instance already.');
        exit;
    }
    file_put_contents($pidfile, $pid);
    register_shutdown_function(function () use($pidfile) {
        @unlink($pidfile);
    });
}
ProcessUtil::setTitle($arguments->get('title', 'serverbench<controller>'));
try {
    $api = new Api('controller', include $app_path);
    if (false === $api->init()) {
        \ServerBench\syslog_error('app->init(\'controller\') returns false.');
        exit;
    }
    PeriodicGc::enable(300);
    $controller = new Controller();
    $controller->run(['groups' => [['proxy' => ['routine' => [$phpbin, ['-r', sprintf('require(\'%s\');', __DIR__ . '/start_proxy.php'), '--', '--title', sprintf('%s<proxy>', $title), '--listen', $listen_addr, '--app', $app_path, '--ipcs', $ipcs]]], 'worker' => ['routine' => [$phpbin, ['-r', sprintf('require(\'%s\');', __DIR__ . '/start_worker.php'), '--', '--title', sprintf('%s<worker>', $title), '--app', $app_path, '--ipcs', $ipcs]], 'num' => $workers]]]], $dir);
    if (false === $api->fini()) {
        \ServerBench\syslog_error('app->fini(\'controller\') returns false.');
    }
} catch (Exception $e) {
    \ServerBench\syslog_error('uncaught exception from controller: %s', [$e]);
}
Пример #4
0
if (!isset($arguments['listen'])) {
    \ServerBench\Cli\printf_and_exit("argument --listen or -l should be set.\n");
}
$listen_addr = explode(',', $arguments['listen']);
if (!isset($arguments['ipcs'])) {
    \ServerBench\Cli\printf_and_exit("argument --ipcs should be set.\n");
}
$ipcs = explode(',', $arguments['ipcs']);
if (count($ipcs) != 2) {
    \ServerBench\Cli\printf_and_exit("argument --ipcs should be a couple of sock files.\n");
}
$api = null;
$app_path = $arguments->get('app');
ProcessUtil::setTitle($arguments->get('title', 'serverbench<proxy>'));
try {
    if (isset($app_path) && file_exists($app_path)) {
        $api = new Api('proxy', include $app_path);
    }
    if ($api && false === $api->init()) {
        \ServerBench\syslog_error('app->init(\'proxy\') returns false.');
        exit;
    }
    PeriodicGc::enable(300);
    $proxy = new Proxy($listen_addr, $ipcs);
    $proxy->run();
    if ($api && false === $api->fini()) {
        \ServerBench\syslog_error('app->fini(\'proxy\') returns false.');
    }
} catch (Exception $e) {
    \ServerBench\syslog_error('uncaught exception from proxy: %s', [$e]);
}
Пример #5
0
 public function run()
 {
     $ipc0 = $this->ipc0_;
     $ipc1 = $this->ipc1_;
     $timer = Timer::getInstance();
     $loop = Loop::getInstance();
     $poller = new ZMQPoll();
     $poller->add($ipc0, ZMQ::POLL_IN);
     while ($loop->running()) {
         // not execute timer too many times
         $timer->execute(64);
         $readable = [];
         $writable = [];
         try {
             if ($timer->isEmpty()) {
                 $events = $poller->poll($readable, $writable, $this->max_wait_ms_);
             } else {
                 $nearest_delta_ms = $timer->nearestDeltaTimeMs();
                 if ($this->max_wait_ms_ > 0 && $this->max_wait_ms_ < $nearest_delta_ms) {
                     $real_wait_ms = $this->max_wait_ms_;
                 } else {
                     if ($nearest_delta_ms < 0) {
                         $nearest_delta_ms = 0;
                     }
                     $real_wait_ms = $nearest_delta_ms;
                 }
                 $events = $poller->poll($readable, $writable, $real_wait_ms);
             }
             if ($events <= 0) {
                 continue;
             }
         } catch (ZMQPollException $e) {
             if (4 == $e->getCode()) {
                 continue;
             }
             throw $e;
         }
         while (true) {
             try {
                 $msg = $ipc0->recvMulti(ZMQ::MODE_NOBLOCK);
                 if (false === $msg) {
                     // would block
                     break;
                 }
                 if (count($msg) !== 3 || !empty($msg[1])) {
                     break;
                 }
                 try {
                     $reply = call_user_func($this->message_callback_, $msg[2]);
                 } catch (\Exception $e) {
                     \ServerBench\syslog_error('caught exception from message_callback: %s', [$e]);
                     continue;
                 }
                 $rc = false;
                 do {
                     try {
                         $rc = $ipc1->sendmulti([$msg[0], '', $reply]);
                     } catch (ZMQPollException $e) {
                         if (4 == $e->getCode()) {
                             continue;
                         }
                         throw $e;
                     }
                     break;
                 } while (true);
                 if (false === $rc) {
                     \ServerBench\syslog_error('replying\'s mq of worker is out of memory, msg(%s) would lose', [$reply]);
                 }
             } catch (ZMQSocketException $e) {
                 if (4 == $e->getCode()) {
                     continue;
                 }
                 throw $e;
             }
         }
     }
 }
Пример #6
0
 public function run($conf)
 {
     $groups = [];
     foreach ($conf['groups'] as $group_conf) {
         $group = [];
         if (isset($group_conf['proxy'])) {
             $proxy_conf = $group_conf['proxy'];
             $proxy_pool = new Pool();
             $proxy_pool->start(1, $proxy_conf['routine']);
             $group['proxy'] = $proxy_pool;
         }
         if (isset($group_conf['worker'])) {
             $worker_conf = $group_conf['worker'];
             $worker_pool = new Pool();
             $worker_pool->start($worker_conf['num'], $worker_conf['routine']);
             $group['worker'] = $worker_pool;
         }
         $groups[] = $group;
     }
     sleep(1);
     $bootstrap_success = true;
     foreach ($groups as $group) {
         foreach ($group as $pool) {
             $pool->waitAll();
             if ($pool->getWorkersDied() > 0) {
                 $bootstrap_success = false;
                 break;
             }
         }
     }
     if ($bootstrap_success) {
         $loop = Loop::getInstance();
         $loop->start();
         $restarting_workers = false;
         Signal::getInstance()->on(SIGUSR1, function () use(&$restarting_workers) {
             $restarting_workers = true;
         });
         while ($loop->running()) {
             if ($restarting_workers) {
                 foreach ($groups as $group) {
                     if (isset($group['worker'])) {
                         $group['worker']->killAll(SIGTERM);
                     }
                 }
                 $restarting_workers = false;
             }
             foreach ($groups as $group) {
                 foreach ($group as $pool) {
                     $pool->keep();
                 }
             }
             usleep(40000);
         }
     } else {
         \ServerBench\syslog_error('failed to bootstrap workers in controller.');
     }
     foreach ($groups as $group) {
         foreach ($group as $pool) {
             $pool->terminate();
         }
     }
 }
Пример #7
0
if (!isset($app_path)) {
    \ServerBench\Cli\printf_and_exit("arugment --app should be set.\n");
}
if (!file_exists($app_path)) {
    \ServerBench\Cli\printf_and_exit("app(%s) does not exist.", $app_path);
}
if (!isset($arguments['ipcs'])) {
    \ServerBench\Cli\printf_and_exit("argument --ipcs should be set.\n");
}
$ipcs = explode(',', $arguments['ipcs']);
if (count($ipcs) != 2) {
    \ServerBench\Cli\printf_and_exit("argument --ipcs should be a couple of sock files.\n");
}
ProcessUtil::setTitle($arguments->get('title', 'serverbench<worker>'));
try {
    $api = new Api('worker', include $app_path);
    if (false === $api->init()) {
        \ServerBench\syslog_error('app->init(\'worker\') returns false.');
        exit;
    }
    PeriodicGc::enable(300);
    $worker = new Worker($ipcs, function ($message) use($api) {
        return $api->process($message);
    });
    $worker->run();
    if (false === $api->fini()) {
        \ServerBench\syslog_error('app->fini(\'worker\') returns false.');
    }
} catch (Exception $e) {
    \ServerBench\syslog_error('uncaught exception from worker: %s', [$e]);
}