为什么即使在升级服务器后,错误 502 仍时不时地出现在我的网站上?

Why does Error 502 show every now and then on my site even after upgrading my server?

我尝试检查和阅读有关此错误的文章,但直到现在我都无法解决此问题。我使用 Cloudflare 来保护我的网站。如何修复错误 502 Bad Gateway

我的站点目前在 Digital Ocean 上 运行(PHP7.2 - Codeigniter 3、MySQL 和 Nginx),我最近升级了我的服务器,因为我认为这可能是由于我的网站流量。我以前用 $5 droplet,现在我用 $15(2 个 vCPU 和 2GB Ram)。

Nginx 错误日志:https://pastebin.com/XjGGjNPL

配置如下:

server {
        listen 80;
        root /var/www/<site_dir>;
        index index.php index.html index.htm index.nginx-debian.html;
        server_name <domain>;

        #location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
        #        expires max;
        #        log_not_found off;
        #}

        location / {
                try_files $uri $uri/ /index.php;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        }

        location ~ /\.ht {
                deny all;
        }

        # Deny for accessing codes
        location ~ ^/(application|system|tests)/ {
            return 403;
        }
}

server {
        listen 80 default_server;
        server_name _;
        return 404;
}

我使用 htop 检查了我的资源

对此有什么建议吗?

所以我检查了日志以验证问题所在。我不喜欢服务器,所以我在旋转 droplet 时将其保留为默认值。

检查 /var/log/php7.2-fpm.log 后显示:

'WARNING: [pool www] server reached pm.max_children setting (5), consider raising it'

于是我按照这个回答提出来:https://serverfault.com/a/844462

pm = ondemand
pm.max_children = 4000
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_requests = 0

我还通过提高工作进程优化了 php-fpm。

worker_processes  2; #my server has 2 vCPU cores
worker_connections  1024;

(https://www.if-not-true-then-false.com/2011/nginx-and-php-fpm-configuration-and-optimizing-tips-and-tricks/)

到目前为止,每当我的服务器遇到网络请求高峰时,这都解决了我的问题

So I raised it according to this answer: https://serverfault.com/a/844462

并且轻松地让 Internet 上的任何人都能立即关闭您的网站。

在任何情况下链接的答案都是好的,但我会在下面解释为什么它对您的特定服务器规格不好。

pm.max_children = 4000

连同pm = ondemand,这意味着随着流量的到来足够快,PHP-FPM 将继续分叉越来越多的进程,直到最多有 4k 个子进程。典型的 PHP-FPM 工作进程平均消耗 80 MB 的 RAM。将其乘以 4k,仅此设置,服务器就需要 320 GB (!!!) RAM。

pm.max_requests = 0

现在这个。它控制给定的 PHP-FPM worker 在被回收并替换为新请求之前将处理多少请求。您通常 总是 想要在某个时候回收 PHP-FPM 工作进程,因为 PHP 本身及其扩展本身就是一个内存泄漏倾向的软件。因此,如果没有进行回收,那么每个进程的平均 80 MB 很可能会随着时间的推移变得越来越多 "fat",因此即使 320 GB 的 RAM 也不足以处理流量。

任何人怎么能用这些设置杀死网站:通过使用任何能够连续发出许多请求的软件(甚至不需要并行),从命令行上的 curl 到GUI 工具,如 SEO Frog Spider。由于他们连续发出许多请求,从而导致 PHP-FPM worker 的几乎无限(最多 4k)分叉,最终您的服务器一旦达到内存不足的情况,将开始终止进程​​以尝试获得空闲 RAM .

这种杀戮的典型选择是MySQL进程,一旦它被内核牺牲——你的网站就停止工作了。

至于如何以 合理的方式配置 PHP-FPM,您需要实际测量 PHP-FPM 工作进程的数量"weights" 以获得正确的 max_children 设置。

但是,您可以通过简单的计算来解决问题,并根据需要进一步微调。假设我们将规定的平均值考虑为 80 MB。取出您的服务器 RAM 并减去 MySQL "eats" 以及任何其他住宅程序。假设这是 500 MB。所以你还有 1500 MB 留给 PHP-FPM worker。

1500 / 80 = 剩下 pm.max_children=19

当然,您需要:

  • pm.max_requests调整为最多10000(最安全的是500甚至更低,例如100)。从不 0(这意味着不回收)
  • 配置一些交换,以防万一即使是那 19 个 PHP 工作进程也会导致内存不足的情况,您的网站仍然在线。

当您随着时间的推移监视交换使用情况时(free -m 是您的朋友),您可以了解进一步提高 PHP-FPM workers 是否安全,但如果有的话,在现代框架中,每个工作人员可能有 80 MB 多一点,您可能需要降低。

但这就是正确获得 PHP-FPM 的方法。真正的解决方案是在您的应用程序内外进行高效缓存:

内部:Codeigniter 缓存

外部:Varnish、NGINX FastCGI 缓存

更远的地方:为 HTML 输出启用 Cloudflare 缓存(缓存所有内容策略)。