实现接入tp6 think-swoole rpc服务
发表于|更新于
公司多个项目之前用的TP3.2,去年部份项目升级为TP6,并使用了JSONRPC服务,使用了TP6官方插件 think-swoole中rpc服务,实现了rpc客户端和服务端,但从便携性上讲,需要项目都是TP6才能快速接入rpc服务。
之前部份老项目由于升级成本过大,迟迟没有升级到TP6。由于某些模块需要在新老项目中都需要用到,所以会容易造成新老项目中相同模块中的代码逻辑不一致的问题。
为了解决这个问题,去看了下think-swoole中关于rpc服务的代码,按照里面的逻辑,仿照写了一个调用rpc服务的客户端类。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| <?php $orderRpc = new CoreRpc('order'); $data = [ 'serviceType' => 0, ]; $res = $orderRpc->estimate($data); var_dump($res);
class CoreRpc { protected $host = '127.0.0.1';
protected $port = 10001;
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()); } }
|
效果如下:

完美。
老项目也可以愉快的接进来了