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_); }
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. } } } } }
} $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]); }
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]); }
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; } } } }
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(); } } }
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]); }