hyperf 3.0 支持在 server.php 中并列定义多个 rpc 服务块,每个需唯一 name、不冲突端口(如 9502 和 9503),分别绑定对应协议处理器(如 tcpserver 或 httpserver),tcp 配置 package_* 参数仅对其生效,http 入口不可混用同一端口,消费者需按端口独立配置 nodes 与 client_count。

server.php里加多个rpc服务块就行
Hyperf 3.0 支持在 config/autoload/server.php 中定义多个独立的 RPC 服务入口,本质是启动多个 TCP Server 实例,每个绑定不同端口、不同协议处理逻辑。不是“一个 server 配置多个节点”,而是“多个 server 配置项并列”。
- 每个
rpc类型 server 必须有唯一name(如'name' => 'rpc-user'),不能重复 - 端口必须不冲突,比如
9502和9503可以共存,但两个都写9502会启动失败 -
callbacks[Event::ON_RECEIVE]必须指向对应协议的接收处理器,JSON-RPC over TCP 用Hyperf\RpcMultiplex\TcpServer::class,而 JSON-RPC over HTTP 则要用Hyperf\JsonRpc\HttpServer::class -
settings中的包解析配置(如package_length_type)只对 TCP 类型生效,HTTP 类型 server 不需要也不应配置这些
JSON-RPC TCP 和 HTTP 入口不能混用同一端口
常见错误是把 jsonrpc-http 和 jsonrpc-tcp 都绑到 9502,结果只有其中一个能正常工作——Swoole 不允许同一端口同时监听两种协议类型。HTTP 入口依赖 Swoole 的 SERVER_HTTP 类型,TCP 入口依赖 SERVER_BASE,底层协议栈完全不同。
- HTTP 入口适合前端联调、curl 测试、浏览器直接访问,路径形如
http://127.0.0.1:9501/jsonrpc - TCP 入口适合内部高频调用,延迟更低,但需客户端用 TCP 连接,不能用 curl 直连
- 如果想对外暴露统一入口,建议只开 HTTP 入口,或用 Nginx 做 TCP 代理(不推荐,破坏长连接优势)
多入口下 client_count 和负载均衡怎么算
每个 RPC 客户端配置(config/autoload/services.php 中的 consumers)是独立的,client_count 参数只作用于该 consumer 对应的 server 地址。比如你开了 rpc-user(9502)和 rpc-order(9503)两个入口,那消费者要分别配两套:
return [
'consumers' => [
[
'name' => 'UserService',
'service' => App\JsonRpc\UserServiceInterface::class,
'protocol' => Hyperf\RpcMultiplex\Constant::PROTOCOL_DEFAULT,
'nodes' => [['host' => '127.0.0.1', 'port' => 9502]],
'options' => ['client_count' => 2],
],
[
'name' => 'OrderService',
'service' => App\JsonRpc\OrderServiceInterface::class,
'protocol' => Hyperf\RpcMultiplex\Constant::PROTOCOL_DEFAULT,
'nodes' => [['host' => '127.0.0.1', 'port' => 9503]],
'options' => ['client_count' => 4],
],
],
];
-
client_count是每个 consumer 自己维护的连接池大小,不是全局共享的 - 负载均衡策略(如随机、一致性哈希)也是按 consumer 独立生效,不会跨入口混用
- 如果你把两个 service 的
nodes都指向同一个host:port,那它们会共享该地址下的连接池,但语义上已违背“多入口”初衷
服务注册时 publishTo 会按 name 区分实例
当你用 @RpcService(publishTo="consul") 注解发布服务,Consul 里注册的 service ID 默认是 name + IP + port 拼接的。所以即使两个服务实现类用了同一个接口(比如都 implements UserInterface),只要 @RpcService(name="user-v1") 和 @RpcService(name="user-v2") 不同,就会注册为两个独立服务实例。
- 客户端调用时,consumer 的
name必须和@RpcService(name=...)严格一致,否则找不到服务 - 如果没配
publishTo,服务只在本地进程内可用,无法被其他机器的 consumer 发现 - 多端口部署时,别忘了在 Consul 的健康检查路径里带上端口号,否则所有实例可能被判定为同一健康状态
worker_num 要同步调高,否则高并发下会出现 “No worker available” 错误。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











