ติดตั้ง Rails ด้วย Nginx -> 3xMongrel <- Monit

ใน blog ก่อนหน้านี้พูดถึง Nginx -> Mongrel cluster <- Monit ปรากฏว่า monit มันไม่สามารถไปคุมเจ้า mongrel cluster ได้ คาดว่าเป็นเพราะ Mongrel cluster มันเป็น cluster จึงไม่ได้แยกแต่ละตัวออกเป็น process เดี่ยวๆ แบบที่ monit ชอบ ดังนั้นเลยลองวิธีใหม่ แยกมันเป็น 3 ตัวซะเลย

ตอนนี้เจ้า monit ควบคุม mongrel อยู่หมัด ผมลอง kill process ดู เจ้า monit ก็ start ขึ้นมาให้ ตอนนี้สั่งปิด/เปิด mongrel จาก monit ได้เลย

ขั้นตอนการติดตั้งจะซ้ำกับของเดิมเยอะหน่อย แต่อยากเขียนให้เต็มๆ ครับ เริ่มจาก

1. ติดตั้ง project ของเรา

Add new user

  1. # สำหรับ ubuntu
  2. sudo /usr/sbin/adduser mongrel
  3.  
  4. # สำหรับ redhat ที่ใส่ -r เพราะไม่ต้องสร้าง home ให้ user
  5. sudo /usr/sbin/adduser -r mongrel

Deploy application

  1. sudo mkdir /var/www
  2. sudo mkdir /var/www/project
  3. sudo chown -R mongrel:mongrel /var/www/project
  4.  
  5. cd /var/www/project
  6. su mongrel
  7. svn checkout svn://host.com/project/trunk/ --username xxx --password xxx .
  8. rake db:create:all
  9. rake db:migrate
  10. rake db:migrate RAILS_ENV=&quot;production&quot;

#ทดสอบว่าติดตั้งเรียบร้อยหรือเปล่า ก่อนเริ่มขั้นตอนต่อไป
./script/server

2. ให้แก้ไฟล์ mongrel_rails ให้ลบ PID ออกถ้ามี PID อยู่แล้ว เพราะถ้าไม่ทำเจ้า mongrel_rails จะ error ตอนที่ process ของเราตายโดยทิ้ง PID เอาไว้ แล้วเราพยายาม start mongrel ขึ้นมา มันจะฟ้องว่ามี PID อยู่แล้ว และไม่ยอม start ให้เรา

สั่ง edit mongrel_rails ใครถนัด editor ตัวไหนก็ใช้ตามสะดวกนะครับ

  1. sudo vi /usr/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails
  2.  
  3. #บางทีก็อยู่ที่นี่
  4. sudo /var/lib/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails

แทนที่บรรทัดนี้

  1.           if File.exist? defaults[:pid_file]
  2.             log &quot;!!! PID file #{defaults[:pid_file]} already exists.  Mongrel could be running already.  Check your #{defaults[:log_file]} for errors.&quot;
  3.             log &quot;!!! Exiting with error.  You must stop mongrel and clear the .pid before I'll attempt a start.&quot;
  4.            exit 1
  5.          end

ด้วยบรรทัดนี้

  1.           if File.exist? defaults[:pid_file]
  2.             # mongrels that crash can leave stale PID files behind, and these
  3.             # should not stop mongrel from being restarted by monitors...
  4.             pid = File.new(defaults[:pid_file]).readline
  5.             unless `ps -ef | grep #{pid} | grep -v grep`.length &gt; 0
  6.               # use &quot;ps ax&quot; for freebsd
  7.               log &quot;!!! PID file #{defaults[:pid_file]} exists, but is stale, and will be deleted so that this mongrel can run.&quot;
  8.               File.delete(defaults[:pid_file])
  9.             else
  10.               log &quot;!!! PID file #{defaults[:pid_file]} already exists and the process id referred to in it is running.  This mongrel is probably already running.  #{defaults[:log_file]} for errors.  EXITING.&quot;
  11.               exit 1
  12.             end
  13.             exit 1
  14.           end

3. เตรียม config สำหรับ mongrel ทั้ง 3 ตัว

  1. sudo vi /var/www/project/config/mongrel_8000.yml

  1. ---
  2. user: mongrel
  3. cwd: /var/www/project
  4. log_file: log/mongrel.8000.log
  5. port: &quot;8000&quot;
  6. environment: production
  7. group: mongrel
  8. address: 127.0.0.1
  9. pid_file: tmp/pids/mongrel.8000.pid
  10. daemon: true

สร้างไฟล์นี้อีกสองไฟล์ แต่เปลี่ยนจาก 8000 เป็น 8001 และ 8002

สำหรับคนที่ลง mongrel cluster ไปแล้ว แถมสั่งให้มัน start ตอน boot ด้วย ต้องไปเอาออกก่อนครับ เพราะต่อไปเราจะให้ monit เป็นคน start ให้ทั้งหมด ผมใช้วิธีลบ ไฟล์ /etc/mongrel_cluster/application_name.yml ออกไป

ทดสอบว่า server ของเราทำงานโดยสั่ง

  1. sudo /usr/bin/mongrel_rails start -C /var/www/project/config/mongrel_8000.yml

จากนั้นทดลองสั่ง

  1. ps -aux | grep mong

ถ้ามี process 8000 ของเราขึ้นมาแสดงว่าเรียบร้อย ถ้าไม่ขึ้นให้ลองไปดู log ที่ /var/www/project/log/mongrel.8000.log

จากนั้นลองสั่ง stop ดูด้วยคำสั่ง

  1. sudo /usr/bin/mongrel_rails stop -P /var/www/project/tmp/pids/mongrel.8000.pid

ถ้าไม่ได้ให้ลองดู log เหมือนเดิม ถ้าได้ก็ไปขั้นตอนต่อไปได้เลย

4. ติดตั้ง Watch dog ที่ชื่อ monit

ติดตั้ง monit (ถ้าใครไม่มี apt-get ใช้ก็ลองประยุกต์ใช้ทางอื่นดูนะครับ)

  1. sudo apt-get install monit

จากนั้นตั้งค่าให้ monit

  1. sudo mkdir /etc/monit.d
  2. sudo vi /etc/monit.d/mongrel.monitrc

ใส่ config ตามนี้

  1. check process mongrel_8000
  2.   with pidfile /var/www/project/tmp/pids/mongrel.8000.pid
  3.   group mongrel
  4.   start program = &quot;/usr/bin/mongrel_rails start -C /var/www/project/config/mongrel_8000.yml&quot;
  5.   stop program = &quot;/usr/bin/mongrel_rails stop -P /var/www/project/tmp/pids/mongrel.8000.pid&quot;
  6.   if failed host 127.0.0.1 port 8000 protocol http
  7.       and request &quot;/&quot; then alert
  8.   if totalmem is greater than 110.0 MB for 4 cycles then restart
  9.   if cpu is greater than 80% for 4 cycles then restart
  10.   if 3 restarts within 5 cycles then timeout
  11.  
  12. check process mongrel_8001
  13.   with pidfile /var/www/project/tmp/pids/mongrel.8001.pid
  14.   group mongrel
  15.   start program = &quot;/usr/bin/mongrel_rails start -C /var/www/project/config/mongrel_8001.yml&quot;
  16.   stop program = &quot;/usr/bin/mongrel_rails stop -P /var/www/project/tmp/pids/mongrel.8001.pid&quot;
  17.   if failed host 127.0.0.1 port 8001 protocol http
  18.       and request &quot;/&quot; then alert
  19.   if totalmem is greater than 110.0 MB for 4 cycles then restart
  20.   if cpu is greater than 80% for 4 cycles then restart
  21.   if 3 restarts within 5 cycles then timeout
  22.  
  23. check process mongrel_8002
  24.   with pidfile /var/www/project/tmp/pids/mongrel.8002.pid
  25.   group mongrel
  26.   start program = &quot;/usr/bin/mongrel_rails start -C /var/www/project/config/mongrel_8002.yml&quot;
  27.   stop program = &quot;/usr/bin/mongrel_rails stop -P /var/www/project/tmp/pids/mongrel.8002.pid&quot;
  28.   if failed host 127.0.0.1 port 8002 protocol http
  29.       and request &quot;/&quot; then alert
  30.   if totalmem is greater than 110.0 MB for 4 cycles then restart
  31.   if cpu is greater than 80% for 4 cycles then restart
  32.   if 3 restarts within 5 cycles then timeout

ถ้าเจ้า monit เจออะไรผิดพลาด ตามที่เขียนใน config มันจะ restart ให้ทันที อันนี้ชอบมั๊กๆ แต่เปิดใช้มาหลายวัน มันยังไม่เคย restart เองเลยครับ เสถียรมาก มีแต่ผมสั่งมัน restart เอง คงเพราะ ผู้ใช้ยังไม่คุ้นเลยยังยิงกันไม่ถึงตาย

แก้ไฟล์ monit ให้มัน start ตอน boot เครื่อง

  1. sudo vi /etc/default/monit

startup=1

จากนั้นเอา comment ของไฟล์ monitrc ออกตามนี้

  1. sudo vi /etc/monit/monitrc

set daemon 120
set logfile syslog facility log_daemon
set httpd port 2812 and
allow localhost # allow localhost to connect to the server and
include /etc/monit.d/*

ทดสอบการทำงานของ monit ตามนี้ครับ

สั่ง restart, sudo shutdown -r now
เมื่อเปิดมาตอนแรกให้รอ 5-10 นาที
จากนั้นลอง sudo monit status
ตัว monit ควรจะ start mongrel ให้เราทั้งสามตัว
ทดลอง ps -aux | grep mong
ดู process ทั้งหมดของ mongrel
ทดลอง kill 1 process
รอ 5-10 นาที
ทดลอง ps -aux | grep mong
ดูว่า mongrel start ขึ้นมาให้เราหรือเปล่า
แล้วสั่ง sudo monit status
ดูว่า monit รับรู้การขึ้นมาหรือยัง
ถ้าขึ้นมาครบทั้ง 3 ตัวเป็นอันว่าติดตั้ง mongrel และ monit สำเร็จ

คำสั่งที่ใช้บ่อยบน monit มีดังนี้ครับ

  1. # restart monit ถ้ามันหือ
  2. sudo /etc/init.d/monit restart
  3.  
  4. #restart mongrel ยกฝูง
  5. sudo monit restart all -g mongrel
  6.  
  7. #start/stop บางตัว
  8. sudo monit stop mongrel_8000
  9. sudo monit start mongrel_8000
  10.  
  11. #ดู status
  12. sudo monit status

#force ให้ monit ตรวจสอบการทำงานของ process ที่มันดูอยู่
sudo monit validate

5. ติดตั้ง NGiNX

  1. sudo apt-get install nginx

แก้ config ของไฟล์

  1. sudo vi /etc/nginx/nginx.conf

  1. #user deploy;
  2. worker_processes  1;
  3.  
  4. error_log  /var/log/nginx/error.log;
  5. #error_log   logs/error.log debug;
  6. #pid        /var/run/nginx.pid;
  7.  
  8. events {
  9.     worker_connections  1024;
  10. }
  11.  
  12. http {
  13.     include       /etc/nginx/mime.types;
  14.     default_type  application/octet-stream;
  15.  
  16.     #tac_nonpush  on;
  17.     tcp_nodelay   on;
  18.  
  19.     #access_log /var/log/nginx/access.log;
  20.  
  21.     sendfile        on;
  22.     #tcp_nopush     on;
  23.  
  24.     #keepalive_timeout  0;
  25.     #keepalive_timeout  65;
  26.  
  27.     gzip            on;
  28.     gzip_min_length 1100;
  29.     gzip_buffers    4 8k;
  30.     gzip_types      text/plain;
  31.  
  32.     #include /etc/nginx/sites-enabled/*;
  33.  
  34.     upstream mongrel {
  35.         server 127.0.0.1:8000;
  36.         server 127.0.0.1:8001;
  37.         server 127.0.0.1:8002;
  38.     }
  39.  
  40.     server {
  41.         listen  80;
  42.         server_name project.com;
  43.         root /var/www/project/public;
  44.         index  index.html index.htm;
  45.         location / {
  46.           proxy_set_header  X-Real-IP  $remote_addr;
  47.           proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  48.           proxy_set_header Host $http_host;
  49.           proxy_redirect false;
  50.           if (-f $request_filename/index.html) {
  51.             rewrite (.*) $1/index.html break;
  52.           }
  53.           if (-f $request_filename.html) {
  54.             rewrite (.*) $1.html break;
  55.           }
  56.           if (!-f $request_filename) {
  57.             proxy_pass <a href="http://mongrel;<br />
  58. " title="http://mongrel;<br />
  59. ">http://mongrel;<br />
  60. </a>            break;
  61.          }
  62.        }
  63.        error_page   500 502 503 504  /50x.html;
  64.        location = /50x.html {
  65.          root   html;
  66.        }
  67.     }
  68. }

restart NGiNX ด้วยคำสั่ง

sudo /etc/init.d/nginx restart

จากนั้นลองเข้าผ่าน web ดูครับ ว่าเปิดได้หรือเปล่า ถ้าได้ก็จบครับ ขั้นต่อไปเป็นของแถม ทำเผื่อเอาไว้ตอนมีปัญหาจะได้เข้ามาดู

6. ติดตั้งตัว monitor ให้ NGiNX

  1. sudo apt-get install rrdtool librrds-perl -y

  1. sudo vi /etc/nginx/nginx.conf

เพิ่ม location status ลงไประหว่าง http และ server

  1. http {
  2.     ...
  3.     server {
  4.         listen SOME.IP.ADD.RESS;
  5.         ...
  6.         location /nginx_status {
  7.             stub_status on;
  8.             access_log   off;
  9.             allow SOME.IP.ADD.RESS;
  10.             deny all;
  11.         }
  12.         ...
  13.     }
  14.     ...
  15. }

ทดสอบว่า script NGiNX ของเรายัง ok อยู่

  1. # sudo /usr/sbin/nginx -t
  2. 2006/04/29 04:24:36 [info] 31676#0: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
  3. 2006/04/29 04:24:36 [info] 31676#0: the configuration file /opt/nginx/conf/nginx.conf was tested successfully

สร้างที่อยู่ให้ output file

  1. sudo mkdir /opt/rrd
  2. sudo mkdir /opt/rrd/html
  3.  
  4. sudo vi /etc/nginx/rrd_nginx.pl

ไฟล์ rrd_nginx.pl เอาได้ที่ apirak.com/downloads/rrd_nginx.pl

อย่าลืมสั่งให้ rrd_nginx.pl กลายเป็น execute file ด้วย

  1. chmod +x /etc/nginx/rrd_nginx.pl

จากนั้น edit ให้ cron เรียก rrd_nginx.pl ทุกๆ นาที

  1. sudo crontab -e
  2.  
  3. # m h  dom mon dow   command
  4.   * *  *   *   *     /etc/nginx/rrd_nginx.pl

เมื่อโปรแกรมทำงานจะมีรูปขึ้นมาที่ /etc/opt/rrd/html สามารถเข้าไปดูได้ วินาทีนี้ผมยังไม่ได้สร้าง HTML สำหรับดู เลยทำแค่ ใช้ feh ในการดู

  1. sudo apt-get install feh -y
  2. feh /opt/rrd/html/*.png

ถ้ามีกราฟขึ้นก็แสดงว่าโปรแกรมทำงานได้แล้ว และถ้ากราฟมีขึ้นๆ ลงๆ ก็แสดงว่าสมบูรณ์ละแล้วครับ :)

Reference ( บางแหล่งก็ลืมไปแล้วครับ จดไว้ประมาณนี้)

http://codesnippets.joyent.com/tag/mongrel
http://www.howtoforge.com/server_monitoring_monit_munin
http://www.circlingminds.com/advanced-rails/using-nginx-mongrel-rails-on-ubuntu/
http://wiki.codemongers.com/NginxInstall
http://groups.google.com/group/thinking-sphinx/browse_thread/thread/a7a11ab1c98f5593
http://mkaz.com/ref/unix_cron.html

Post new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Copy the characters (respecting upper/lower case) from the image.