读 gunicorn 文档有感:原来日志丢失不是玄学
前几天服务日志又丢了,这次没有硬着头皮瞎试,而是把 gunicorn 的官方文档翻了一遍,记录一下几个以前没注意到的点。
一是 worker 的生命周期比我想的短。我一直以为 master 起来后 worker 就一直活着,实际上 worker 会定期被 master 重启(还有 max_requests 这种主动回收的配置)。所以任何存在 worker 内存里的东西——比如我在模块顶层塞的一个简易缓存——都会不定时被清空。以前遇到"缓存偶尔失效,过一会又好了",其实就是 worker 被回收了,跟代码没关系。
二是日志设计的思路。文档里专门有一节讲 logging,推荐的做法是应用里只写日志事件,输出交给 gunicorn 统一管理。我之前在应用里自己配 handler、自己开文件,等于跟框架抢活干,多 worker 各开各的文件句柄,缓冲互相覆盖,丢日志就是这么来的。理解了"谁负责输出"这个分界之后,之前那个"日志时有时无"的问题一下子就说得通了。
三是 preload 选项的利弊。开了 preload,代码在 fork 前加载,省内存也启动快,但坑是如果应用在 import 时建立了数据库连接,fork 出来的 worker 会共享同一个连接,出一些很诡异的问题。文档建议 import 阶段只放纯代码,连接类的资源等 worker 起来再建。回头看我自己写的启动代码,确实把连接池初始化放在了模块顶层,属于典型的反面教材。
整体感受是,很多以前靠猜的问题,文档里其实都写了,只是以前遇到问题第一反应是搜报错信息,很少想到把文档从头读一遍。这次认真读下来,等于把部署这块的知识缺口补了一块,后面打算把 uwsgi 的文档也照这个方式过一遍。
- 点赞
- 收藏
- 关注作者
评论(0)