php - Heroku PHP 立即消耗所有内存
问题描述
我有一个 Heroku 1X 测功机,它在重新启动时会立即消耗所有内存。
这是日志中的重启:
2020-05-18T16:57:54.119229+00:00 app[web.1]: Stopping php-fpm...
2020-05-18T16:57:54.119814+00:00 app[web.1]: Stopping httpd gracefully...
2020-05-18T16:57:54.121897+00:00 app[web.1]: Stopping httpd...
2020-05-18T16:57:54.131154+00:00 app[web.1]: Shutdown complete.
2020-05-18T16:57:54.194178+00:00 heroku[web.1]: Process exited with status 143
2020-05-18T16:57:57.194751+00:00 app[web.1]: Detected 536870912 Bytes of RAM
2020-05-18T16:57:57.231186+00:00 app[web.1]: PHP memory_limit is 4M Bytes
2020-05-18T16:57:57.245920+00:00 app[web.1]: Starting php-fpm with 128 workers...
2020-05-18T16:57:57.386605+00:00 app[web.1]: Starting httpd...
2020-05-18T16:57:58.220510+00:00 heroku[web.1]: State changed from starting to up
我的 procfile 只是:
web: vendor/bin/heroku-php-apache2
我的 .user.ini 是:
memory_limit = 4M
这些代码都没有设置为在后台运行,它只是一个处理请求的 API。然而,它会立即消耗最大内存并抛出 R14 错误,有 0 个请求进入。https://share.getcloudapp.com/GGukb5QZ
有人知道会发生什么吗?
解决方案
这是您需要阅读的文档:https ://devcenter.heroku.com/articles/php-concurrency
你用你的评论回答了这个问题“我可以通过增加 memory_limit 来减少内存下限(这样它就不会在启动时占用所有内存)。”
TL;DR,Heroku 说:
- 我有多少内存?(您有 512MB)
- 每个 PHP 进程的最大内存量(您设置为 4MB)
- 将两者分开并启动那么多工人(你得到 128)
这个计算忽略了运行 HTTP 和其他进程的开销。正如该页面所阐明的那样,“故意选择这些默认值以不留下任何“空间”……因为应用程序极不可能消耗其全部内存限制……这意味着默认情况下测功机略微超额订阅。”
通常,如果您将限制设置为 128MB = 4 个工作进程,这并不重要:
- 每个 php 进程 128MB,但平均只使用 100MB(这是巨大的 :))
- 每个 http 进程添加 1MB = 101MB
- 乘以 4 = 404MB
- 添加日志记录、日志轮换、SSH 和所有其他数百个进程的开销,比如说 40MB
- 总计 = 404 + 40 = 444MB < 512MB。
- 如果每个进程仅使用 3.5MB = 大量备用。
- 耶!
但是,您有:
- 每个 php 进程 4MB,平均仅使用 3.5MB(检查PHP 中的 memory-get-peak-usage)
- 每个 http 进程添加 1MB = 4.5MB
- 乘以 128 = 576MB
- 添加日志记录、日志轮换、SSH 和所有其他数百个进程的开销,比如说 40MB
- 总计 = 576 + 40 = 616MB > 512MB。
- Heroku 开始内存管理。
您需要找到合适的平衡点,例如设置为 8M = 64 个进程,就像您所做的那样。
注意:关于开销和 HTTP 进程的陈述是一种简化,仅用于说明目的。
配置 FPM 有点像噩梦,因为您可以运行多个池,每个池都有初始工作人员和备用工作人员。https://www.php.net/manual/en/install.fpm.configuration.php
Heroku 试图为您简化这一点。
推荐阅读
- android - 在 dispose() 之后调用 setState():_StatefulBuilderState#09642(生命周期状态:已失效,未安装)
- javascript - 如何仅滚动固定区域,而不是整个页面 onClick?
- python - json到pandas数据框,第一列值在所有行中都相同
- kubernetes - k8s - pod可以ping外部IP,但不能wget?
- linux - 如何创建一个从 csv 文件读取输入的 bash 脚本
- google-bigquery - BigQuery 验证器检测到错误,但 Query 成功运行
- devise - 典狱长的自定义策略没有被调用
- javascript - 如何命令我的机器人锁定当前频道?
- r - 如何按 R 中的线分割/剪辑多边形?
- bluetooth-lowenergy - 使用 BLE 查询结构数组的最佳方法