当前位置: 首页 > news >正文

elli WebSocket 实现指南:Handover 机制让双工通信更简单的 30 分钟实战

elli WebSocket 实现指南:Handover 机制让双工通信更简单的 30 分钟实战

【免费下载链接】elliSimple, robust and performant Erlang web server项目地址: https://gitcode.com/gh_mirrors/ell/elli

elli 是一个简单、健壮且高性能的 Erlang web server,专为 HTTP API 场景设计,但你同样可以用它轻松实现 WebSocket 服务。本文将带你用 30 分钟掌握 elli 的 Handover 机制:它能把 TCP socket 的控制权直接交给你的业务代码,让你从零搭建一个双工通信服务。无论你是 Erlang 新手还是正在选型 WebSocket 服务器方案,这份 elli WebSocket 实现指南都能帮你快速上手。

为什么用 elli 做 WebSocket 服务?🧐

先说结论:elli 本身不内置 WebSocket 协议解析,但它提供了一条极其优雅的"逃生通道"——Handover。相比 Cowboy 等重型框架,elli 的核心优势在于:

特性说明
🚀 高性能基于 acceptor 池 + 事件驱动,文档称其为 performant Erlang web server
📦 极简源码仅十几个模块,无重型依赖,学习成本低
🔌 可扩展Middleware 机制支持请求预处理与多 handler 链式路由
🎯 精准控制Handover 把连接控制权交给用户,协议实现完全自由

更关键的是,elli 的 CHANGELOG.md 明确提到:"Handover" a socket to user code, making it possible to implement WebSockets,也就是说 Handover 机制的设计初衷之一,就是为 WebSocket 这类长连接双工协议提供实现空间。

Handover 机制的核心原理:连接控制权交接 🔄

在了解实战之前,先花 2 分钟搞懂原理。elli 的请求处理流程通常是这样:连接建立 → 解析 HTTP 请求 → 调用回调函数 → 返回响应。而 Handover 机制在中间插入了一个"岔路口":

%% 位于 elli_http.erl 的 handle_request/4 case init(Req) of {ok, standard} -> %% 标准流程:读 body、执行回调、返回响应 ...; {ok, handover} -> %% Handover 流程:直接调用你的 handle/2, %% 由你的代码接管整个 socket! Req1 = Req#req{body = B1}, Response = Mod:handle(Req1, Args), Response end

这段逻辑就在 elli_http.erl。当你的回调模块在init/2中返回{ok, handover}时,elli 就不再按 HTTP 语义处理这个连接,而是把Req(其中携带了socket字段)直接交给你的handle/2函数。

💡一句话总结:Handover 就像你把方向盘交给了司机——之后车怎么开(协议怎么聊),完全由你决定。这正是实现 WebSocket 升级握手的理想切入点。

30 分钟实战:搭建基于 Handover 的 WebSocket 服务 🛠️

第一步:获取并编译 elli 源码(约 3 分钟)

首先克隆项目源码:

git clone https://gitcode.com/gh_mirrors/ell/elli cd elli make

项目使用 rebar 构建,依赖为空(deps, []),编译非常轻量。编译通过后,你可以先跑一下测试验证环境:

make eunit

其中 elli_handover_tests.erl 就是 Handover 路径的集成测试用例,稍后我们会对照它来理解代码。

第二步:从官方示例理解 Handover 触发方式(约 10 分钟)

elli 提供了一个开箱即用的示例模块 elli_example_callback_handover.erl,它展示了 Handover 的完整用法,核心逻辑分为三部分:

1. 在 init/2 中判定哪些请求走 Handover:

init(Req, _Args) -> case elli_request:path(Req) of [<<"hello">>, <<"world">>] -> {ok, handover}; %% 命中路径 → 触发 Handover _ -> ignore %% 其他路径 → 标准流程 end.

2. 在 handle/2 中接管连接,直接使用底层 socket 通信:

handle('GET', [<<"hello">>, <<"world">>], Req, _Args) -> Body = <<"Hello World!">>, Size = list_to_binary(integer_to_list(size(Body))), %% 绕过 elli 的响应封装,直接通过 socket 发送 elli_http:send_response(Req, 200, [{"Connection", "close"}, {"Content-Length", Size}], Body), {close, <<>>}; %% 返回 {close, _} 表示处理完毕后关闭连接

3. 其他请求照常走普通 HTTP 流程:

handle('GET', [<<"hello">>], Req, _Args) -> Name = elli_request:get_arg(<<"name">>, Req, <<"undefined">>), {ok, [], <<"Hello ", Name/binary>>}.

⚠️ 注意{close, <<>>}这个返回值——它告诉 elli"连接已由我处理完毕,请关闭 socket"。如果你的 WebSocket 连接要保持长连接,这里就要返回相应的长连接语义(例如持续循环接收数据),这也是从 Handover 到 WebSocket 的关键一步。

第三步:改造为真正的 WebSocket 双工通信(约 15 分钟)

现在你已经掌握了 Handover 的骨架,要让它"升级"成 WebSocket 服务,只需要做两件事:

  1. 完成 HTTP 升级握手:在handle/2中读取请求头,校验Upgrade: websocketSec-WebSocket-Key,然后向客户端返回101 Switching Protocols响应;
  2. 进入消息循环:握手成功后,用gen_tcp:recv/2循环读取客户端帧,解析 WebSocket 帧格式(FIN、opcode、mask、payload length 等),并调用gen_tcp:send/2回写数据。

由于 socket 已经握在你手里,双工通信的实现完全透明。你可以按需实现 ping/pong 心跳、分片消息、二进制帧等功能,不受 elli 框架的任何约束。

启动服务的方式与普通 elli 服务完全一致,只需把 callback 换成我们的模块:

{ok, Pid} = elli:start_link([{callback, elli_example_callback_handover}, {port, 3003}]).

参考 elli_handover_tests.erl 中的setup/0,你可以照葫芦画瓢写出自己的启动与集成测试。

进阶:Handover 与 Middleware 的搭配技巧 🧩

如果你的项目需要鉴权、压缩等横切逻辑,可以借助 elli_middleware.erl 实现多 handler 链式处理。Middleware 本身也是一个 elli handler,支持预处理与后处理,例如:

Config = [{mods, [ {elli_example_middleware, []}, %% 前置中间件 {elli_middleware_compress, []}, %% 压缩中间件 {elli_example_callback_handover, []} %% 真正的业务回调(Handover) ]}], elli:start_link([..., {callback, elli_middleware}, {callback_args, Config}]).

推荐把鉴权、日志放在前置中间件,让 Handover 回调专注于 WebSocket 协议本身,这样职责清晰、便于测试。

常见问题与避坑指南 🚧

  • 为什么我的 handover 请求没有触发?检查init/2的返回值:必须是{ok, handover}原子元组,且你的模块需要导出init/2handle/2handle_event/3三个函数(见 elli_example_callback_handover.erl)。
  • WebSocket 长连接如何保持?Handover 后 elli 默认流程已结束,你需要在自己的handle/2里维护消息循环,注意设置合适的 socket 接收超时,并实现心跳机制防掉线。
  • 性能如何保障?elli 每个连接由独立进程处理,天然契合 Erlang 的并发模型。WebSocket 长连接占用的进程资源远低于短连接风暴,配合min_acceptors参数调节 elli.erl 中的 acceptor 池大小即可。
  • 想用现成的 WebSocket 库?社区有基于 Handover 构建的 elli_websocket 扩展,你可以在 CHANGELOG 的 v1.0 说明中找到线索,再结合本文原理自行集成。

总结 ✅

通过本文的 30 分钟实战,你学会了:

  1. elli 作为Erlang web server的轻量、高性能特性;
  2. Handover 机制的本质:init/2返回{ok, handover}后,连接控制权交给用户代码;
  3. 基于 elli_example_callback_handover.erl 改造出 WebSocket 双工通信服务的完整思路;
  4. 与 Middleware 搭配以及常见坑位的规避方法。

elli 的哲学是"框架只管 HTTP,协议自由发挥"。Handover 机制就像一把万能钥匙,让 WebSocket 这类双工协议在你的 Erlang 服务中轻松落地。现在就 clone 一份源码动手试试吧,30 分钟后你也能拥有自己的 WebSocket 服务!🚀

【免费下载链接】elliSimple, robust and performant Erlang web server项目地址: https://gitcode.com/gh_mirrors/ell/elli

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

http://www.cnnetsun.cn/news/4068286.html

相关文章:

  • PingFangSC字体免费开源:绕过中文网页跨平台排版的三道坎
  • Linux系统下R语言环境搭建与包管理全攻略
  • KMS激活工具完整实战记录:一条脚本让 Windows 和 Office 激活不再是难题
  • 呼叫中心服务商怎么选?技术能力、服务保障、合规资质3核心
  • AI Agent开发实战:从核心架构到OpenClaw本地部署指南
  • Linux看B站还靠浏览器硬撑?这款开源客户端把弹幕和漫游一次补齐
  • 近红外光谱研究缺数据?Open-Nirs-Datasets 让你从样本荒走向模型上线
  • 人生过得很通透,很不一般的博主
  • AI Agent 编排与云原生 AI 应用部署:模型输出异常时的降级边界
  • Microsoft 标识平台应用类型和身份验证流
  • LaTeX分段编译实战:用input、include与includeonly提升大型文档编译效率
  • iperf3 Windows版上手指南:5分钟测出你的真实网速
  • RPG-Maker-MV-Decrypter 完整指南:三步打开 RPG Maker 加密素材宝箱(附避坑清单)
  • AI变声从零到一:开源RVC WebUI,10分钟语音就能训练专属音色模型
  • 大模型工具调用新范式:代码优先策略提升AI代理准确性
  • C#枚举绑定ComboBox:告别硬编码,实现类型安全与优雅取值
  • Neo-Async 流程控制一文读懂:parallel、series 与 waterfall 的完整教程
  • 终结磁盘空间紧张局面,针对性处理重复、无用文件
  • Search完全指南:AI的“实时信息获取”能力
  • 多核处理器技术解析:从缓存一致性问题到异构计算演进
  • 电机选型与分类全解析:从原理到实战应用
  • AI知识库(Knowledge Base)核心知识点详解
  • Linux系统管理与运维进阶实战指南
  • 番茄小说下载工具完全指南:5种导出格式、3种运行方式,把心爱小说永久留在本地
  • 告别微信压缩图:5分钟搭建Windows与iPhone的跨平台文件传输通道
  • AI服务器狂飙:算力大周期下,不止是GPU的狂欢
  • pgrust 命令行速查手册:从启动到关闭的常用命令大全
  • MTKClient 联发科刷机一次讲透:从备份救砖到刷入自定义系统的实操路线
  • MiniMax-Music-3 代码实现原理:从文本编码到波形输出的完整生成流水线
  • C语言位操作