delphi 内存泄漏检测工具_go内存泄漏_性能测试内存泄漏

我曾经开发过的几个大型Django应用程序都在某个时候出现了内存泄漏。Python进程缓慢地增加它们的内存消耗,直到崩溃。这一点也不好玩。即使自动重新启动进程之后,仍然会有一些宕机问题。

Python中的内存泄漏通常发生在无限增长的模块级变量中。这可能是一个具有无穷大maxsize的lru_cache变量,也可能是一个在错误范围内声明的简单列表。

泄漏也不是只有发生在您自己的代码中才会影响您。例如,看看BuzzFeed的Peter Karp写的这篇优秀的文章,他在Python的标准库中发现了一个内存泄漏(已经修复了!)

解决方法

下面的解决方法都会在执行了很多请求或任务之后重新启动worker进程。这是一个清除任何潜在的无限积累的Python对象的简单方法。如果您的web服务器、队列worker或类似的应用程序有此能力,但还没有被功能化,请告诉我,我会添加它!

即使您现在还没有看到任何内存泄漏,添加这些解决方法也会提高您的应用程序的弹性。

Gunicorn

如果您正在使用Gunicorn作为您的Python web服务器,您可以使用–max-requests设置来定期重启worker。与它的兄弟–max-requests-jitter配合使用以防止所有worker同时重启。这有助于减少worker的启动负载。

例如,在最近的一个项目中,我将Gunicorn配置为:

对于此项目的流量水平、worker数量和服务器数量来说,这将大约每1.5小时重新启动worker。5%的浮动足以消除重启负载的相关性。

Uwsgi

如果您正在使用uwsgi,您可以使用它类似的max-requests设置。此设置在很多次请求之后,也会重新启动worker。

例如go内存泄漏,在以前的一个项目中,我在uwsgi.ini文件中像这样使用了这个设置:

性能测试内存泄漏_go内存泄漏_delphi 内存泄漏检测工具

Uwsgi还提供了max-requests-delta选项用于添加其他浮动。但由于它是一个绝对数字go内存泄漏,所以配置起来要比Gunicorn更麻烦。如果您更改了worker的数量或max-requests的值,那您就需要重新计算max-requests-delta来保持您的浮动在一个特定的百分比。

Celery

Celery为内存泄漏提供了几个不同的设置。

首先是worker_max_tasks_per_child设置。这将在worker子进程处理了许多任务之后重新启动它们。此设置没有浮动选项,但是Celery任务的运行时间范围很广,所以会有一些自然的浮动。

例如:

或者您正在使用Django设置:

100个任务比我上面建议的web请求数要小一些。在过去,我最终为Celery使用了较小的值,因为我在后台任务中看到了更多的内存消耗。(我想我还在Celery本身中遇到了内存泄漏。)

您可以使用的另一个设置是worker_max_memory_per_child。这指定子进程在父进程替换它之前可以使用的最大千字节内存。它有点复杂,所以我还没用过。

如果您确实使用了worker_max_memory_per_child设置,那么您可能应该将其计算为总内存的百分比,并除以每个子进程。这样,如果您更改了子进程的数量或您的服务器的可用内存,它将会自动扩展。例如(未测试):

这使用psutil来查找整个系统内存。它将最多75%(0.75)的内存分配给Celery,只有在服务器是一个专用Celery服务器的情况下您才会需要它。

跟踪泄漏

在Python中调试内存泄漏是很不容易的,因为任何函数都可以在任何模块中分配全局对象。它们也可能出现在与C API集成的扩展代码中。

我用过的一些工具:

更新 (2019-09-19): Riccardo Magliocchetti在Twitter上提到,pyuwsgimemhog项目可以解析uwsgi日志文件,并告诉您哪些路径正在泄漏内存。很简洁!

其他一些有用的博文:

结束语

祝您内存泄漏更少!

—Adam

英文原文:

译者:野生大熊猫

———END———
限 时 特 惠:本站每日持续更新海量各大内部创业教程,一年会员只需128元,全站资源免费下载点击查看详情
站 长 微 信:jiumai99

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注