实现接入tp6 think-swoole rpc服务
公司多个项目之前用的TP3.2,去年部份项目升级为TP6,并使用了JSONRPC服务,使用了TP6官方插件 think-swoole中rpc服务,实现了rpc客户端和服务端,但从便携性上讲,需要项目都是TP6才能快速接入rpc服务。
之前部份老项目由于升级成本过大,迟迟没有升级到TP6。由于某些模块需要在新老项目中都需要用到,所以会容易造成新老项目中相同模块中的代码逻辑不一致的问题。
为了解决这个问题,去看了下think-swoole中关于rpc服务的代码,按照里面的逻辑,仿照写了一个调用rpc服务的客户端类。
代码如下:
<?php
$orderRpc = new CoreRpc('order');
$data = [
'serviceType' => 0,
];
$res = $orderRpc->estimate($data);
var_dump($res);
class CoreRpc
{
protected $host = '127.0.0.1'; //rpc服务IP
protected $port = 10001; //rpc服务端口
protected $timeout = 5;
protected $client;
protected $interface;
protected $rpcFunc = [
'OrderRpcInterface' => ['estimate', 'order'],
'UserRpcInterface' => ['create'],
];
protected $interfaces = [
'order' => 'OrderRpcInterface',
'user' => 'UserRpcInterface',
];
public function __construct($interface)
{
$this->interface = $interface;
}
protected function isConnected(): bool
{
return $this->client && $this->client->isConnected();
}
protected function getClient()
{
if (!$this->isConnected()) {
$client = new Swoole\Client(SWOOLE_SOCK_TCP);
if (!$client->connect($this->host, $this->port, $this->timeout)) {
throw new Exception(sprintf('Connect failed host=%s port=%d', $this->host, $this->port));
}
$this->client = $client;
}
return $this->client;
}
public function packData($interface, $func, $arguments)
{
$method = $interface . '@' . $func;
$data = [
'jsonrpc' => '2.0',
'method' => $method,
'params' => $arguments,
'context' => [],
'id' => '',
];
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
return pack('NN', strlen($json), 0) . $json;
}
public function __call($method, array $arguments)
{
$interface = $this->interface;
if(!isset($this->interfaces[$interface])){
throw new Exception('非法的interface');
}
$rpcFunc = $this->rpcFunc[$this->interfaces[$interface]];
if(!in_array($method, $rpcFunc)){
throw new Exception('非法的method');
}
$pack = $this->packData($this->interfaces[$interface], $method, $arguments);
return $this->sendAndRecv($pack);
}
protected function sendAndRecv($data)
{
return $this->runWithClient(function (Swoole\Client $client) use ($data) {
try {
if ($client->send($data) === false) {
throw new Exception('Send data failed.');
}
$response = $client->recv();
// 处理响应数据
if ($response === false) {
throw new Exception('Recv data failed.');
}
$res = substr($response,8);
$data = json_decode($res, true);
return $data['result'];
} catch (Exception $e) {
$client->close();
throw $e;
}
});
}
protected function runWithClient($callback)
{
return $callback($this->getClient());
}
}
效果如下:
完美。
老项目也可以愉快的接进来了
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 1年前 自动加精