![在请求到达服务器之前突然开始经历漫长的等待时间](https://linux22.com/image/678971/%E5%9C%A8%E8%AF%B7%E6%B1%82%E5%88%B0%E8%BE%BE%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B9%8B%E5%89%8D%E7%AA%81%E7%84%B6%E5%BC%80%E5%A7%8B%E7%BB%8F%E5%8E%86%E6%BC%AB%E9%95%BF%E7%9A%84%E7%AD%89%E5%BE%85%E6%97%B6%E9%97%B4.png)
我们的 Web 应用每天的浏览量为 2 万到 3 万次,并且还在稳步增长。大约 4 天前,我们突然发现 HTML 加载前需要等待 30 到 40 秒,而前一天的页面加载时间仅为 1 秒。
在 New Relic Synthetics 中,这些时间仅显示为“等待”。通过监控 nginx 日志,我可以看到这些时间对应于传入请求到达服务器所需的时间。
这是一个在 2GB droplet 上运行 Unicorn 和 Nginx 的 Rails 应用。我之前根据这篇文章优化了我的 Unicorn 配置:https://www.digitalocean.com/community/tutorials/how-to-optimize-unicorn-workers-in-a-ruby-on-rails-app,我们的内存使用率往往徘徊在 50% 左右。尽管如此,我还在上面的同一篇日志输出中注意到了一堆这样的内容:
2016/03/15 06:52:36 [error] 9460#0: *1110377 connect() to unix:/tmp/unicorn.streamfeed.sock failed (11: Resource temporarily unavailable) while connecting to upstream, client: 66.226.75.13, server: streamfeed.com, request: "GET /watch HTTP/1.1", upstream: "http://unix:/tmp/unicorn.streamfeed.sock:/watch", host: "streamfeed.com", referrer: "http://google.com/"
在没有更好的想法的情况下,我认为这可能意味着我们获得的流量超过了我们的 Unicorn 工作者数量所能处理的流量(我们的流量一直在稳步增长,前几天我们刚刚度过了有史以来最忙碌的一天)。所以我将我们的 droplet 升级到 4GB,并将 Unicorn 工作者的数量增加了一倍,但这并没有解决问题——有时我会看到这 11 个错误,有时是 110 个。
这不是我代码优化的问题——请求最终通过后,相关操作仍然需要 1-2 秒才能实际处理(根据 New Relic),包括任何数据库查询。延迟发生在请求到达服务器之前。我们的两个 droplet(应用服务器和数据库)的 CPU 使用率均低于 50%,内存使用率也是如此。Unicorn 日志中没有错误。我尝试了在线找到的每一种调整/优化 nginx 和 unicorn 的方法,但没有任何变化——如果有的话,加载时间会继续增加。我们现在看到处理请求需要等待 40-50 秒,这实际上意味着我们的网站瘫痪了。在这种情况开始发生之前,我很长时间没有更改任何相关设置或代码。我已经将相关文件回滚到这种情况开始发生时的状态,因为我所做的任何调整/更改都没有任何变化。我迫切希望我们的网站再次运行……希望有人能帮忙。
nginx.conf:
upstream unicorn {
server unix:/tmp/unicorn.streamfeed.sock fail_timeout=0;
}
server {
server_name www.streamfeed.com;
rewrite ^(.*) http://streamfeed.com$1 permanent;
}
server {
listen 80 default_server deferred;
# server_name example.com;
server_name streamfeed.com;
root /home/deployer/apps/streamfeed/current/public;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
location ~* \.(js|css)$ {
add_header Access-Control-Allow-Origin *;
}
}
location ^~ /fonts/ {
gzip_static on;
expires max;
add_header Cache-Control public;
location ~* \.(ttf|ttc|otf|eot|woff|svg|font.css)$ {
add_header Access-Control-Allow-Origin *;
}
}
try_files $uri/index.html $uri @unicorn;
location @unicorn {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://unicorn;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 30;
}
独角兽.rb:
root = "/home/deployer/apps/streamfeed/current"
working_directory root
pid "#{root}/tmp/pids/unicorn.pid"
stderr_path "#{root}/log/unicorn.log"
stdout_path "#{root}/log/unicorn.log"
listen "/tmp/unicorn.streamfeed.sock"
worker_processes 11
timeout 60
config.ru:# 此文件由基于 Rack 的服务器用来启动应用程序。
if ENV['RAILS_ENV'] == 'production'
require 'unicorn/worker_killer'
max_request_min = 500
max_request_max = 600
# Max requests per worker
use Unicorn::WorkerKiller::MaxRequests, max_request_min, max_request_max
oom_min = (240) * (1024**2)
oom_max = (260) * (1024**2)
# Max memory size (RSS) per worker
use Unicorn::WorkerKiller::Oom, oom_min, oom_max
end
require ::File.expand_path('../config/environment', __FILE__)
run Rails.application