基于axum和chromiumoxide实现headless browser服务
内容提要
这篇文章介绍了作者使用Rust实现了一个类似于Golang的功能,并提供了代码链接。主要功能是提供headless chrome的API服务,支持puppeteer连接远程的headless chrome实例。还介绍了一些遇到的问题和心得,以及与Gin框架的比较。文章还介绍了如何实现PDF和Screenshot以及puppeteer连接浏览器实例的功能。最后总结了使用Rust开发后台服务的优点和不足。
延伸解读
Rust 异步生态的选型考量
作者在开发中因 async-std 更新不活跃而转向 tokio,这反映了 Rust 异步运行时生态的现状。tokio 作为最主流的运行时,拥有更活跃的社区和更完善的工具链,但 vscode 对其调试支持仍不友好,遇到 await 会进入 poll 代码区域,增加调试难度。对于需要长期维护的后台服务,选择 tokio 能获得更好的生态支持,但需接受调试体验上的不足。
Axum 与 Gin 的框架差异
Axum 的 extract 功能可直接从请求中提取参数,省去手动解析 Form 的步骤,路由设计与 Gin 接近,迁移成本较低。但 Axum 的错误处理不够友好,handler 返回 Result 时难以便捷地将 Err 转为 Status 加 Json 响应,而 Gin 可直接返回 c.JSON(500, ...)。若团队习惯 Gin 的中间件生态和错误处理模式,转向 Axum 需在错误封装上投入额外工作。
超时控制与 WebSocket 桥接的实现思路
由于 chromiumoxide 无法为页面操作指定超时,作者用 tokio::select! 同时等待页面加载和定时器,实现超时控制。在 puppeteer 连接场景中,通过 tokio-tungstenite 建立 WebSocket 桥接,用 select! 并行处理双向消息转发和关闭信号。相比 Golang 版本用 io.Copy 的 hack 方案,Rust 实现更清晰且能感知消息内容,但代码量更大。
Rust 后台服务的优势与局限
作者认为 Rust 的异常处理和异步模型适合严谨的后台服务,但配套库成熟度不及 Golang,例如 chromiumoxide 缺少动态修改设备 Viewport 的能力。此外,Rust 编译速度比 Go 慢一倍以上,大型项目 CI 资源消耗更高。若项目对性能和可靠性要求高且能接受较长的编译时间,Rust 是可行选择;否则需权衡开发效率与运行效率。
Q&A
browserlify 是什么?它提供了哪些主要功能?
browserlify 是一个用 Rust 实现的 headless browser 服务,提供 headless chrome 的 API 服务,支持 puppeteer 连接远程 headless chrome 实例,并内置生成 PDF、截图、innerText、innerHTML 的快捷功能。
如何通过 puppeteer 连接到 browserlify 的 headless chrome 实例?
使用 puppeteer.connect 方法,传入 browserWSEndpoint 参数,例如 `ws://localhost:9000`,即可连接到远程 headless chrome 实例。
browserlify 如何实现 PDF 和截图功能?
通过创建一个 browser 实例,然后创建一个 page 实例,使用 page.goto 加载网页,再通过 page.pdf 和 page.screenshot 生成 PDF 和图片。由于 chromiumoxide 无法指定操作超时,使用 tokio::select 实现超时等待。
browserlify 如何实现 puppeteer 连接浏览器实例的桥接?
通过 websocket 桥接功能,连接后端的 chrome 实例,获取客户端(如 puppeteer)的 websocket,然后将客户端的 websocket 和后端的 websocket 进行桥接,使用 tokio::select 同时处理双向消息转发。
Axum 和 Gin 框架相比有哪些优缺点?
Axum 的 extract 功能方便,可以直接从 Request 中提取参数,route 功能与 Gin 接近,迁移方便;但 Axum 的 middleware 不如 Gin 丰富,错误处理不够友好,不能方便地将 Err 变成 Status + Json。
使用 Rust 开发 browserlify 有哪些心得和不足?
心得:Drop 功能类似 C++ 析构,log 功能强大,tokio::select! 比 go 的 select 强大,但 vscode 对 tokio 调试支持不友好。不足:配套库不如 golang 成熟,如 chromiumoxide 无法动态修改 Viewport,编译速度比 go 慢一倍以上。