Как я уже упоминал пару недель назад, я работал над учебником о том, как продумывать проблемы на графиках, и, поскольку это приложение для Sinatra, я подумал, что thin будет неплохим выбором для веб-сервера .
В моей первоначальной настройке у меня был следующий конфигурационный файл nginx, который использовался для прокси-запросов на thin:
/etc/nginx/sites-available/thinkingingraphs.conf
upstream thin { server 127.0.0.1:3000; } server { listen 80 default; server_name _; charset utf-8; rewrite ^\/status(.*)$ $1 last; gzip on; gzip_disable "MSIE [1-6]\.(?!.*SV1)"; gzip_types text/plain application/xml text/xml text/css application/x-javascript application/xml+rss text/javascript application/json; gzip_vary on; access_log /var/www/thinkingingraphs/shared/log/nginx_access.log; error_log /var/www/thinkingingraphs/shared/log/nginx_error.log; root /var/www/thinkingingraphs/current/public; location / { proxy_pass http://thin; } error_page 404 /404.html; error_page 500 502 503 504 /500.html; }
У меня был сценарий выскочка, который запустил тонкий сервер …
/etc/init/thinkingingraphs.conf
script export RACK_ENV=production export RUBY=ruby cd /var/www/thinkingingraphs/current exec su -s /bin/sh vagrant -c '$RUBY -S bundle exec thin -p 3000 start >> /var/www/thinkingingraphs/current/log/production.log 2>&1' end script
… А затем я использовал следующий скрипт capistrano, чтобы останавливать и запускать сервер всякий раз, когда я развертывал новую версию приложения:
конфиг / deploy.rb
namespace :deploy do task(:start) {} task(:stop) {} desc "Restart Application" task :restart do sudo "stop thinkingingraphs || echo 0" sudo "start thinkingingraphs" end end
Проблема с этим подходом состоит в том, что некоторые запросы получают код ответа 502 при его перезапуске:
$ bundle exec cap deploy
$ while true; do curl -w %{http_code}:%{time_total} http://localhost/ -o /dev/null -s; printf "\n"; sleep 0.5; done 200:0.076 200:0.074 200:0.095 502:0.003 200:0.696
Я хотел попробовать сделать сценарий развертывания без простоев и наткнулся на пару постов, которые помогли мне понять, как это сделать.
Первым шагом было убедиться, что у меня запущено более одного тонкого экземпляра, чтобы запросы могли отправляться одному из других во время перезапуска.
Я создал следующий файл конфигурации:
/etc/thin/thinkingingraphs.yml
chdir: /var/www/thinkingingraphs/current environment: production address: 0.0.0.0 port: 3000 timeout: 30 log: log/thin.log pid: tmp/pids/thin.pid max_conns: 1024 max_persistent_conns: 100 require: [] wait: 30 servers: 3 daemonize: true onebyone: true
Одним из других свойств, которые нам нужно установить, является «onebyone», что означает, что при перезапуске thin он будет удалять тонкие экземпляры по одному за раз. Это означает, что один из двух других может обрабатывать входящие запросы.
Мы установили количество серверов на 3, что увеличит скорость на 3 экземпляра на портах 3000, 3001 и 3002.
Я изменил свой скрипт выскочки, чтобы он выглядел так:
/etc/init/thinkingingraphs.conf
script export RACK_ENV=production export RUBY=ruby cd /var/www/thinkingingraphs/current exec su -s /bin/sh vagrant -c '$RUBY -S bundle exec thin -C /etc/thin/thinkingingraphs.yml start >> /var/www/thinkingingraphs/current/log/production.log 2>&1' end script
Мне также пришлось изменить скрипт capistrano, чтобы он вызывал «тонкий перезапуск» вместо остановки и запуска сценария upstart:
конфиг / deploy.rb
namespace :deploy do task(:start) {} task(:stop) {} desc "Restart Application" task :restart do run "cd #{current_path} && bundle exec thin restart -C /etc/thin/thinkingingraphs.yml" end end
Finally I had to make some changes to the nginx config file to send on requests to other thin instances if the first attempt failed (due to it being restarted) using the proxy_next_upstream method:
/etc/nginx/sites-available/thinkingingraphs.conf
upstream thin { server 127.0.0.1:3000 max_fails=1 fail_timeout=15s; server 127.0.0.1:3001 max_fails=1 fail_timeout=15s; server 127.0.0.1:3002 max_fails=1 fail_timeout=15s; } server { listen 80 default; server_name _; charset utf-8; rewrite ^\/status(.*)$ $1 last; gzip on; gzip_disable "MSIE [1-6]\.(?!.*SV1)"; gzip_types text/plain application/xml text/xml text/css application/x-javascript application/xml+rss text/javascript application/json; gzip_vary on; access_log /var/www/thinkingingraphs/shared/log/nginx_access.log; error_log /var/www/thinkingingraphs/shared/log/nginx_error.log; root /var/www/thinkingingraphs/current/public; location / { proxy_pass http://thin; proxy_next_upstream error timeout http_502 http_503; } error_page 404 /404.html; error_page 500 502 503 504 /500.html; }
We’ve also made a change to our upstream definition to proxy requests to one of the thin instances which will be running.
When I deploy the application now there is no downtime:
$ bundle exec cap deploy
$ while true; do curl -w %{http_code}:%{time_total} http://localhost/ -o /dev/null -s; printf "\n"; sleep 0.5; done 200:0.094 200:0.095 200:0.082 200:0.102 200:0.080 200:0.081
The only problem is that upstart now seems to have lost a handle on the thin processes and from what I can tell there isn’t a master process which upstart could get a handle on so I’m not sure how to wire this up.
Any ideas welcome!