我正在运行一个 nginx 服务器,它充当上游 unix 套接字的代理,如下所示:
upstream app_server {
server unix:/tmp/app.sock fail_timeout=0;
}
server {
listen ###.###.###.###;
server_name whatever.server;
root /web/root;
try_files $uri @app;
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
Run Code Online (Sandbox Code Playgroud)
一些应用服务器进程反过来在请求/tmp/app.sock可用时将其拉出。此处使用的特定应用服务器是 Unicorn,但我认为这与此问题无关。
问题是,似乎超过一定量的负载后,nginx 无法以足够快的速度通过套接字获取请求。我设置了多少个应用服务器进程并不重要。
我在 nginx 错误日志中收到了大量这些消息:
connect() to unix:/tmp/app.sock failed (11: Resource temporarily unavailable) while connecting to upstream
Run Code Online (Sandbox Code Playgroud)
许多请求会导致状态代码 502,以及那些不需要很长时间才能完成的请求。nginx 写入队列统计数据徘徊在 1000 左右。
无论如何,我觉得我在这里遗漏了一些明显的东西,因为 nginx 和应用程序服务器的这种特殊配置非常普遍,尤其是对于 Unicorn(实际上这是推荐的方法)。是否有任何需要设置的 linux 内核选项,或者 nginx 中的某些内容?关于如何增加上游套接字的吞吐量的任何想法?我显然做错了什么?
关于环境的其他信息:
$ uname -a
Linux …Run Code Online (Sandbox Code Playgroud) 我们正在 Unicorn 下运行 Ruby on Rails 网络应用程序。我们的应用程序不受 CPU 限制(我们有一个双 Xeon E5645 系统,带有 12 个内核,峰值负载平均值约为 6)。我们最初有 40 个 Unicorn 工作人员,但随着时间的推移,应用程序内存占用量增加。所以,现在我们必须减少工作进程的数量。我认为标准(CPU 内核数 + 1)公式也适用于 Unicorn,但我的同事试图说服我我们应该为每个 CPU 保留更多 Unicorn 实例并提供此链接。然而,我不确定为什么我们需要在空闲的 Unicorn 进程上花费这么多内存。
我的问题是:每个 CPU 内核有多个 Unicorn 实例的原因是什么?是因为 Unicorn 的一些建筑特性吗?我知道忙碌的 Unicorn 进程无法接受新连接(顺便说一句,我们使用 UNIX 域套接字与 Unicorn 实例进行通信),但我认为引入 backlog 正是为了解决这个问题。无论如何,是否有可能克服每个 CPU 规则的 2 到 8 个 Unicorn 实例?
我开始将我们所有的系统转换为使用 upstart 来管理我们的各种应用程序流程。我经常缺少的一件事是能够向进程stop或restart事件发送不同的信号。
例如,我们使用Unicorn运行我们的 Web 进程。Unicorn 有一个很棒的信号处理 API。当我想优雅地重新加载进程时,我向主 pid 发送一个 USR2 信号。为了优雅地关闭它们,我发送了一个 QUIT 命令。TERM(新贵的默认停止信号)构成立即关闭。
另一个例子是使用Resque。为了优雅地关闭一个工人,我向它发送 QUIT 信号。TERM 信号再次导致立即关闭,无论工人的孩子是否被分叉。
新贵是否支持自定义信号?我似乎在任何地方都找不到它,这让我担心我正在使用“错误的工作工具”。
如果我理解 Unicorn 是正确的(特别是从他们的哲学文档中),似乎 Unicorn 真的被设计为在像 nginx 这样的反向代理后面运行。
我的问题是:考虑到我们在顶部有一个 ELB 作为反向代理,我可以从我的 HTTP 堆栈中删除 nginx 吗?
我在初始测试中没有发现任何问题,只是想知道是否有人已经在这方面有经验。
好吧,这是在融化我的大脑。这可能与我不太了解 Upstart 的事实有关。很抱歉,这个问题很长。
我正在尝试使用 Upstart 来管理 Rails 应用程序的 Unicorn 主进程。这是我的当前/etc/init/app.conf:
description "app"
start on runlevel [2]
stop on runlevel [016]
console owner
# expect daemon
script
APP_ROOT=/home/deploy/app
PATH=/home/deploy/.rbenv/shims:/home/deploy/.rbenv/bin:$PATH
$APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production # >> /tmp/upstart.log 2>&1
end script
# respawn
Run Code Online (Sandbox Code Playgroud)
这工作得很好 - 独角兽开始很棒。不好的是,检测到的 PID 不是 Unicorn master 的,而是一个sh进程。这本身也不是那么糟糕 - 如果我没有使用自动独角兽零停机部署策略。因为在我发送-USR2给我的独角兽主人后不久,一个新主人出现了,而旧主人死了……这个sh过程也是如此。所以 Upstart 认为我的工作已经死了,如果我愿意,我不能再用它重新启动restart或停止它stop。
我玩过配置文件,尝试将 -D 添加到 Unicorn 行(如下所示$APP_ROOT/bin/unicorn -c $APP_ROOT/config/unicorn.rb -E production -D:)来守护 Unicorn,然后我添加了该expect daemon …
我主要按照本指南在 Ubuntu (Amazon EC2) 上创建了一个 nginx/unicorn/capistrato 设置。我想一切都设置得像它应该的那样,但是当我启动 Unicorn 时,我在日志中收到(很多)这个错误:
E, [2012-09-08T08:57:20.658092 #12356] ERROR -- : Operation not permitted (Errno::EPERM)
/home/deployer/apps/bridgekalenderen.no/shared/bundle/ruby/1.9.1/gems/unicorn-4.3.1/lib/unicorn/worker.rb:82:in `initgroups'
Run Code Online (Sandbox Code Playgroud)
我看到它与用户的权限有关,但我无法弄清楚我遗漏了什么。如果我使用 sudo(或 rvmsudo,真的)启动服务器,它会很好地启动。
用户具有 sudo 功能,我已经多次修改了该应用程序,因此那里的文件权限应该没问题。/tmp 中的独角兽套接字归部署者用户所有,因此这也不应该是问题。
有没有人知道在哪里看?
更新:
经过一番挖掘,我发现它归结为一个Process.initgroups抛出 EPERM的调用。我已经在 irb 中验证了这一点。我无法弄清楚导致错误的原因。用户可以阅读/etc/group。
我似乎无缘无故地从独角兽工人那里得到间歇性超时,我需要一些帮助来调试实际问题。更糟糕的是,它可以处理大约 10 - 20 个请求,然后 1 个将超时,然后再有 10 - 20 个请求,同样的事情将再次发生。
我创建了一个开发环境来说明这个特定问题,所以除了我的之外没有任何流量。
堆栈是 Ubuntu 14.04、Rails 3.2.21、PostgreSQL 9.3.4、Unicorn 4.8.3、Nginx 1.6.2。
问题
我将详细描述它不起作用的时间。
我通过浏览器请求一个 url。
Started GET "/offers.xml?q%5bupdated_at_greater_than_or_equal_to%5d=2014-12-28T18:01:16Z&q%5bupdated_at_less_than_or_equal_to%5d=2014-12-28T19:30:21Z" for 127.0.0.1 at 2014-12-30 15:58:59 +0000
Completed 200 OK in 10.3ms (Views: 0.0ms | ActiveRecord: 2.1ms)
Run Code Online (Sandbox Code Playgroud)
如您所见,请求在 10.3 毫秒内成功完成,响应状态为 200。
然而,浏览器挂了大约 30 秒,Unicorn 杀死了工人:
E, [2014-12-30T15:59:30.267605 #13678] ERROR -- : worker=0 PID:14594 timeout (31s > 30s), killing
E, [2014-12-30T15:59:30.279000 #13678] ERROR -- : reaped #<Process::Status: pid 14594 SIGKILL (signal 9)> worker=0
I, [2014-12-30T15:59:30.355085 #23533] …Run Code Online (Sandbox Code Playgroud) 我通过这个问题尝试了我在谷歌中找到的所有内容,但是 - 什么都没有。无论如何都行不通。
我的 NGINX 默认:
upstream app {
server unix:/tmp/unicorn.rails.sock fail_timeout=0;
}
server {
listen 80;
root /home/rails/public;
server_name _;
index index.htm index.html;
location / {
try_files $uri/index.html $uri.html $uri @app;
}
location ~* ^.+\.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ {
try_files $uri @app;
}
location @app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
}
}
Run Code Online (Sandbox Code Playgroud)
NGINX 错误日志:
*12 connect() to unix:/tmp/unicorn.myapp.sock failed (2: No such file or directory) while connecting to upstream, client: 46.228.180.65, server: _, request: "GET / …Run Code Online (Sandbox Code Playgroud) 我在 AWS 负载均衡器后面设置了 5 个 t1.micro EC2。
一旦连接到 LB,所有实例都会变慢。即使我直接向实例发出请求(绕过 LB),10 个请求中有 8 个需要超过 30 秒。实例的 CPU 负载似乎不是问题。当我从 LB 中删除其中一个实例时,它的响应很好。一旦它被添加回 LB,请求就会再次变慢。
任何人都可以给我一些线索,说明为什么一旦 LB 连接起来,实例的响应速度就会慢得多?
提前致谢
ruby-on-rails amazon-ec2 amazon-web-services unicorn amazon-elb
我在 Unicorn 上部署了一个生产 Rails 应用程序,前面有 nginx 用于静态文件服务。我现在需要 Varnish 的一些功能,我想知道如何引入它。
有些人把 Varnish 放在前面,而有些人把 nginx 放在前面。我还没有听说有人只使用Varnish 和 Unicorn,但我想这是有效的。
前面有 nginx 的人似乎是为了 gzip 和 SSL 终止而这样做的。SSL 与我的应用程序无关,但 gzip 是。我想清漆很快就会得到它,所以为了简单起见,我可以不用一段时间。
这两种方法还有其他优点/缺点吗?是否有规范的最佳实践布局?
unicorn ×10
nginx ×5
amazon-elb ×2
upstart ×2
amazon-ec2 ×1
http ×1
linux ×1
ruby ×1
socket ×1
tuning ×1
ubuntu ×1
ubuntu-10.04 ×1
ubuntu-14.04 ×1
varnish ×1
web-server ×1