实现接入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());
    }
}

效果如下:

实现接入tp6 think-swoole rpc服务
完美。
老项目也可以愉快的接进来了

本作品采用《CC 协议》,转载必须注明作者和本文链接
To live is to change the world
本帖由系统于 7个月前 自动加精
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!