生产环境下如何优雅地重启 Tornado

不得不注意tornado多进程部署的副作用 tornado多进程启动时,采用的是fork的方式。 一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。 子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父... 阅读详情
之前我在《 Tornado 使用经验》一文中,提到了调用 tornado.process.fork_processes() 来提高性能的方法。
在最近的实践中,我发现这样会有些弊端,所以便有了本文。
当然,这些仍然只是我个人的探索而已,并不保证是最佳实践。

首先说下为什么我不再使用 tornado.process.fork_processes() 方法。
网站在上线后,难免会遇到需求更改或修复 bug 的时候,这就免不了要重启 Tornado 进程了。如果使用上述方法的话,会有一个主进程和多个子进程需要 kill,然后再重新运行。简单来说,代码如下:
killall python
nohup python myapp.py >> log/myapp.log &
如果除了 Tornado,还有其他 Python 进程的话,就更麻烦了,需要精确地找到这些进程的 pid,再分别干掉。于是总觉得不太优雅。

后来和知乎的李申申聊天时,问了他这个问题,他推荐我使用  Supervisor。
这玩意折腾了我半天,大致配出这样一个玩意:
[unix_http_server]
file = /tmp/supervisor.sock

[supervisord]
logfile = %(here)s/log/supervisord.log
pidfile = /tmp/supervisord.pid
directory = %(here)s

[supervisorctl]
serverurl = unix:///tmp/supervisor.sock

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[program:myapp]
command = python myapp.py
directory = %(here)s
stdout_logfile = %(here)s/log/myapp.log
stderr_logfile = %(here)s/log/myapp_err.log
然后运行这条命令,就能启动服务了:
supervisord -c supervisord.conf
接着坑爹的事发生了,本以为这样能重启的:
supervisorctl -c supervisord.conf restart myapp
结果却出错了,Supervisor 认为没有启动成功,但其实已经重启好了。

研究了一番才知道,tornado.process.fork_processes() 方法产生的子进程并不会随主进程的退出而退出,而 Supervisor 当然是不知道这些子进程的。(顺带一提,Supervisor 也不能管理守护进程。)
如此一来,如果主进程有什么异常,或者被 kill 掉了,子进程就变成僵尸进程了,确实很有问题。

思索了一番,还是决定自己创建多个进程,分布在多个端口,然后由 nginx 来反向代理到 80 端口。
其中 nginx 的部分配置如下:
http {
    upstream myapps {
        server 127.0.0.1:6666;
        server 127.0.0.1:6667;
        server 127.0.0.1:6668;
        server 127.0.0.1:6669;
    }

    server {
        listen       80;
        server_name  localhost;

        location / {
            proxy_pass_header Server;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For  $remote_addr;
            proxy_set_header X-Scheme $scheme;
            proxy_pass http://myapps;
        }
    }
}
而 supervisord.conf 则改成这样:
[program:myapp]
command = python myapp.py 666%(process_num)d
process_name = %(program_name)s%(process_num)d
numprocs = 4
numprocs_start = 6
directory = %(here)s
stdout_logfile = %(here)s/log/myapp.log
stderr_logfile = %(here)s/log/myapp_err.log
现在 myapp.py 需要接收一个端口参数了,且不再 fork 子进程,代码我就略过了。
此外,如果端口号末位从 0 开始增长的话,是不需要设置 numprocs_start 的,这里只是个人喜好而已。

重启的命令则改成了这样:
supervisorctl -c supervisord.conf restart myapp:*

可是在使用过程中发现,每次重启都会导致网站有大约 10 秒无法访问,这显然不够好。
于是又写了个脚本,依次重启各个进程:
for i in {6..9}
	do supervisorctl -c supervisord.conf restart myapp:myapp$i
done
nginx -s reload

这样基本任何时候网站都是可访问的,不过在重启的过程中,有些没处理完的请求可能会被直接中断掉。
搜索了一番后,找到了这两篇文章可供参考: 《Proper way to stop a Tornado》和 《Tornado server graceful stop》。
简单来说,就是捕捉 TERM 和 INT 信号,使 Tornado 在退出前先停止接收新请求(由 nginx 分发到其他端口),再尝试处理未完成的回调,最后才退出:
def sig_handler(sig, frame):
    logging.warning('Caught signal: %s', sig)
    tornado.ioloop.IOLoop.instance().add_callback(shutdown)

def shutdown():
    logging.info('Stopping http server')
    server.stop() # 不接收新的 HTTP 请求

    logging.info('Will shutdown in %s seconds ...', settings.MAX_WAIT_SECONDS_BEFORE_SHUTDOWN)
    io_loop = tornado.ioloop.IOLoop.instance()

    deadline = time.time() + settings.MAX_WAIT_SECONDS_BEFORE_SHUTDOWN

    def stop_loop():
        now = time.time()
        if now < deadline and (io_loop._callbacks or io_loop._timeouts):
            io_loop.add_timeout(now + 1, stop_loop)
        else:
            io_loop.stop() # 处理完现有的 callback 和 timeout 后,可以跳出 io_loop.start() 里的循环
            logging.info('Shutdown')
    stop_loop()

if __name__ == '__main__':
    port = int(sys.argv[1])
    if settings.IPV4_ONLY:
        import socket
        sockets = bind_sockets(port, family=socket.AF_INET)
    else:
        sockets = bind_sockets(port)
    server = HTTPServer(application, xheaders=True)
    server.add_sockets(sockets)

    signal.signal(signal.SIGTERM, sig_handler)
    signal.signal(signal.SIGINT, sig_handler)

    tornado.ioloop.IOLoop.instance().start()
    logging.info('Exit')
试了下以这种方式重启,耗时几秒的请求也不会被强制中断;100 个并发的压力测试下,重启过程中也没有任何失败请求出现。
不过如果你的 settings.MAX_WAIT_SECONDS_BEFORE_SHUTDOWN 设得超过 10 秒,就要相应地增加 supervisord.conf 中 stopwaitsecs 的时间,否则会被强行杀掉的。

最后顺带一提,修改了 Supervisor 的配置,也可以用 supervisorctl reread 来重新载入,或用 supervisorctl reload 来载入新配置并重启所有子进程。直接运行 supervisorctl 的话,可以进入命令行模式操作。你可能还会对下列文章感兴趣:

Tornado框架深度解析:从异步原理到高并发Web服务实战 异步编程是现代高性能Web服务的核心技术范式,其核心原理在于通过事件循环机制实现非阻塞I/O操作,从而在单线程内高效处理海量并发连接。这种技术价值在于能够以更少的系统资源开销支撑更高的并发吞吐量,尤其适用于WebSockets、实时数据推送等需要持久连接的场景。Tornado作为Python生态中成熟的高性能Web框架,其内置的IOLoop事件驱动引擎和原生的async/await语法支持,使得开发者能够以同步的代码风格构建异步应用,平滑地从传统同步框架迁移。本文通过一个实时监控面板的完整项目示例,深入探讨 阅读详情

相关推荐

ML模型服务化实战:从Notebook到高可用生产环境

机器学习模型服务化是将训练好的模型转化为稳定、可观测、可运维的在线API的关键过程。其核心在于跨越Notebook开发与生产环境之间的鸿沟——前者追求快速验证,后者要求强契约、低延迟、容错与持续可观测。技术价值体现在通过数据契约校验、分层超时控制、业务级熔断和特征漂移监控,显著提升模型服务的SLA与故障自愈能力。典型应用场景包括实时风控、推荐系统、IoT预测性维护等对延迟与稳定性敏感的工业级AI系统。本文聚焦真实落地中高频出现的GPU超时陷阱、Pydantic语义歧义、HTTP 200型软失败等硬茬问题,结

weixin_33947521的博客 331

Linux信号signal介绍,signal()函数,sigaction()函数 退出while True:

转https://blog.youkuaiyun.com/gx19862005/article/details/17241631 https://blog.youkuaiyun.com/qq_16583687/article/details/78163015 https://www.cnblogs.com/alexyuyu/articles/3853583.html 信号(signal)是一种进程间通信机制,它给应...

weixin_42205776的博客 1016

从Notebook到生产环境:机器学习模型服务化实战指南

机器学习模型服务化是将训练好的算法转化为稳定、可监控、可扩展的在线API的关键过程。其核心原理在于解耦模型逻辑与业务系统,通过容器化打包、标准化接口(如gRPC/REST)、微服务架构和全链路可观测性实现工程闭环。技术价值体现在提升模型迭代效率、保障线上稳定性、支持灰度发布与快速故障定位。典型应用场景包括风控模型实时评分、推荐系统在线推理、NLP服务化部署等。本文聚焦真实生产环境下的Triton模型服务、Kong网关治理、Feast特征一致性及Prometheus黄金指标监控等落地细节,覆盖Docker镜像

weixin_33933118的博客 477

生产环境优雅的重启基于Nginx、Tornado的Web服务进程

Nginx是一个高效的Web服务器及代理服务器,Tornado是一个基于epoll的异步Web开发框架,通常使用Nginx做为Web服务器时,都会以FastCGI模式,而我们从开发、调试、运维的角度考虑,使用了反向代理的模式,同时Nginx可以做一些特殊业务和负载均衡的处理。 其实反向代理模式很简单,Nginx监听在80端口,做为Web服务端口,而Tornado的Web服务进程监听...

dianfu2892的博客 454

webapi .net core8.0配置使用Token权限认证

本人在网上找了很多版本,不是太复杂就是不行。

m0_74824592的博客 1760

Cursor Cloud Agent:云原生编程工作流的底层重构

编程工作流正从本地计算范式转向云原生执行范式。Cloud Agent 本质是将代码理解、生成、执行与调试等核心能力下沉至隔离、可控、按需分配的云端虚拟机,通过 Firecracker 微虚拟机实现亚秒级启动,并依托上下文快照、环境镜像化和内核级沙箱保障一致性、算力弹性与数据安全。这一范式突破了传统本地 AI 编程助手在环境依赖、调试能力与企业合规上的根本局限,使 IDE 从编辑工具升维为分布式开发指挥中心。本文深入解析其运行机制与工程落地实践。

weixin_34354173的博客 337

tornado之多进程服务

tornado多进程开启 在前文中简单介绍过tornado的基本使用。tornado默认启动的是单进程,启动方式如下: if __name__ == "__main__": application = tornado.web.Application([(r"/", MainHandler)]) # application.listen(8888) server = HTTPServer(application) server.listen(8888) tornado.

xiaoyi52的专栏 2735

使用Gitlab 搭建私有镜像仓库(外置Nginx)

为了让团队尽快使用Gitlab的CI进行工作,必须做好Gitlab的初始化工作,大家都知道拉取镜像由于某些原因,会比较慢,因此构建自己的私有镜像仓库就成为了关键的一步。当然私有镜像仓库的搭建有很多种方式,这里直接使用Gitlab提供的镜像仓库功能。一揽子解决方案比较香。gitlab真的越来越好用了,有了这个镜像仓,也没必要再使用三方的镜像仓库了。Devops 真好用!

网尘的技术专栏 1829

实现不重启服务的情况下改变tornado的工作进程数

要实现不重启服务的情况下改变tornado 的进程数,那得先理解tornado是怎么管理多进程的。 其实很简单,主要看process.py的fork_processes函数,了解子进程的创建过程。 首先启动子进程。根据传入的进程数依次启动调用start_child函数fork一个进程,如果在子进程的上下文中,则改变全局变量task_id,并且返回task_id,退出fork_processes...

Gikieng的奋斗路 1864

1篇1章3节:R 语言的产生与发展轨迹(更新2024/08/14)

药物的研究阶段包括靶标确定、生物学模型建立、新化学实体的发现和优化新化学实体四个关键环节。每个环节都在药物研发过程中发挥着至关重要的作用。通过科学严谨的方法和技术手段,研究人员能够在药物研发过程中不断探索和优化,从而发现和开发出具有高效、安全性的候选药物,为疾病治疗提供更多的选择和希望。

MD Code 2664

渗透测试工具之Sliver

攻击者需要将生成的植入物传输到目标系统,并执行它。C2 框架的架构与 Metasploit(如 Meterpreter)类似,但更专注于。(Red Teaming)中常见的攻击工具之一,攻击者利用 C2 服务器。组成,二者共同实现 C2 服务器与受控设备的通信。植入物(Implants)是 Sliver 生成的。抓包分析时,可以看到所有数据都是加密传输的。和**监听器(Listeners)**功能。Sliver 支持多种通信协议,如。随着安全防御的不断提升,企业应加强。进行通信,数据仍然是加密的。

idlecloud0105的博客 1935

Tornado异步Web框架实战:从零构建百万级并发实时服务

本文分享多年Python开发中使用Tornado构建高并发系统的实战经验。Tornado凭借非阻塞IO和协程机制,单机可支撑5万+长连接,特别适合实时通信场景。文章详细解析事件循环原理、协程最佳实践,并给出WebSocket聊天系统完整实现,包括连接管理、消息限流等核心代码。通过性能对比数据展示Tornado在长连接场景的优势(5000连接仅85MB内存),并提供连接池优化、内存泄漏排查等生产级解决方案。关键建议:合理技术选型,Tornado适合实时系统但需注意CPU密集型任务限制,配合监控和优雅重启保障

七夜zippoe的博客 706

机器人控制基础:伺服驱动器的泄放电阻

摘要:伺服驱动器泄放电阻用于消耗电机减速或制动时产生的再生电能,防止母线电压过高损坏元件。其核心作用是将多余电能转化为热能,规避硬件损坏和停机风险。选型需关注功率、阻值和封装三大参数,功率应匹配再生能量,阻值需符合驱动器要求,封装应满足散热需求。可通过动态监测母线电压或静态检测电阻阻值来判断其是否正常工作。

start_up_go的博客 381

Tigo平滑部署方案:Endless与Overseer的完美应用

Tigo是一款用Go语言开发的web应用框架,API特性类似于Tornado并且拥有比Tornado更好的性能。在实际生产环境中,平滑部署是保证服务持续稳定运行的关键,本文将详细介绍如何利用Tigo框架内置的Endless和Overseer两种方案实现零 downtime 部署。 ## 为什么需要平滑部署? 传统的服务重启方式会导致短暂的服务不可用,影响用户体验和业务连续性。平滑部署能够在不中

gitblog_00166的博客 1050

Dify 实战:使用 Firecrawl 插件高效爬取微信公众号文章

本文介绍了如何利用Dify平台和Firecrawl插件构建微信公众号文章自动化采集系统。Dify作为开源LLM应用开发平台,结合Firecrawl的智能网页爬取能力,可轻松实现文章爬取、清洗和结构化存储。文章详细讲解了环境部署、插件安装以及工作流创建过程,通过可视化节点操作即可完成从URL输入到Markdown格式输出的全流程。该方案无需复杂代码,能有效解决反爬、动态渲染等问题,适用于知识库构建、模型训练等场景,显著提升开发效率。

SmartSi 1824

基于Multisim的三相桥式全控整流电路建模、仿真与综合分析

本文基于Multisim 14.2平台,系统研究了三相桥式全控整流电路的建模与仿真方法。首先阐述了电路拓扑结构和工作原理,建立了数学模型。重点介绍了在Multisim中搭建主电路、设计六脉冲触发系统(含两种实现方案)的关键步骤,以及参数设置技巧。通过仿真分析了不同负载(阻性、阻感性)和触发角(0°-90°)下的输出特性,包括电压波形、电流谐波等性能指标。研究为电力电子教学提供了直观的仿真范例,并探讨了模型改进方向与实际工程应用价值。

huanghm88的专栏 353

Tornado异步Web框架深度解析:从核心原理到高并发实战

异步编程是现代高性能Web应用的核心技术之一,它通过非阻塞I/O模型,允许单个线程同时处理多个网络连接,从而显著提升系统的并发处理能力。其核心原理在于事件循环机制,该机制持续监听I/O事件并调度相应的回调函数或协程执行,避免了传统同步模式中线程阻塞导致的资源浪费。这一技术价值在于能够以更少的资源开销支撑更高的并发连接数,特别适用于实时聊天、消息推送、API网关等I/O密集型场景。Tornado作为Python生态中成熟的异步Web框架,其一体化异步设计从底层网络库到HTTP服务器均提供了原生支持,结合asy

weixin_34268579的博客 1459

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

从Notebook到生产环境:机器学习模型工程化落地实战

机器学习模型部署不是简单启动API服务,而是涵盖模型打包、服务编排、特征一致性、全链路监控与CI/CD交付的系统性工程。其核心在于解决数据漂移、概念漂移、推理性能瓶颈及线上稳定性等真实问题。关键技术包括Docker确定性镜像构建、Triton推理服务器选型与调优、Feast特征存储保障线上线下一致性,以及基于Prometheus+Grafana+Evidently的多层级监控体系。本文聚焦MLOps落地中的关键决策点与魔鬼细节,覆盖Kubernetes集群搭建、gRPC服务治理、GPU资源管控及自动化发布流

weixin_30629653的博客 413

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

从Notebook到生产环境:机器学习模型落地的工程化实践

机器学习模型部署不是简单启动API服务,而是涉及模型打包、服务编排、实时特征供给、数据漂移监控与弹性降级的一整套工程体系。其核心原理在于将‘可运行’升级为‘可运维’——通过Docker确定性构建、Triton推理服务器优化GPU利用率、Redis支撑毫秒级特征读取、Evidently检测数据分布偏移,实现模型在高并发、数据漂移、依赖故障等真实场景下的稳定服役。技术价值体现在降低运维成本、提升推理吞吐、保障业务连续性;典型应用场景包括信贷风控、实时推荐与图像识别等需低延迟响应的线上服务。本文聚焦MLOps落地

weixin_30825581的博客 398

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

从Notebook到生产环境:构建高可用机器学习服务的完整实践

机器学习模型部署不是简单启动API,而是涉及模型服务化、可观测性、弹性伸缩与安全合规的系统工程。其核心原理在于将模型封装为可版本化、可监控、可回滚的独立服务单元,通过容器化、标准化接口(如gRPC/Protobuf)和分层架构实现业务解耦。技术价值体现在稳定性提升(如Triton动态批处理将GPU利用率从30%提至85%)、运维效率跃迁(K8s滚动更新+健康探针保障零停机)及成本可控(基于Prometheus指标的GPU自动伸缩)。典型应用场景包括实时风控、个性化推荐与A/B测试驱动的模型迭代。本文聚焦真实

coolmsn8786的博客 360

生产级机器学习模型部署实战:从Notebook到K8s+Triton

机器学习模型部署不仅是API封装,更是覆盖模型服务化、可观测性、弹性扩缩与故障隔离的全生命周期工程实践。其核心在于解决数据漂移、特征不一致、GPU资源争用及监控盲区等真实问题。关键技术包括Triton推理服务器的动态批处理与热更新能力、Docker镜像依赖锁定保障可重现性、分层架构实现模型与业务解耦,以及基于Prometheus+Alertmanager的SLO驱动告警体系。本文聚焦MLOps落地中的高频痛点——如模型结果不一致、推理延迟突增、上线后效果衰减等,结合Kubernetes、Flink、Evid

weixin_33861800的博客 582

机器学习模型上线后的真实挑战:从Notebook到生产环境的系统性风险防控

机器学习模型部署不是终点,而是进入真实业务场景的起点。在金融、电商等高敏领域,模型性能受数据管道稳定性、特征新鲜度、服务协议兼容性、熔断降级机制等系统性因素深刻影响。延迟预算需拆解至整个决策链路,而非仅关注模型推理;监控必须覆盖基础设施、数据质量、模型表现与业务影响四层,并支持子群体漂移检测;治理核心在于可追溯性、变更控制与责任明确。本文聚焦MLOps中易被忽视的‘脏活’——集成验证、失败模式设计、自动化闭环响应,助力模型从静态算法蜕变为可信、可控、可演进的业务决策组件。

weixin_34377919的博客 418

从Notebook到生产环境:机器学习模型服务化落地实战

机器学习模型服务化是将训练完成的模型转化为稳定、可扩展、可观测API的关键过程。其核心原理在于打破Notebook探索性开发与生产环境确定性要求之间的根本矛盾,通过契约驱动(如Pydantic Schema)、异步高性能框架(FastAPI/Uvicorn)、容器化(Docker/K8s)及特征工程代码化等手段,保障服务的可重复性、类型安全与资源可控性。技术价值体现在降低线上故障率、加速业务集成、支撑A/B测试与持续监控。典型应用场景包括实时推荐、风控评分、智能客服等需低延迟响应的在线推理系统。本文聚焦于模

weixin_34367257的博客 488

从Notebook到生产环境:机器学习模型落地实战指南

机器学习模型部署不是简单启动API服务,而是涉及环境一致性、服务韧性、特征管理与持续监控的系统工程。其核心原理在于将模型生命周期从‘可运行’升级为‘可运维’,通过Docker容器化保障依赖确定性,Triton推理服务器提升GPU利用率与热更新能力,并借助Feast实现特征血缘追踪与实时漂移检测。技术价值体现在降低线上故障率、缩短问题定位时间、支撑AB测试与自动回滚等关键运维能力。典型应用场景包括电商推荐、金融风控、内容分发等高并发、低延迟、强稳定性要求的业务系统。本文聚焦真实世界中的MLOps落地细节,覆盖

wangqiaowqo的专栏 355
上一篇: 算法复杂度——时间复杂度和空间复杂度
下一篇: 复习数据结构和算法的好网站【python版】
wilelm
博客等级 码龄16年 5粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值