这里以Swoft启动http server为例。
php bin/swoft http:start
执行上述命令,启动http server。
在前面第一篇文章的时候,提到了如何启动http服务。
今天我们就来看一下http服务是如何启动的,具体实现就在ConsoleProcess
这个模块。
/**
* Handle console
* @return bool
* @throws ReflectionException
* @throws ContainerException
*/
public function handle(): bool
{
if (!$this->application->beforeConsole()) {
return false;
}
/** @var Router $router */
$router = bean('cliRouter');
// Register console routes
CommandRegister::register($router);
CLog::info(
'Console command route registered (group %d, command %d)',
$router->groupCount(),
$router->count()
);
// Run console application
bean('cliApp')->run();
return $this->application->afterConsole();
}
这里调用了bean
方法获取Bean
实例,定义见swoft-component-2.0.5\src\bean\src\Helper\Functions.php
。
if (!function_exists('bean')) {
/**
* Get bean by name
*
* @param string $name Bean name Or alias Or class name
*
* @return object|string|mixed
*/
function bean(string $name)
{
if (BeanFactory::isSingleton('config')) {
return BeanFactory::getBean($name);
}
return sprintf('${%s}', $name);
}
}
这里调用了BeanFactory
的getBean
方法。
/**
* Get object by name
*
* @param string $name Bean name Or alias Or class name
*
* @return object|mixed
*/
public static function getBean(string $name)
{
return Container::getInstance()->get($name);
}
最终调用的是Swoft\Bean\Container
下的get
方法。
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Bean name Or alias Or class name
*
* When class name will return all of instance for class name
*
* @return object
* @throws InvalidArgumentException
*/
public function get($id)
{
// It is singleton
if (isset($this->singletonPool[$id])) {
return $this->singletonPool[$id];
}
// Prototype by clone
if (isset($this->prototypePool[$id])) {
return clone $this->prototypePool[$id];
}
// Alias name
$aliasId = $this->aliases[$id] ?? '';
if ($aliasId) {
return $this->get($aliasId);
}
// Class name
$classNames = $this->classNames[$id] ?? [];
if ($classNames) {
$id = end($classNames);
return $this->get($id);
}
// Interface
if (interface_exists($id)) {
$id = InterfaceRegister::getInterfaceInjectBean($id);
return $this->get($id);
}
// Not defined
if (!isset($this->objectDefinitions[$id])) {
throw new InvalidArgumentException(sprintf('The bean of %s is not defined', $id));
}
/* @var ObjectDefinition $objectDefinition */
$objectDefinition = $this->objectDefinitions[$id];
// Prototype
return $this->safeNewBean($objectDefinition->getName());
}
获取对应的ObjectDefinition
实例,然后调用safeNewBean
方法。
/**
* Secure creation of beans
*
* @param string $beanName
* @param string $id
*
* @return object|mixed
*/
private function safeNewBean(string $beanName, string $id = '')
{
try {
return $this->newBean($beanName, $id);
} catch (Throwable $e) {
throw new InvalidArgumentException($e->getMessage(), 500, $e);
}
}
这里又调用了newBean
方法,在上一篇文章里我们已经讲过这个方法,这里会返回实例化后的Bean
类。
那cliRouter
对应的类是说明呢?这个定义在swoft-component-2.0.5\src\console\src\AutoLoader.php
里。
/**
* {@inheritDoc}
*/
public function beans(): array
{
return [
'cliApp' => [
'class' => Application::class,
'version' => '2.0.0'
],
'cliRouter' => [
'class' => Router::class,
],
'cliDispatcher' => [
'class' => ConsoleDispatcher::class,
],
];
}
所以$router = bean('cliRouter')
,返回的是一个Swoft\Console\Router\Router
类。
回到ConsoleProcessor
类,接着看代码。
CommandRegister::register($router);
调用了CommandRegister
类的register
方法。
/**
* @param Router $router
* @throws ReflectionException
*/
public static function register(Router $router): void
{
$maxLen = 12;
$groups = [];
$docOpts = [
'allow' => ['example']
];
$defInfo = [
'example' => '',
'description' => 'No description message',
];
foreach (self::$commands as $class => $mapping) {
$names = [];
$group = $mapping['group'];
// Set ID aliases
$router->setIdAliases($mapping['idAliases']);
// Set group name aliases
$router->setGroupAliases($group, $mapping['aliases']);
$refInfo = Swoft::getReflection($class);
$mhdInfo = $refInfo['methods'] ?? [];
$grpOpts = $mapping['options'] ?? [];
foreach ($mapping['commands'] as $method => $route) {
// $method = $route['method'];
$cmdDesc = $route['desc'];
$command = $route['command'];
$idLen = strlen($group . $command);
if ($idLen > $maxLen) {
$maxLen = $idLen;
}
$cmdExam = '';
if (!empty($mhdInfo[$method]['comments'])) {
$tagInfo = DocBlock::getTags($mhdInfo[$method]['comments'], $docOpts, $defInfo);
$cmdDesc = $cmdDesc ?: Str::firstLine($tagInfo['description']);
$cmdExam = $tagInfo['example'];
}
$route['group'] = $group;
$route['desc'] = ucfirst($cmdDesc);
$route['example'] = $cmdExam;
$route['options'] = self::mergeOptions($grpOpts, $route['options']);
// Append group option
$route['enabled'] = $mapping['enabled'];
$route['coroutine'] = $mapping['coroutine'];
$router->map($group, $command, [$class, $method], $route);
$names[] = $command;
}
$groupExam = '';
$groupDesc = $mapping['desc'];
if (!empty($refInfo['comments'])) {
$tagInfo = DocBlock::getTags($refInfo['comments'], $docOpts, $defInfo);
$groupDesc = $groupDesc ?: Str::firstLine($tagInfo['description']);
$groupExam = $tagInfo['example'];
}
$groups[$group] = [
'names' => $names,
'desc' => ucfirst($groupDesc),
'class' => $class,
'alias' => $mapping['alias'],
'aliases' => $mapping['aliases'],
'example' => $groupExam,
];
}
$router->setGroups($groups);
// +1 because router->delimiter
$router->setKeyWidth($maxLen + 1);
// clear data
self::$commands = [];
}
这里遍历了类属性$commands
注册路由。
那么$commands
这个属性是哪里来的呢?
既然开头我们说的是http服务是怎么启动的,这里我们就以http-server
来举例,找到swoft-component-2.0.5\src\http-server\src\Command\HttpServerCommand.php
文件。
<?php declare(strict_types=1);
namespace Swoft\Http\Server\Command;
use ReflectionException;
use Swoft;
use Swoft\Bean\Exception\ContainerException;
use Swoft\Console\Annotation\Mapping\Command;
use Swoft\Console\Annotation\Mapping\CommandMapping;
use Swoft\Console\Annotation\Mapping\CommandOption;
use Swoft\Console\Helper\Show;
use Swoft\Http\Server\HttpServer;
use Swoft\Server\Command\BaseServerCommand;
use Swoft\Server\Exception\ServerException;
use function bean;
use function input;
use function output;
/**
* Provide some commands to manage the swoft HTTP server
*
* @since 2.0
*
* @Command("http", alias="httpsrv", coroutine=false)
* @example
* {fullCmd}:start Start the http server
* {fullCmd}:stop Stop the http server
*/
class HttpServerCommand extends BaseServerCommand
{
/**
* Start the http server
*
* @CommandMapping(usage="{fullCommand} [-d|--daemon]")
* @CommandOption("daemon", short="d", desc="Run server on the background", type="bool", default="false")
*
* @throws ReflectionException
* @throws ContainerException
* @throws ServerException
* @example
* {fullCommand}
* {fullCommand} -d
*
*/
public function start(): void
{
$server = $this->createServer();
// Check if it has started
if ($server->isRunning()) {
$masterPid = $server->getPid();
output()->writeln("<error>The HTTP server have been running!(PID: {$masterPid})</error>");
return;
}
// Startup settings
$this->configStartOption($server);
$settings = $server->getSetting();
// Setting
$workerNum = $settings['worker_num'];
// Server startup parameters
$mainHost = $server->getHost();
$mainPort = $server->getPort();
$modeName = $server->getModeName();
$typeName = $server->getTypeName();
// Http
$panel = [
'HTTP' => [
'listen' => $mainHost . ':' . $mainPort,
'type' => $typeName,
'mode' => $modeName,
'worker' => $workerNum,
],
];
// Port Listeners
$panel = $this->appendPortsToPanel($server, $panel);
Show::panel($panel);
output()->writeln('<success>HTTP server start success !</success>');
// Start the server
$server->start();
}
/**
* Reload worker processes
*
* @CommandMapping(usage="{fullCommand} [-t]")
* @CommandOption("t", desc="Only to reload task processes, default to reload worker and task")
*
* @throws ReflectionException
* @throws ContainerException
*/
public function reload(): void
{
$server = $this->createServer();
$script = input()->getScript();
// Check if it has started
if (!$server->isRunning()) {
output()->writeln('<error>The HTTP server is not running! cannot reload</error>');
return;
}
output()->writef('<info>Server %s is reloading</info>', $script);
if ($reloadTask = input()->hasOpt('t')) {
Show::notice('Will only reload task worker');
}
if (!$server->reload($reloadTask)) {
Show::error('The swoole server worker process reload fail!');
return;
}
output()->writef('<success>HTTP server %s reload success</success>', $script);
}
/**
* Stop the currently running server
*
* @CommandMapping()
*
* @throws ReflectionException
* @throws ContainerException
*/
public function stop(): void
{
$server = $this->createServer();
// Check if it has started
if (!$server->isRunning()) {
output()->writeln('<error>The HTTP server is not running! cannot stop.</error>');
return;
}
// Do stopping.
$server->stop();
}
/**
* Restart the http server
*
* @CommandMapping(usage="{fullCommand} [-d|--daemon]",)
* @CommandOption("daemon", short="d", desc="Run server on the background")
*
* @throws ReflectionException
* @throws ContainerException
* @example
* {fullCommand}
* {fullCommand} -d
*/
public function restart(): void
{
$server = $this->createServer();
// Check if it has started
if ($server->isRunning()) {
$success = $server->stop();
if (!$success) {
output()->error('Stop the old server failed!');
return;
}
}
output()->writef('<success>Server HTTP restart success !</success>');
$server->startWithDaemonize();
}
/**
* @return HttpServer
* @throws ReflectionException
* @throws ContainerException
*/
private function createServer(): HttpServer
{
$script = input()->getScript();
$command = $this->getFullCommand();
/** @var HttpServer $server */
$server = bean('httpServer');
$server->setScriptFile(Swoft::app()->getPath($script));
$server->setFullCommand($command);
return $server;
}
}
通过Swoft文档,我们可以看到这里分别使用了类注解和方法注解。
@Command("http", alias="httpsrv", coroutine=false)
@CommandMapping(usage="{fullCommand} [-d|--daemon]")
@CommandOption("daemon", short="d", desc="Run server on the background", type="bool", default="false")
...
通过第二篇文章分析,我们知道这里会自动实例化对应的注解类。
这里以Swoft\Console\Annotation\Mapping\CommandMapping
这个注解为例,对应的注解解析类为Swoft\Console\Annotation\Parser\CommandMappingParser
。
<?php declare(strict_types=1);
namespace Swoft\Console\Annotation\Parser;
use Swoft\Annotation\Annotation\Mapping\AnnotationParser;
use Swoft\Annotation\Annotation\Parser\Parser;
use Swoft\Annotation\Exception\AnnotationException;
use Swoft\Console\Annotation\Mapping\CommandMapping;
use Swoft\Console\CommandRegister;
/**
* Class CommandMappingParser
*
* @since 2.0
* @AnnotationParser(CommandMapping::class)
*/
class CommandMappingParser extends Parser
{
/**
* Parse object
*
* @param int $type Class or Method or Property
* @param CommandMapping $annotation Annotation object
*
* @return array
* Return empty array is nothing to do!
* When class type return [$beanName, $className, $scope, $alias, $size] is to inject bean
* When property type return [$propertyValue, $isRef] is to reference value
*/
public function parse(int $type, $annotation): array
{
if ($type !== self::TYPE_METHOD) {
throw new AnnotationException('`@CommandMapping` must be defined on class method!');
}
$method = $this->methodName;
// add route info for controller action
CommandRegister::addRoute($this->className, $method, [
'command' => $annotation->getName() ?: $method,
'method' => $method,
'alias' => $annotation->getAlias(),
'aliases' => $annotation->getAliases(),
'desc' => $annotation->getDesc(),
'usage' => $annotation->getUsage(),
// 'example' => $annotation->getExample(),
]);
return [];
}
}
看到这里,你应该可以猜到CommandRegister
类的$commands
是怎么来的了吧。
我们看下CommandRegister
类的addRoute
方法,验证下想法。
/**
* @param string $class
* @param string $method
* @param array $route
*
* @throws AnnotationException
*/
public static function addRoute(string $class, string $method, array $route): void
{
self::checkClass($class);
// init some keys
$route['options'] = [];
$route['arguments'] = [];
// save
self::$commands[$class]['commands'][$method] = $route;
}
bingo,跟我们猜想的一模一样,这下我们也知道CommandMapping
这个注解是用来注册终端的路由信息。
回到ConsoleProcessor
类,接着看代码。
CLog::info(
'Console command route registered (group %d, command %d)',
$router->groupCount(),
$router->count()
);
打印日志。
// Run console application
bean('cliApp')->run();
感觉到了重头戏。
根据前面的代码,我们知道cliApp
这个Bean
实例对应的类是Swoft\Console\Application
。
/**
* @return void
* @throws ContainerException
*/
public function run(): void
{
try {
Swoft::trigger(ConsoleEvent::RUN_BEFORE, $this);
// Prepare
$this->prepare();
// Get input command
$inputCommand = $this->input->getCommand();
if (!$inputCommand) {
$this->filterSpecialOption();
} else {
$this->doRun($inputCommand);
}
Swoft::trigger(ConsoleEvent::RUN_AFTER, $this, $inputCommand);
} catch (Throwable $e) {
/** @var ConsoleErrorDispatcher $errDispatcher */
$errDispatcher = BeanFactory::getSingleton(ConsoleErrorDispatcher::class);
// Handle request error
$errDispatcher->run($e);
}
}
通过Swoft::trigger
,注册了ConsoleEvent::RUN_BEFORE
和ConsoleEvent::RUN_AFTER
两个事件。
protected function prepare(): void
{
$this->input = \input();
$this->output = \output();
// load builtin comments vars
$this->setCommentsVars($this->commentsVars());
}
prepare
比较简单,这里声明了输入和输出两个类。注意哈,这个后面会用到。
$inputCommand = $this->input->getCommand();
if (!$inputCommand) {
$this->filterSpecialOption();
} else {
$this->doRun($inputCommand);
}
获取终端命令行下的输入,如果有输入执行doRun
方法。
/**
* @param string $inputCmd
*
* @return void
* @throws ReflectionException
* @throws ContainerException
* @throws Throwable
*/
protected function doRun(string $inputCmd): void
{
$output = $this->output;
/* @var Router $router */
$router = Swoft::getBean('cliRouter');
$result = $router->match($inputCmd);
// Command not found
if ($result[0] === Router::NOT_FOUND) {
$names = $router->getAllNames();
$output->liteError("The entered command '{$inputCmd}' is not exists!");
// find similar command names by similar_text()
if ($similar = Arr::findSimilar($inputCmd, $names)) {
$output->writef("\nMaybe what you mean is:\n <info>%s</info>", implode(', ', $similar));
} else {
$this->showApplicationHelp(false);
}
return;
}
$info = $result[1];
// Only input a group name, display help for the group
if ($result[0] === Router::ONLY_GROUP) {
$this->showGroupHelp($info['group']);
return;
}
// Display help for a command
if ($this->input->getSameOpt(['h', 'help'])) {
$this->showCommandHelp($info);
return;
}
// Parse default options and arguments
$this->bindCommandFlags($info);
$this->input->setCommandId($info['cmdId']);
Swoft::triggerByArray(ConsoleEvent::DISPATCH_BEFORE, $this, $info);
// Call command handler
/** @var ConsoleDispatcher $dispatcher */
$dispatcher = Swoft::getSingleton('cliDispatcher');
$dispatcher->dispatch($info);
Swoft::triggerByArray(ConsoleEvent::DISPATCH_AFTER, $this, $info);
}
$router = Swoft::getBean('cliRouter');
$result = $router->match($inputCmd);
获取cliRouter
实例,根据输入匹配路由操作类。
/**
* Match route by input command
*
* @param array $params [$route]
*
* @return array
*
* [
* status, info(array)
* ]
*/
public function match(...$params): array
{
$delimiter = $this->delimiter;
$inputCmd = trim($params[0], "$delimiter ");
$noSepChar = strpos($inputCmd, $delimiter) === false;
// If use command ID alias
if ($noSepChar && isset($this->idAliases[$inputCmd])) {
$inputCmd = $this->idAliases[$inputCmd];
// Must re-check
$noSepChar = strpos($inputCmd, $delimiter) === false;
}
if ($noSepChar && in_array($inputCmd, $this->defaultCommands, true)) {
$group = $this->defaultGroup;
$command = $this->resolveCommandAlias($inputCmd);
// Only a group name
} elseif ($noSepChar) {
$group = $this->resolveGroupAlias($inputCmd);
if (isset($this->groups[$group])) {
return [self::ONLY_GROUP, ['group' => $group]];
}
return [self::NOT_FOUND];
} else {
$nameList = explode($delimiter, $inputCmd, 2);
if (count($nameList) === 2) {
[$group, $command] = $nameList;
// resolve command alias
$command = $this->resolveCommandAlias($command);
} else {
$command = '';
// $command = $this->defaultCommand;
$group = $nameList[0];
}
}
$group = $this->resolveGroupAlias($group);
// build command ID
$commandID = $this->buildCommandID($group, $command);
if (isset($this->routes[$commandID])) {
$info = $this->routes[$commandID];
// append some info
$info['cmdId'] = $commandID;
return [self::FOUND, $info];
}
if ($group && isset($this->groups[$group])) {
return [self::ONLY_GROUP, ['group' => $group]];
}
return [self::NOT_FOUND];
}
这里会返回匹配后的路由信息。
回到doRun
方法。
// Command not found
if ($result[0] === Router::NOT_FOUND) {
$names = $router->getAllNames();
$output->liteError("The entered command '{$inputCmd}' is not exists!");
// find similar command names by similar_text()
if ($similar = Arr::findSimilar($inputCmd, $names)) {
$output->writef("\nMaybe what you mean is:\n <info>%s</info>", implode(', ', $similar));
} else {
$this->showApplicationHelp(false);
}
return;
}
$info = $result[1];
// Only input a group name, display help for the group
if ($result[0] === Router::ONLY_GROUP) {
$this->showGroupHelp($info['group']);
return;
}
// Display help for a command
if ($this->input->getSameOpt(['h', 'help'])) {
$this->showCommandHelp($info);
return;
}
根据返回的路由信息进行不同的处理。
// Parse default options and arguments
$this->bindCommandFlags($info);
$this->input->setCommandId($info['cmdId']);
Swoft::triggerByArray(ConsoleEvent::DISPATCH_BEFORE, $this, $info);
绑定默认参数,注册ConsoleEvent::DISPATCH_BEFORE
事件。
// Call command handler
/** @var ConsoleDispatcher $dispatcher */
$dispatcher = Swoft::getSingleton('cliDispatcher');
$dispatcher->dispatch($info);
获取cliDispatcher
的Bean
实例,对应Swoft\Console\ConsoleDispatcher
类,调用dispatch
方法。
/**
* @param array $params
*
* @return void
* @throws ReflectionException
* @throws Throwable
*/
public function dispatch(...$params): void
{
$route = $params[0];
// Handler info
[$className, $method] = $route['handler'];
// Bind method params
$params = $this->getBindParams($className, $method);
$object = Swoft::getSingleton($className);
// Blocking running
if (!$route['coroutine']) {
$this->before(get_parent_class($object), $method);
PhpHelper::call([$object, $method], ...$params);
$this->after($method);
return;
}
// Hook php io function
Runtime::enableCoroutine();
// If in unit test env, has been in coroutine.
if (\defined('PHPUNIT_COMPOSER_INSTALL')) {
$this->executeByCo($object, $method, $params);
return;
}
// Coroutine running
srun(function () use ($object, $method, $params) {
$this->executeByCo($object, $method, $params);
});
}
获取路由对应的类和方法,通过Swoft::getSingleton($className);
实例化对象。
如果未开启协程,则用PhpHelper::call([$object, $method], ...$params);
调用对应的方法。
开启协程的话,使用$this->executeByCo($object, $method, $params);
调用对应的方法。
我们前面启动命令是php bin/swoft http:start
,这里对应的类就是Swoft\Http\Server\Command\HttpServerCommand
,方法就是start
。
/**
* Start the http server
*
* @CommandMapping(usage="{fullCommand} [-d|--daemon]")
* @CommandOption("daemon", short="d", desc="Run server on the background", type="bool", default="false")
*
* @throws ReflectionException
* @throws ContainerException
* @throws ServerException
* @example
* {fullCommand}
* {fullCommand} -d
*
*/
public function start(): void
{
$server = $this->createServer();
// Check if it has started
if ($server->isRunning()) {
$masterPid = $server->getPid();
output()->writeln("<error>The HTTP server have been running!(PID: {$masterPid})</error>");
return;
}
// Startup settings
$this->configStartOption($server);
$settings = $server->getSetting();
// Setting
$workerNum = $settings['worker_num'];
// Server startup parameters
$mainHost = $server->getHost();
$mainPort = $server->getPort();
$modeName = $server->getModeName();
$typeName = $server->getTypeName();
// Http
$panel = [
'HTTP' => [
'listen' => $mainHost . ':' . $mainPort,
'type' => $typeName,
'mode' => $modeName,
'worker' => $workerNum,
],
];
// Port Listeners
$panel = $this->appendPortsToPanel($server, $panel);
Show::panel($panel);
output()->writeln('<success>HTTP server start success !</success>');
// Start the server
$server->start();
}
这里先调用了createServer
方法。
/**
* @return HttpServer
* @throws ReflectionException
* @throws ContainerException
*/
private function createServer(): HttpServer
{
$script = input()->getScript();
$command = $this->getFullCommand();
/** @var HttpServer $server */
$server = bean('httpServer');
$server->setScriptFile(Swoft::app()->getPath($script));
$server->setFullCommand($command);
return $server;
}
获取httpServer
的Bean
实例。
框架定义在swoft-component-2.0.5\src\http-server\src\AutoLoader.php
,这里声明了onRequest
回调事件。
'httpServer' => [
'on' => [
SwooleEvent::REQUEST => bean(RequestListener::class)
]
],
业务定义在swoft-2.0.5\app\bean.php
。
'httpServer' => [
'class' => HttpServer::class,
'port' => 18306,
'listener' => [
'rpc' => bean('rpcServer')
],
'process' => [
// 'monitor' => bean(MonitorProcess::class)
// 'crontab' => bean(CrontabProcess::class)
],
'on' => [
// SwooleEvent::TASK => bean(SyncTaskListener::class), // Enable sync task
SwooleEvent::TASK => bean(TaskListener::class), // Enable task must task and finish event
SwooleEvent::FINISH => bean(FinishListener::class)
],
/* @see HttpServer::$setting */
'setting' => [
'task_worker_num' => 12,
'task_enable_coroutine' => true
]
],
createServer
返回的是一个Swoft\Http\Server\HttpServer
实例。
回到HttpServerCommand
类的start
方法。
// Start the server
$server->start();
调用Swoft\Http\Server\HttpServer
类的start
方法。
/**
* Start server
*
* @throws ServerException
* @throws ContainerException
*/
public function start(): void
{
$this->swooleServer = new \Swoole\Http\Server($this->host, $this->port, $this->mode, $this->type);
$this->startSwoole();
}
声明Swoole\Http\Server
对象,调用startSwoole
方法。
Swoft\Http\Server\HttpServer
类继承自Swoft\Server\Server
类,startSwoole
方法定义在这个类。
/**
* Bind swoole event and start swoole server
*
* @throws ServerException
* @throws Swoft\Bean\Exception\ContainerException
*/
protected function startSwoole(): void
{
if (!$this->swooleServer) {
throw new ServerException('You must to new server before start swoole!');
}
// Always enable coroutine hook on server
CLog::info('Swoole\Runtime::enableCoroutine');
Runtime::enableCoroutine();
Swoft::trigger(ServerEvent::BEFORE_SETTING, $this);
// Set settings
$this->swooleServer->set($this->setting);
// Update setting property
// $this->setSetting($this->swooleServer->setting);
// Before Add event
Swoft::trigger(ServerEvent::BEFORE_ADDED_EVENT, $this);
// Register events
$defaultEvents = $this->defaultEvents();
$swooleEvents = array_merge($defaultEvents, $this->on);
// Add events
$this->addEvent($this->swooleServer, $swooleEvents, $defaultEvents);
//After add event
Swoft::trigger(ServerEvent::AFTER_ADDED_EVENT, $this);
// Before listener
Swoft::trigger(ServerEvent::BEFORE_ADDED_LISTENER, $this);
// Add port listener
$this->addListener();
// Before bind process
Swoft::trigger(ServerEvent::BEFORE_ADDED_PROCESS, $this);
// Add Process
Swoft::trigger(ServerEvent::ADDED_PROCESS, $this);
// After bind process
Swoft::trigger(ServerEvent::AFTER_ADDED_PROCESS, $this);
// Trigger event
Swoft::trigger(ServerEvent::BEFORE_START, $this, array_keys($swooleEvents));
// Storage server instance
self::$server = $this;
// Start swoole server
$this->swooleServer->start();
}
$this->swooleServer->set($this->setting);
设置Swoole
运行配置。
// Register events
$defaultEvents = $this->defaultEvents();
$swooleEvents = array_merge($defaultEvents, $this->on);
// Add events
$this->addEvent($this->swooleServer, $swooleEvents, $defaultEvents);
添加Swoole
回调事件。
// Add port listener
$this->addListener();
监听端口。
// Start swoole server
$this->swooleServer->start();
启动Swoole\Http\Server
服务。
现在服务已经启动了,那http请求
是怎么被处理的呢?
这个我们下一篇再继续讲。