avatar

mdo

Hello

  • 首页
  • 知识库
  • 归档
  • 标签
  • 关于
主页 通过网关代理类gateway动态分发客户端的调用
文章

通过网关代理类gateway动态分发客户端的调用

发表于 2026-06-10 更新于 2026-06- 14
作者 mdo
9~12 分钟 阅读

针对方案一(通过网关代理类动态分发),客户端如果同样是 TP 项目,由于服务端在 config/swoole.php 中只向官方扩展注册了一个固定的服务标识 gateway,客户端的调用方式也需要做出相应的配合。

以下是客户端对应的具体调用写法,分为快捷调用和优雅的代理类调用(推荐)两种:

写法 A:通过 RPC 门面直接快捷调用

这是最直接的写法,客户端直接连接服务端的 gateway 标识,并将实际的目标服务名和方法名作为参数打包传过去:

php

namespace app\controller;

use think\swoole\facade\RPC;

class OrderController
{
    public function index()
    {
        // 1. 连接服务端配置的 'gateway' 服务
        // 2. 调用服务端的 __call 魔术方法,依次传入:[目标服务标识, 目标方法名, 实际参数]
        $userInfo = RPC::user('gateway')->execute('user', 'getInfo', ['uid' => 99]);

        return json($userInfo);
    }
}

请谨慎使用此类代码。

注: 这里的 execute 是在服务端 RpcGateway 类中可以自由定义的方法名(如果服务端用的是 __call,客户端这里写任何方法名如 run()、do() 都可以,因为服务端都会通过魔术方法接收)。


写法 B:高级代理写法(完美复刻本地调用感,推荐)

写法 A 虽然能用,但代码看起来不够优雅,且失去了 IDE 的代码提示。在实际开发中,更推荐在客户端编写一个本地动态代理类,让调用端维持 UserService->getInfo() 这种完全面向对象的原生体验。

1. 客户端创建动态代理基类

在客户端创建一个公共的代理基类 app\rpc\client\BaseProxy.php,用来封装向服务端 gateway 发送请求的底层逻辑:

php

namespace app\rpc\client;

use think\swoole\facade\RPC;

abstract class BaseProxy
{
    // 子类需要定义自己对应服务端的哪个“动态服务标识”
    protected $serviceAlias = '';

    /**
     * 利用魔术方法,自动拦截客户端调用的所有方法
     */
    public function __call($methodName, $arguments)
    {
        // 自动打包:[ 动态服务标识, 调用的方法名, 传入的参数 ]
        return RPC::user('gateway')->execute(
            $this->serviceAlias, 
            $methodName, 
            $arguments
        );
    }
}

请谨慎使用此类代码。

2. 客户端为每个远程服务定义一个空类

有了基类后,客户端如果要调用服务端的 user 服务,只需要继承基类并指定标识即可。
创建 app\rpc\client\UserService.php:

php

namespace app\rpc\client;

/**
 * 用户远程服务代理
 * @method array getInfo(int $uid)  <-- 在这里写注解,IDE 就会有完美的代码提示!
 */
class UserService extends BaseProxy
{
    // 对应服务端动态映射表(如 Redis/数据库)里的键名
    protected $serviceAlias = 'user'; 
}

请谨慎使用此类代码。

3. 客户端控制器中的最终调用

通过上述代理封装后,你在控制器或者 Service 层调用时,完全感知不到“网关分发”的存在,代码极度干净:

php

namespace app\controller;

use app\rpc\client\UserService;

class Index
{
    protected $userService;

    // 通过 TP6 容器自动注入代理类
    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function getUser()
    {
        // 像调用本地方法一样,IDE 还能正常提示方法和参数
        $result = $this->userService->getInfo(99);

        return json($result);
    }
}

请谨慎使用此类代码。


🛠️ 配合方案一的服务端微调提醒

为了配合客户端通过 execute 或者魔术方法调用,服务端 app\rpc\RpcGateway.php 的接收方法需要对应写成这样:

php

namespace app\rpc;

use think\Container;

class RpcGateway
{
    /**
     * 统一接收客户端的 execute 请求
     */
    public function execute(string $serviceAlias, string $methodName, array $realParams = [])
    {
        // 1. 从 Redis 或配置中动态获取类名
        $serviceClass = \think\facade\Cache::store('redis')->get("rpc:services:{$serviceAlias}");
        
        if (!$serviceClass || !class_exists($serviceClass)) {
            throw new \Exception("RPC服务 [{$serviceAlias}] 未注册");
        }

        // 2. 实例化并调用
        $serviceInstance = Container::getInstance()->make($serviceClass);
        
        return call_user_func_array([$serviceInstance, $methodName], $realParams);
    }
}

请谨慎使用此类代码。

这种设计下,如果未来你服务端新增了一个 goods 货品服务,你只需要在服务端的 Redis 里加一条映射,然后客户端直接新建一个继承 BaseProxy 的 GoodsService 类即可直接调用,两端都不需要重启 Swoole 进程。

技术
许可协议:  CC BY 4.0
分享

相关文章

10月 2, 2026

iOS 侧载(Sideloading)工具

AltStore 和 Sideloadly 都是目前最流行的 iOS 侧载(Sideloading)工具。 简单来说,它们的作用就是让你绕过苹果的官方 App Store,直接把第三方的 IPA 安装包(也就是 iOS 的应用安装文件)安装到你的 iPhone 或 iPad 上。 通过这两个工具,你

9月 28, 2026

注册 Chat Participant

将当前服务接入 VS Code 的 AI 聊天窗口是完全可行的。VS Code 在近期的版本中正式推出了 Chat Extensions API(github.copilot.chat),允许第三方扩展将自定义的 LLM 服务或工具注册到 Copilot Chat 面板中。 结合当前 code_ge

9月 23, 2026

php intelephense 设置 if 空格

在 VS Code 中,如果你使用的是 PHP Intelephense 插件,控制 if 关键字后面是否加空格的设置是由其内置的格式化引擎(基于 PSR-12 标准)决定的。 你可以通过修改 VS Code 的 settings.json 来配置这个行为: 1. 开启 if 后面的空格(默认/推荐

下一篇

轻量级开源全文搜索引擎:Manticore Search 入门介绍 - 实践

上一篇

原生的 fsockopen 或基于流的 socket 客户端

最近更新

  • 比尔盖茨的智慧:想多赚钱,就每天循环做这3件事
  • iOS 侧载(Sideloading)工具
  • 程序员越想创业,越不要急着动手
  • 注册 Chat Participant
  • 中秋给在外游子的一封信

热门标签

API CodeGeex Coding Cursor DeepSeek Docker Gitkraken Harness Laravel Management

目录

©2026 mdo. 保留部分权利。