一个超级简单的RPC

caylof

关于

服务端的实现基于 workman。
使用 stream_socket_* 实现了一个简单的同步 client ,目前只支持 workman 的 frame 协议。
使用示例:https://github.com/caylof/php-rpc

服务定义说明

服务方法的定义需要遵循如下方式函数签名:

function (array | Google\Protobuf\Internal\Message $request): array | Google\Protobuf\Internal\Message

在 webman 中的集成方案

  • 安装 composer 包
composer require caylof/rpc
  • 新建文件 process/RpcServer.php
<?php

namespace process;

use Caylof\Rpc\Driver\WorkmanServer;
use Caylof\Rpc\ServiceCaller;
use Caylof\Rpc\ServiceRepository;
use support\Container;

class RpcServer extends WorkmanServer
{
    public function __construct()
    {
        $container = Container::instance();
        $serviceCaller = new ServiceCaller();
        $serviceCaller->setCallerRegistry(new ServiceRepository($container));
        $this->setServiceCaller($serviceCaller);
    }
}
  • 在配置文件 config/process.php 添加进程
'rpc' => [
    'handler' => process\RpcServer::class,
    'listen' => 'frame://0.0.0.0:2345',
    'count' => 1,
],
  • 定义一个服务

    新建文件 app/rpc/TestSrv

    <?php
    
    namespace app\rpc;
    
    class TestSrv
    {
        public function hello(array $request): array
        {
            $name = $request['name'] ?? 'ctv';
            return ['msg' => 'hello ' . $name];
        }
    }
    
  • 重启 webman 完成服务端 server

proto   user            worker          listen                  processes    status
tcp     root            webman          http://0.0.0.0:8787     1             [OK]
tcp     root            monitor         none                    1             [OK]
tcp     root            rpc             frame://0.0.0.0:2345    1             [OK]
  • client 端调用

    这里为简便,可以直接在 controller 中 测试,在 IndexController 中 添加一个 action

    public function rpc()
    {
      $client = new \Caylof\Rpc\Driver\WorkmanFrameClient('tcp', '127.0.0.1', 2345);
      $result = $client->call('app\\rpc\\TestSrv@hello', ['name' => 'asdf']);
      return json($result);
    }

    然后访问 http://127.0.0.1:8787/index/rpc,不出意外应该会调用成功。

  • client 进一步封装

    新建文件 app/rpc/client/ServiceClient.php,作为一个客户端的基类:

    <?php
    
    namespace app\rpc\client;
    
    use Caylof\Rpc\Driver\WorkmanFrameClient;
    
    abstract class ServiceClient
    {
        protected WorkmanFrameClient $client;
        protected string $serverServicePrefix = 'app\\rpc';
    
        public function __construct()
        {
            $this->client = new WorkmanFrameClient('tcp', '127.0.0.1', 2345);
        }
    
        public function __call(string $name, array $arguments)
        {
            $caller = sprintf('%s\\%s@%s',
                trim($this->serverServicePrefix, '\\'),
                substr(static::class, strrpos(static::class, '\\') + 1),
                $name
            );
            return $this->client->call($caller, ...$arguments);
        }
    }
    

    新建文件 app/rpc/client/TestSrv.php,作为 client 端服务类,只需继续基类:

    <?php
    
    namespace app\rpc\client;
    
    class TestSrv extends ServiceClient
    {
    }
    

    使用 client 服务类调用:

    $srv = new \app\rpc\client\TestSrv();
    $result = $srv->hello(['name' => 'asdf']);

over~ 感谢 workman !!!

2019 2 3
2个评论

不败少龙

https://www.workerman.net/q/6057 其实这个一样的简单

woshiyigebing

这是啥,云函数吗

  • 暂无评论

caylof

240
积分
0
获赞数
0
粉丝数
2022-08-13 加入
🔝