利用 JSON-RPC 返回 PHP 对象遇到的问题

在[微服务]中JSON-RPC服务,这章中碰到了无法返回返回[PHP对象]的问题。

首先把场景复现下

1.服务在没有使用[PHP对象]时是正常的。

2.服务提供者的定义

<?php

namespace App\JsonRpc;

use Hyperf\RpcServer\Annotation\RpcService;

/**
* @RpcService(name="CalculatorService", protocol="jsonrpc", server="jsonrpc-http", publishTo="consul")
*/
class CalculatorService implements CalculatorServiceInterface
{
    public function sum($a): MathValue
    {
        //返回一个MathValue对象
        return new MathValue(5);
    }
}

3.服务提供者的注册

//server.php中定义为9504端口
[
    'name' => 'jsonrpc-http',
    'type' => Server::SERVER_HTTP,
    'host' => '0.0.0.0',
    'port' => 9504,
    'sock_type' => SWOOLE_SOCK_TCP,
    'callbacks' => [
        SwooleEvent::ON_REQUEST => [\Hyperf\JsonRpc\HttpServer::class, 'onRequest'],
    ],
]

//consul.php的注册
[
    'uri' => 'consul:8500',
];

4.服务消费者定义

//services.php中的定义
return [
    'consumers' => [
        [            
            'name' => 'CalculatorService',
            'service' => \App\JsonRpc\CalculatorServiceInterface::class,
            'id' => \App\JsonRpc\CalculatorServiceInterface::class,
            'protocol' => 'jsonrpc-http',
            'load_balancer' => 'random',
            'registry' => [
                'protocol' => 'consul',
                'address' => 'consul:8500',
            ],
            'nodes' => [
                ['host' => '127.0.0.1', 'port' => 9504],
            ],
            'options' => [
                'connect_timeout' => 5.0,
                'recv_timeout' => 5.0,
                'settings' => [
                    'open_eof_split' => true,
                    'package_eof' => "\r\n",
                ],
                'pool' => [
                    'min_connections' => 1,
                    'max_connections' => 32,
                    'connect_timeout' => 10.0,
                    'wait_timeout' => 3.0,
                    'heartbeat' => -1,
                    'max_idle_time' => 60.0,
                ],
            ],
        ]
    ],
];

5.进行消费

public function index()
{
    $client = ApplicationContext::getContainer()->get(CalculatorServiceInterface::class);
    $result = $client->sum(1);
    var_dump($result->value);
}

6.生成的临时文件

<?php

namespace App\JsonRpc;

class CalculatorServiceInterface_ee8e44e618dd11853be3872215cf9e94 extends \Hyperf\RpcClient\Proxy\AbstractProxyService implements CalculatorServiceInterface
{
    public function sum($v1) : MathValue
    {
        return $this->client->__call(__FUNCTION__, func_get_args());
    }
}

问题描述

消费者报错

利用JSON-RPC返回PHP对象遇到的问题

打印出 $this->client->__call(__FUNCTION__, func_get_args()) 的值

array(1) {
  ["value"]=>
  int(5)
}

确实是一个数组。请问我该如何进行微服务中的PHP返回呢?

蔺焕然
最佳答案

一个简单的做法,替换 jsonrpc 协议,换成 php serialize 来做数据序列化和反序列化,添加个 Listener 注册覆盖原协议即可

<?php
declare(strict_types=1);

namespace App\Listener;

use Hyperf\Di\Annotation\Inject;
use Hyperf\Event\Annotation\Listener;
use Hyperf\JsonRpc\DataFormatter;
use Hyperf\JsonRpc\JsonRpcHttpTransporter;
use Hyperf\JsonRpc\PathGenerator;
use Hyperf\Rpc\ProtocolManager;
use Hyperf\Utils\Packer\PhpSerializerPacker;

/**
 * @Listener(priority=0)
 */
class RegisterProtocolListener extends \Hyperf\JsonRpc\Listener\RegisterProtocolListener
{
    /**
     * @Inject
     * @var ProtocolManager
     */
    private $protocolManager;

    public function process(object $event)
    {
        $this->protocolManager->register('jsonrpc-http', [
            'packer' => PhpSerializerPacker::class,
            'transporter' => JsonRpcHttpTransporter::class,
            'path-generator' => PathGenerator::class,
            'data-formatter' => DataFormatter::class,
        ]);
    }
}
4年前 评论
蔺焕然 (楼主) 4年前
讨论数量: 2

一个简单的做法,替换 jsonrpc 协议,换成 php serialize 来做数据序列化和反序列化,添加个 Listener 注册覆盖原协议即可

<?php
declare(strict_types=1);

namespace App\Listener;

use Hyperf\Di\Annotation\Inject;
use Hyperf\Event\Annotation\Listener;
use Hyperf\JsonRpc\DataFormatter;
use Hyperf\JsonRpc\JsonRpcHttpTransporter;
use Hyperf\JsonRpc\PathGenerator;
use Hyperf\Rpc\ProtocolManager;
use Hyperf\Utils\Packer\PhpSerializerPacker;

/**
 * @Listener(priority=0)
 */
class RegisterProtocolListener extends \Hyperf\JsonRpc\Listener\RegisterProtocolListener
{
    /**
     * @Inject
     * @var ProtocolManager
     */
    private $protocolManager;

    public function process(object $event)
    {
        $this->protocolManager->register('jsonrpc-http', [
            'packer' => PhpSerializerPacker::class,
            'transporter' => JsonRpcHttpTransporter::class,
            'path-generator' => PathGenerator::class,
            'data-formatter' => DataFormatter::class,
        ]);
    }
}
4年前 评论
蔺焕然 (楼主) 4年前

:joy:我的跑不通

4年前 评论

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