ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

在 Puma 集群模式下使用 gRPC:生命周期钩子完整实战指南

在 Puma 集群模式下使用 gRPC:生命周期钩子完整实战指南 后端网络【免费下载链接】pumaA Ruby/Rack web server built for parallelism项目地址https://gitcode.com/gh_mirrors/pu/puma点击查看免费下载导读本指南围绕 PumaRuby/Rack 并行 Web 服务器的集群模式Clustered Mode讲解如何通过 Puma 提供的进程生命周期钩子hooks在 fork 前后正确调用 gRPC 的生命周期方法从而消除grpc cannot be used between calls to GRPC.prefork and GRPC.postfork_child or GRPC.postfork_parent这类运行时报错。读完本文你将掌握before_worker_fork、after_worker_fork、before_worker_boot三个钩子的执行时机与所在进程理解预加载preload与非预加载模式下的差异并拿到一份可在生产环境直接复制使用的config/puma.rb配置示例。问题集群模式 fork 下的 gRPC 状态错乱Puma 的集群模式通过多进程workers提供并行能力其本质是在主进程master中反复调用fork(2)派生出多个 worker 进程。而 gRPC 内部维护了大量与进程绑定、与线程池绑定的运行时状态fork 之后这些状态不会自动正确继承。因此在集群模式下使用 gRPC 时常常会遇到如下报错grpc cannot be used between calls to GRPC.prefork and GRPC.postfork_child or GRPC.postfork_parent这句话的含义是gRPC 检测到进程发生了 fork但使用者既没有在 fork 之前调用GRPC.prefork做好准备也没有在 fork 之后调用GRPC.postfork_child/GRPC.postfork_parent完成收尾。要让 gRPC 在集群环境下稳定工作必须在其进程生命周期的三个关键节点调用对应方法生命周期方法调用时机作用GRPC.preforkfork 之前为即将到来的 fork 做准备冻结/整理 gRPC 内部状态GRPC.postfork_childfork 之后的子进程worker内在子进程中重建、复位 gRPC 运行所需状态GRPC.postfork_parentfork 之后的父进程master内在父进程中恢复 gRPC 状态继续正常工作Puma 恰好提供了与这些时机一一对应的生命周期钩子这就是解决问题的基础。解决方案用 Puma 钩子编排 gRPC 生命周期完整配置示例下面的配置将 gRPC 的三个生命周期方法接入 Puma 集群模式的 fork 流程无论是否开启 preload 都可用# config/puma.rb is_mac RUBY_PLATFORM.include?(darwin) before_worker_fork do |index| GRPC.prefork unless is_mac end after_worker_fork do |index| GRPC.postfork_parent unless is_mac end before_worker_boot do GRPC.postfork_child unless is_mac end几点使用说明三个钩子都放在同一个config/puma.rb配置文件中Puma 启动时会通过 DSL 自动加载并注册这些钩子钩子块中的index参数是 worker 的索引从 0 开始的整数可据此区分不同 worker做更细粒度的处理macOS 特判is_mac RUBY_PLATFORM.include?(darwin)用于判断运行平台。在 macOS 上这些调用被跳过因为 macOS 的 fork 行为存在差异gRPC 在这些平台上不需要这些调用只有集群模式下这些钩子才会生效单进程single模式下它们会被跳过并给出警告详见下文钩子的 cluster_only 属性。钩子与进程生命周期的对应关系Puma 的钩子决定了何时调用 gRPC 的生命周期方法每个钩子在 fork 流程中扮演的角色如下before_worker_fork在 fork worker之前执行这里调用GRPC.prefork预加载preload模式下Puma v7 默认开启preload_app!应用在 master 进程中完成预加载因此该钩子运行在master 进程中非预加载模式下该钩子同样运行在master 进程、worker fork 之前只是应用尚未被预加载到 master在此调用GRPC.prefork为接下来的 fork 做好准备。after_worker_fork无论是否预加载该钩子始终运行在 master 进程中在一个 worker fork 完成之后执行在此调用GRPC.postfork_parent完成 master 进程 fork 后的状态收尾。before_worker_boot无论是否预加载该钩子始终运行在 worker 进程中在 worker 被 fork 出来之后、应用正式启动之前执行在此调用GRPC.postfork_child完成 worker子进程一侧的状态初始化。源码级印证钩子究竟在哪个进程、哪一刻执行master 侧的 fork 调用链先看Puma::Cluster的spawn_worker实现lib/puma/cluster.rbdef spawn_worker(idx, master) config.run_hooks(:before_worker_fork, idx, log_writer) pid fork { worker(idx, master) } if !pid log ! Complete inability to spawn new workers detected log ! Seppuku is the only choice. exit! 1 end config.run_hooks(:after_worker_fork, idx, log_writer) pid end从源码结构可以清晰看到before_worker_fork钩子在fork调用之前、且位于 master 进程上下文中执行fork之后master 立刻执行after_worker_fork钩子——同样在 master 进程内。这正与文档描述的GRPC.preforkfork 前、master 内和GRPC.postfork_parentfork 后、master 内一一对应。worker 侧的启动调用链再看 worker 进程的运行入口lib/puma/cluster/worker.rbdef run ... # Invoke any worker boot hooks so they can get # things in shape before booting the app. config.run_hooks(:before_worker_boot, index, log_writer, hook_data) begin server start_server rescue Exception e log ! Unable to start worker ... end源码注释和实现都表明before_worker_boot在fork完成后的worker子进程中执行且先于start_server应用/服务器启动。因此在这个钩子里调用GRPC.postfork_child时机完全正确——gRPC 会在 worker 真正开始服务请求之前完成子进程内的状态重建。钩子是如何注册与触发的注册三个钩子都通过 lib/puma/dsl.rb 中的 DSL 方法注册。before_worker_fork、after_worker_fork与before_worker_boot均带cluster_only: true标记表示这些钩子只在集群模式下有意义process_hook实现见 lib/puma/dsl.rb触发run_hooks定义在 lib/puma/configuration.rb它会遍历该钩子名下注册的所有 block 并依次执行若某钩子抛出异常会记录 WARNING 而不会让整个进程崩溃单进程模式的警告如果配置了cluster_only的钩子但以单进程模式运行Puma 会输出警告提示相关逻辑见 lib/puma/configuration.rb。因此本文的 gRPC 配置只适用于集群模式部署。预加载preload与 fork_worker 的影响预加载通过preload_app!开启见 lib/puma/dsl.rb默认为开启。预加载时应用在 master 中加载worker fork 后通过 COW写时复制继承这也是 Puma v7 的默认行为文档中的配置同时兼容两种模式fork_worker若开启fork_worker见 lib/puma/dsl.rbworker 0 会作为次级 master 继续派生其他 worker此时spawn_worker逻辑在 lib/puma/cluster/worker.rb 中执行钩子调用顺序与 master 一致before_worker_fork→ fork →after_worker_fork。如果你在fork_worker模式下运行 gRPC 服务应留意这套二级 fork 链同样会经过这些钩子。测试用例佐证仓库中的测试验证了这些钩子的注册与行为test/test_config.rb 中test_run_hooks_before_worker_fork、test_run_hooks_after_worker_fork、test_run_hooks_before_worker_boot分别验证三个钩子的注册、无 block 时的报错以及单进程模式下的警告test/config/state_file_testing_config.rb 是一个同时使用多个钩子的真实配置样例test/test_integration_cluster.rb 验证了集群模式下before_worker_boot钩子正常执行、不会误报单进程警告。这些测试表明在配置文件中以before_worker_fork do ... end、after_worker_fork do ... end、before_worker_boot do ... end的形式书写钩子块是仓库支持的标准用法。实战要点与注意事项放在集群配置中并确认 worker 数大于 1钩子是cluster_only的只有在workers NN ≥ 2或workers :auto且解析出的可用处理器数量 ≥ 2时才生效。若以单进程运行钩子不会执行并伴有警告gRPC 自然也不会遇到 fork 相关问题macOS 平台务必保留is_mac判断跳过调用不是可选项而是 gRPC 在 macOS 上 fork 行为的硬性要求不要在钩子里做重操作before_worker_fork在 master 中执行若块内耗时过长会拖延整个集群的 worker 派生before_worker_boot若阻塞过久可能触发worker_boot_timeout测试用例 test/test_integration_cluster.rb 展示了相关行为。因此 gRPC 生命周期调用应保持轻量预加载与否均适用本文配置不依赖preload_app!的开关状态文档与源码均确认钩子的执行进程归属在两种模式下一致可放心随集群默认配置使用配合 phased restart / refork 场景集群的 phased restart 与 reforkfork_worker!同样会经历before_worker_fork→ fork →after_worker_fork→before_worker_boot的流程相关实现见 lib/puma/cluster.rb 与 lib/puma/cluster.rb因此这些钩子配置在滚动重启时同样会保护 gRPC 状态的一致性。小结要在 Puma 集群模式下安全使用 gRPC核心是让 gRPC 的GRPC.prefork、GRPC.postfork_parent、GRPC.postfork_child三个方法与 Puma 的before_worker_fork、after_worker_fork、before_worker_boot三个钩子对齐fork 前在 master 中准备、fork 后在 master 中收尾父进程状态、在 worker 中重建子进程状态。仓库源码lib/puma/cluster.rb、lib/puma/cluster/worker.rb完整印证了这套钩子调用链测试用例则保证了配置语法的正确性。把示例配置放入config/puma.rb即可在集群部署中消除 gRPC 的 fork 状态报错。赞分享后端网络【免费下载链接】pumaA Ruby/Rack web server built for parallelism项目地址https://gitcode.com/gh_mirrors/pu/puma点击查看免费下载相关推荐Litestar 生命周期钩子实战before_request、after_request 与 after_response 的完整指南Litestar 生命周期钩子实战before_request、after_request 与 after_response 的完整指南 本文围绕 Lites后端Web框架Rspack插件开发模式钩子与生命周期完全指南Rspack插件开发模式钩子与生命周期完全指南 Rspack作为新一代高性能构建工具其插件系统提供了强大的扩展能力。本文将为初学者详细介绍Rspack插件开开发工具前端OHIF Viewer Mode 生命周期钩子onModeInit / onModeEnter / onModeExit完整指南OHIF Viewer Mode 生命周期钩子onModeInit / onModeEnter / onModeExit完整指南 本指南以 OHIF Vie医疗健康前端音视频上一篇5个实用技巧快速掌握ComfyUI文件名格式化的完整指南下一篇BaiduNetdiskPlugin-macOS百度网盘下载加速与功能优化指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表