后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载Hyperf 通过hyperf/websocket-server组件为 WebSocket 提供了完整的封装使开发者能够在协程框架内以近乎 HTTP 服务的开发体验快速搭建 WebSocket 应用。本文将以官方文档为骨架结合仓库源码从安装、服务配置、路由与中间件、控制器编写、连接级上下文、跨 Worker 消息推送以及 HTTP/WebSocket 混合监听等方面带你完整掌握在 Hyperf 中构建 WebSocket 服务的全过程。组件简介与安装hyperf/websocket-server是 Hyperf 官方提供的 WebSocket Server 封装组件。它复用了 Hyperf 的依赖注入DI、中间件、路由与异常处理体系将 Swoole/Swow 底层的 WebSocket 事件回调收敛为与 HTTP 控制器风格一致的编程模型。其核心入口类Hyperf\WebSocketServer\Server实现了OnHandShakeInterface、OnMessageInterface、OnCloseInterface三个契约见 src/websocket-server/src/Server.php。安装组件composer require hyperf/websocket-server安装完成后即可在config/autoload/server.php中注册 WebSocket 服务。服务端配置注册 WebSocket Server编辑config/autoload/server.php在servers数组中追加一个类型为Server::SERVER_WEBSOCKET的服务?php return [ servers [ [ name ws, type Server::SERVER_WEBSOCKET, host 0.0.0.0, port 9502, sock_type SWOOLE_SOCK_TCP, callbacks [ Event::ON_HAND_SHAKE [Hyperf\WebSocketServer\Server::class, onHandShake], Event::ON_MESSAGE [Hyperf\WebSocketServer\Server::class, onMessage], Event::ON_CLOSE [Hyperf\WebSocketServer\Server::class, onClose], ], ], ], ];配置项说明name服务名称用于后续路由、中间件配置中对该服务进行定位type服务类型WebSocket 服务必须使用Server::SERVER_WEBSOCKEThost/port监听地址与端口示例中监听0.0.0.0:9502sock_type套接字类型TCP 服务使用SWOOLE_SOCK_TCPcallbacks事件回调映射将握手、消息、关闭三个事件分别绑定到Hyperf\WebSocketServer\Server的onHandShake、onMessage、onClose方法。从源码看onHandShakesrc/websocket-server/src/Server.php#L118-L186是 WebSocket 请求的入口它会先通过Security校验sec-websocket-key正则#^[/0-9A-Za-z]{21}[AQgw]$#且 base64 解码后长度必须为 16见 src/websocket-server/src/Security.php随后交由CoreMiddleware完成路由分发并利用FdCollector记录「fd → 控制器类」的映射关系src/websocket-server/src/Collector/FdCollector.php为后续onMessage/onClose找到对应的处理实例。路由配置目前 WebSocket 路由仅支持配置文件方式注解模式将在未来版本提供。在config/routes.php中通过Router::addServer()为名为ws的 Server 添加路由。这里的ws必须与config/autoload/server.php中 WebSocket 服务的name值保持一致?php Router::addServer(ws, function () { Router::get(/, App\Controller\WebSocketController); });Router::get的第一个参数是路径第二个参数是该路径对应的控制器类。由于 Hyperf 的 WebSocket 服务复用 HTTP 路由体系握手阶段即完成路由匹配匹配失败会抛出WebSocketHandShakeException对应源码 src/websocket-server/src/CoreMiddleware.php#L30-L35 中对「Router not exist.」的处理。中间件配置在config/autoload/middlewares.php中以 Server 的name为键配置该服务的全局中间件?php return [ ws [ yourMiddleware::class ] ];同样地ws取决于你在config/autoload/server.php中配置的 WebSocket 服务名。从Server::initCoreMiddlewaresrc/websocket-server/src/Server.php#L79-L89可以看到中间件读取自middlewares.serverName异常处理器默认使用WebSocketExceptionHandler::class也可通过exceptions.handler.serverName覆盖配置。握手阶段会将全局中间件与路由级中间件合并后统一执行。编写 WebSocket 控制器控制器同时实现OnMessageInterface、OnOpenInterface、OnCloseInterface三个接口即可分别处理消息、连接建立与连接关闭?php declare(strict_types1); namespace App\Controller; use Hyperf\Contract\OnCloseInterface; use Hyperf\Contract\OnMessageInterface; use Hyperf\Contract\OnOpenInterface; use Hyperf\Engine\WebSocket\Frame; use Hyperf\Engine\WebSocket\Response; use Hyperf\WebSocketServer\Constant\Opcode; use Swoole\Server; use Swoole\WebSocket\Server as WebSocketServer; class WebSocketController implements OnMessageInterface, OnOpenInterface, OnCloseInterface { public function onMessage($server, $frame): void { $response (new Response($server))-init($frame); if($frame-opcode Opcode::PING) { // 如果使用 Coroutine Server识别到 PING 帧后需要手动处理并返回 PONG 帧。 // 对于异步风格 Server可以直接通过 Swoole 配置处理。 $response-push(new Frame(opcode: Opcode::PONG)); return; } $response-push(new Frame(payloadData: Recv: . $frame-data)); } public function onClose($server, int $fd, int $reactorId): void { var_dump(closed); } public function onOpen($server, $request): void { $response (new Response($server))-init($request); $response-push(new Frame(payloadData: Opened)); } }关键点说明消息收发onMessage中通过(new Response($server))-init($frame)获取当前连接的响应对象再调用push(new Frame(...))向客户端回传数据Frame支持命名参数构造payloadData为数据内容、opcode为帧类型。PING/PONG 心跳代码对Opcode::PING进行了显式识别并返回Opcode::PONG帧。注释特别提醒使用 Coroutine Server 时必须在应用层手动应答 PING异步风格 Server 则可通过 Swoole 配置自动处理。帧类型常量Opcode类src/websocket-server/src/Constant/Opcode.php定义了CONTINUATION(0x0)、TEXT(0x1)、BINARY(0x2)、CLOSE(0x8)、PING(0x9)、PONG(0xA)六种标准操作码可用于判断文本、二进制、关闭、心跳等帧。打开与关闭onOpen在握手成功后触发可用于下发欢迎信息或初始化状态onClose收到连接关闭事件可用于资源清理。从源码看Server::onMessagesrc/websocket-server/src/Server.php#L188-L214会先从FdCollector取出该 fd 对应的控制器类并实例化再校验其是否实现OnMessageInterface然后调用onMessageonClosesrc/websocket-server/src/Server.php#L216-L240则在defer中清理FdCollector与连接上下文保证异常情况下也能释放资源。启动服务与验证完成上述配置后启动服务$ php bin/hyperf.php start [INFO] Worker#0 started. [INFO] WebSocket Server listening at 0.0.0.0:9502 [INFO] HTTP Server listening at 0.0.0.0:9501可以看到 WebSocket Server 已在9502端口运行即可使用任意 WebSocket Client 连接并传输数据。! 当 HTTP Server9501与 WebSocket Server9502同时监听时WebSocket Client 通过这两个端口均能连接成功即连接ws://0.0.0.0:9501与ws://0.0.0.0:9502都会握手成功。这是因为Swoole\WebSocket\Server继承自Swoole\Http\Server天然具备 HTTP 能力。因此你也可以利用 HTTP 请求来触发 WebSocket 推送具体可参考 Swoole 文档中onRequest回调部分。如果你需要禁用 HTTP 服务的 WebSocket 协议能力可以在config/autoload/server.php中为http服务添加open_websocket_protocol配置项?php return [ // 该文件的其他配置已省略 servers [ [ name http, type Server::SERVER_HTTP, host 0.0.0.0, port 9501, sock_type SWOOLE_SOCK_TCP, callbacks [ Event::ON_REQUEST [Hyperf\HttpServer\Server::class, onRequest], ], settings [ open_websocket_protocol false, ] ], ] ];连接级上下文ContextWebSocket 服务的onOpen、onMessage、onClose回调并不在同一个协程中触发因此不能直接依赖协程上下文coroutine context来跨回调保存状态。hyperf/websocket-server为此提供了连接级connection-level上下文Hyperf\WebSocketServer\Context其 API 与协程上下文完全一致?php declare(strict_types1); namespace App\Controller; use Hyperf\Contract\OnMessageInterface; use Hyperf\Contract\OnOpenInterface; use Hyperf\Engine\WebSocket\Frame; use Hyperf\Engine\WebSocket\Response; use Hyperf\WebSocketServer\Context; use Swoole\WebSocket\Server as WebSocketServer; class WebSocketController implements OnMessageInterface, OnOpenInterface { public function onMessage($server, $frame): void { $response (new Response($server))-init($frame); $response-push(new Frame(payloadData: Username: . Context::get(username))); } public function onOpen($server, $request): void { Context::set(username, $request-cookie[username]); } }上面的示例中onOpen将客户端 Cookie 中的用户名写入连接上下文onMessage中即可读取到该值实现了跨回调的会话数据共享。从源码src/websocket-server/src/Context.php可以看到其实现机制Context内部以静态数组存储所有数据以fd作为一级键、以id作为二级键进行读写如sprintf(%d.%s, $fd, $id)从而将数据与具体连接绑定fd由协程上下文中的Context::FD即ws.fd提供该值在Server::onHandShake、onMessage、onClose中都会通过Context::set(WsContext::FD, $fd)写入见 src/websocket-server/src/Server.php#L123、#L195、#L225。Context提供的方法包括set($id, $value)写入数据get($id, $default null, $fd null)读取数据支持指定 fdhas($id, $fd null)判断是否存在destroy($id)销毁单个键release(?int $fd null)释放整个连接的全部数据copy($fromFd, $keys [])将指定连接的数据复制到当前连接可选复制部分键override($id, Closure $closure)/getOrSet($id, $value)便捷的读改写工具方法。这些能力均有对应的单元测试覆盖见 src/websocket-server/tests/ContextTest.php包括并发场景下的copy行为验证。多服务部署Nginx 负载均衡当 WebSocket 服务需要水平扩展时可通过 Nginx 对多个 WebSocket Server 实例做反向代理与负载均衡。因为 WebSocket 是基于 Upgrade 的长连接协议需要显式设置 Upgrade 相关的请求头# /etc/nginx/conf.d/ng_socketio.conf # Multiple ws servers upstream io_nodes { server ws1:9502; server ws2:9502; } server { listen 9502; # server_name your.socket.io; location / { proxy_set_header Upgrade websocket; proxy_set_header Connection upgrade; # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # proxy_set_header Host $host; # proxy_http_version 1.1; # Forward ke multiple ws servers proxy_pass http://io_nodes; } }其中upstream中按需列出多个 WebSocket 服务节点示例为ws1:9502与ws2:9502proxy_set_header Upgrade websocket与proxy_set_header Connection upgrade是 WebSocket 代理的关键配置缺少它们会导致握手失败。跨进程消息推送Sender当需要在 HTTP 服务或其他服务中主动向某个 WebSocket 连接推送数据或关闭连接时可以直接使用Hyperf\WebSocketServer\Sender。工作原理Sender会先判断目标fd是否归属于当前 Worker。若属于当前 Worker则直接通过 Swoole Server 发送数据若不属于则通过PipeMessage将消息广播给除自己以外的所有 Worker由持有该fd的 Worker 完成实际发送。Sender提供两个核心 APIpush推送数据与disconnect断开连接在 HTTP 控制器中的典型用法如下?php declare(strict_types1); namespace App\Controller; use Hyperf\Di\Annotation\Inject; use Hyperf\HttpServer\Annotation\AutoController; use Hyperf\WebSocketServer\Sender; use function Hyperf\Coroutine\go; #[AutoController] class ServerController { #[Inject] protected Sender $sender; public function close(int $fd) { go(function () use ($fd) { sleep(1); $this-sender-disconnect($fd); }); return ; } public function send(int $fd) { $this-sender-push($fd, Hello World.); return ; } }上述示例分别演示了/server/close/{fd}在延迟 1 秒后断开指定连接go创建协程避免阻塞请求以及/server/send/{fd}立即向指定 fd 推送Hello World.文本。从源码src/websocket-server/src/Sender.php可以进一步理解其实现细节连接状态校验check($fd)通过connection_info($fd)获取连接信息仅当websocket_status WEBSOCKET_STATUS_ACTIVE时认为连接可写src/websocket-server/src/Sender.php#L128-L137相关行为在 src/websocket-server/tests/SenderTest.php 的testSenderCheck中有完整测试跨 Worker 广播sendPipeMessage()遍历worker_num - 1个 Worker向除自己外的每个 Worker 发送SenderPipeMessagesrc/websocket-server/src/Sender.php#L178-L188消息接收端OnPipeMessageListenersrc/websocket-server/src/Listener/OnPipeMessageListener.php监听OnPipeMessage事件识别SenderPipeMessage后由收到消息的 Worker 执行proxy()完成发送Worker 身份绑定InitSenderListenersrc/websocket-server/src/Listener/InitSenderListener.php在AfterWorkerStart事件中为Sender注入当前workerId这是跨进程定位与广播的基础协程风格 Server 适配当server.type为CoroutineServer或SwowServer时Sender切换为基于responses映射的直接发送模式无需跨进程广播。在 WebSocket 服务中处理 HTTP 请求除了通过端口将 HTTP 服务与 WebSocket 服务分离还可以让 WebSocket 服务同时监听 HTTP 请求。由于server.servers.*.callbacks中的配置项是单例singleton的因此需要先在dependencies中配置独立的实例?php return [ HttpServer Hyperf\HttpServer\Server::class, ];然后在config/autoload/server.php中为ws服务的callbacks添加Event::ON_REQUEST回调无关配置已省略?php declare(strict_types1); use Hyperf\Server\Event; use Hyperf\Server\Server; return [ mode SWOOLE_BASE, servers [ [ name ws, type Server::SERVER_WEBSOCKET, host 0.0.0.0, port 9502, sock_type SWOOLE_SOCK_TCP, callbacks [ Event::ON_REQUEST [HttpServer, onRequest], Event::ON_HAND_SHAKE [Hyperf\WebSocketServer\Server::class, onHandShake], Event::ON_MESSAGE [Hyperf\WebSocketServer\Server::class, onMessage], Event::ON_CLOSE [Hyperf\WebSocketServer\Server::class, onClose], ], ], ], ];最后即可在ws服务上添加 HTTP 路由。这样同一端口既能提供 WebSocket 长连接服务也能响应普通 HTTP 请求便于在单端口场景下实现「HTTP 触发推送」的架构。总结Hyperf 的 WebSocket Server 组件将握手校验、路由分发、中间件、异常处理、连接级上下文与跨 Worker 消息发送等复杂逻辑封装在Server、CoreMiddleware、Context、Sender等类中组件全部源码位于 src/websocket-server/src开发者只需关注控制器逻辑本身。掌握本文的服务注册、路由与中间件绑定、PING/PONG 心跳、连接上下文与 Sender 跨进程推送即可在生产中构建稳定可扩展的 WebSocket 应用并平滑接入 Nginx 负载均衡与多 Worker 部署架构。赞分享后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载相关推荐Hyperf WebSocket Server 实战指南从安装配置到跨进程消息推送的完整实现Hyperf WebSocket Server 实战指南从安装配置到跨进程消息推送的完整实现 导读 Hyperf 框架对 Swoole/Swow 的 WebS后端Web框架微服务RPC框架异步编程Hyperf WebSocket Server 实战指南从服务搭建到连接级上下文与跨 Worker 消息发送Hyperf WebSocket Server 实战指南从服务搭建到连接级上下文与跨 Worker 消息发送 Hyperf 官方文档 docs/zh cn/w后端微服务Hyperf WebSocket Server 实战指南从安装配置到连接上下文与跨 Worker 消息推送Hyperf WebSocket Server 实战指南从安装配置到连接上下文与跨 Worker 消息推送 导读 本文是 Hyperf 框架中 hyperf/后端Web框架微服务RPC框架异步编程上一篇如何将AITemplate与Jupyter集成交互式推理优化开发终极指南下一篇UZI-Skill 多平台安装完全指南Claude Code、Codex、Cursor、Gemini CLI 6种Agent一键配置创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考