我正在运行一个 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