workerman本身不是现成api网关,需手动组装路由、jwt认证、限流等功能;核心是用worker作http入口、asynctcpconnection异步转发请求至后端,避免同步阻塞,同时须处理连接复用、超时、协议解析及错误关闭等细节。

Workerman 本身不是现成的 API 网关产品,它不内置路由规则引擎、JWT 验证中间件或限流策略配置项。你得自己组装——但正因如此,它才能做到极轻量、极高并发、极低内存占用。直接上手写网关逻辑,比套用 Spring Cloud Gateway 或 Kong 这类重型方案更可控,也更适合中小团队定制化需求。
如何用 Worker 和 AsyncTcpConnection 实现请求转发?
核心是把 Worker 当 HTTP 入口,用 AsyncTcpConnection 异步发请求到后端服务,避免阻塞主线程。
常见错误现象:onMessage 回调里直接 file_get_contents() 或 cURL 同步调用,导致整个进程卡死,QPS 暴跌;或者忘记 $connection->close() 或 $backend->close(),连接堆积泄漏。
- 必须使用
AsyncTcpConnection(或Coroutine\Http\Client,如果启用了协程扩展)做后端通信,不能用同步网络函数 - 转发前要手动解析
$request->header、$request->get、$request->post,Workerman不自动做参数合并 - 后端返回非 JSON 时,
$connection->send()前需补全Content-Type头,否则浏览器可能乱码 - 若后端是 HTTP,建议统一走
http://127.0.0.1:8001形式;若是自定义 TCP 协议,确保协议格式双方对齐(比如包头长度字段)
onMessage 中怎么安全做路由分发?
别写一堆 if (strpos($path, '/api/user')) 嵌套判断。路径匹配效率低,且无法支持通配符和变量提取(如 /api/user/{id})。
推荐做法:用一个轻量级数组路由表 + preg_match,不引入第三方 router 组件。
- 路由表结构示例:
['/api/users(?:/(?P<id>\d+))?$' => ['backend' => 'tcp://127.0.0.1:8001', 'method' => 'userHandler']]</id> - 匹配后从
$matches提取id,拼进转发 payload,而不是靠parse_url()手动切 - 未匹配路由必须显式返回
404,否则默认空响应会触发客户端超时重试,放大压力 - GET/POST/PUT 等方法要校验,
$request->method() !== 'POST'时直接send("405 Method Not Allowed")
为什么不能直接在 onMessage 里写 JWT 验证逻辑?
因为 onMessage 是事件回调,不是独立作用域;JWT 解析(尤其是验签)若用 firebase/php-jwt 默认的 OpenSSL 方式,会轻微阻塞。高并发下,几十个并发验签就可能拖慢事件循环。
真正可行的做法是:把验签逻辑下沉到连接建立阶段(onConnect),或用预共享密钥(PSK)方式跳过公钥运算。
- 若必须动态验 JWT,改用对称密钥(
HS256)而非RS256,性能提升 3–5 倍 - 把
JWT::decode()放在Worker::$onWorkerStart里预热 OpenSSL 上下文,减少重复初始化开销 - 验证失败不要只
return,必须调用$connection->close(),防止恶意 token 轮询耗尽连接数 - API Key 可走 Header:
$request->header('X-Api-Key'),比 query 参数更安全,也更容易被 Nginx 层提前拦截
并发压测时连接数暴涨但 QPS 上不去,问题出在哪?
典型表现是 netstat -an | grep :8080 | wc -l 达到几千,但 ab -n 10000 -c 1000 测出来只有 200 QPS。这不是 Workerman 的锅,而是你没调好底层资源边界。
关键点不在 PHP 代码,而在 Linux 内核参数和 Workerman 自身配置协同:
-
$worker->count别盲目设成 CPU 核数 × 2;实际应 ≤ulimit -n/ 1024,否则子进程抢不到文件描述符 - 确认开了
Event或Swoole扩展:没它们时Workerman回退到select(),单进程扛不住 1000+ 并发 -
/proc/sys/net/core/somaxconn至少调到 65535,否则新连接在内核队列就被丢弃 - 后端服务响应时间超过 200ms 时,务必加超时:
$backend->timeout = 1.5;,否则异步连接挂起太久,挤占可用连接槽位
最易被忽略的是:所有 AsyncTcpConnection 实例都该复用连接池(Workerman\Connection\TcpConnection::setProtocol() 不够,得自己实现简单连接池),否则每请求新建 TCP 连接,三次握手 + TIME_WAIT 开销远超业务逻辑本身。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











