服务定义
每一个Rpc服务都应继承自 EasySwoole\Rpc\AbstractService 类。该类的具体代码如下:
namespace EasySwoole\Rpc;
use EasySwoole\Component\TableManager;
use Swoole\Coroutine;
abstract class AbstractService
{
private $allowMethods = [];
private $requests = [];
private $responses = [];
private $sockets = [];
private $actions = [];
/*
* 禁止重写该方法,防止在构造函数中抛出异常
*/
final public function __construct()
{
//支持在子类控制器中以private,protected来修饰某个方法不可见
$list = [];
$ref = new \ReflectionClass(static::class);
$public = $ref->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach ($public as $item) {
array_push($list, $item->getName());
}
$this->allowMethods = array_diff($list,
[
'__hook', '__destruct',
'__clone', '__construct', '__call',
'__callStatic', '__get', '__set',
'__isset', '__unset', '__sleep',
'__wakeup', '__toString', '__invoke',
'__set_state', '__clone', '__debugInfo',
'serviceName','version','onTick','actionList'
]
);
}
protected function onRequest(?string $action):?bool
{
return true;
}
protected function afterAction(?string $action)
{
}
abstract public function serviceName():string ;
/*
* 每秒会执行一次,请自己实现间隔需求
*/
public function onTick(Config $config)
{
}
protected function onException(\Throwable $throwable)
{
throw $throwable;
}
protected function request():Request
{
return $this->requests[Coroutine::getCid()];
}
protected function response():Response
{
return $this->responses[Coroutine::getCid()];
}
protected function socket():Coroutine\Socket
{
return $this->sockets[Coroutine::getCid()];
}
protected function action(): ?string
{
return $this->actions[Coroutine::getCid()];
}
protected function actionNotFound(?string $action)
{
$this->response()->setStatus(Response::STATUS_SERVICE_ACTION_NOT_FOUND);
}
public function version():string
{
return '1.0';
}
public function actionList():array
{
return $this->allowMethods;
}
public function __hook(Request $request, Response $response, Coroutine\Socket $client)
{
$this->requests[Coroutine::getCid()] = $request;
$this->responses[Coroutine::getCid()] = $response;
$this->sockets[Coroutine::getCid()] = $client;
$this->actions[Coroutine::getCid()] = $request->getAction();
$actionName = $this->action();
try {
if ($this->onRequest($this->action()) !== false) {
if (in_array($actionName, $this->allowMethods)) {
$actionName = $this->action();
$this->$actionName();
} else {
$this->actionNotFound($this->action());
}
}
} catch (\Throwable $throwable) {
//若没有重构onException,直接抛出给上层
$this->onException($throwable);
} finally {
try {
$this->afterAction($this->action());
} catch (\Throwable $throwable) {
$this->onException($throwable);
}
unset( $this->requests[Coroutine::getCid()]);
unset( $this->responses[Coroutine::getCid()]);
unset( $this->actions[Coroutine::getCid()]);
unset( $this->sockets[Coroutine::getCid()]);
}
if($response->getStatus() === Response::STATUS_OK){
TableManager::getInstance()->get($this->serviceName())->incr($actionName,'success');
}else{
TableManager::getInstance()->get($this->serviceName())->incr($actionName,'fail');
}
}
}
注意,全部请求都会复用该实例。因此成员属性的修改访问是不安全的。请用上下文管理器实现变量存储。