ติดตั้ง Rails Mongrel Cluster บน Ubuntu Hardy (8.04)

ทดลองมาหลาย solution สุดท้ายมาได้เป็น solution ง่ายๆ แบบนี้ครับ

web_solution

การ Deploy เราค่อยๆ ทำตามลำดับดังนี้

1. ติดตั้ง Application ของเราบน mongrel ให้ขึ้นได้ก่อน

Adduser

สร้าง user สำหรับ run mongrel เวลากำหนดสิทธิ์จะได้ง่ายหน่อย

สำหรับ Ubuntu

  1. sudo /usr/sbin/adduser mongrel

สำหรับ Redhat, "-r" คือไม่ต้องสร้าง home ไม่ต้องมี attribute มากมายให้ user

  1. sudo /usr/sbin/adduser -r mongrel

Deploy application

ติดตั้ง application ของเราไว้ที่ /var/www/

  1. sudo mkdir /var/www
  2. sudo mkdir /var/www/application_name
  3. sudo chown -R mongrel:mongrel /var/www/application_name

เอา application ของเรามาใส่ไว้ในที่ๆ เตรียมไว้ จะเอาออกมาจาก svn หรือ copy มาใส่ก็ได้ ไว้ตอนต่อไปเราค่อยมา set capistano กัน

  1. svn export svn://svn_server.com/application_name/trunk/ --username name --password pass .
  2. rake db:create:all
  3. rake db:migrate RAILS_ENV="production"

ทดลอง run ดูก่อนว่าทำงานได้หรือเปล่า

  1. ./script/server -e production

Setup Mongrel Cluster

เมื่อหนึ่งตัวทำงานได้ ต่อไปก็ทำให้เป็น cluster ให้ cd เข้าไปที่ /var/www/application_name แล้วสั่งสร้าง configuration file ของ mongrel_cluster

  1. mongrel_rails cluster::configure -e production -p 8000 -N 3 -c /var/www/application_name -a 127.0.0.1 --user mongrel --group mongrel

สร้างแล้วทดลอง start stop ดู

  1. sudo mongrel_rails cluster::start
  2. sudo mongrel_rails cluster::stop

ให้ลองเปิด browser แล้วเรียก localhost:8000, localhost:8001, localhost:8002 ว่าได้ครบหรือเปล่า ในตอนนี้เราไม่สามารถเรียก web โดยตรงจาก IP เพราะต้องการเปิดแค่ localhost เท่านั้น กันคนอื่นเข้ามาเรียกตรงๆ

Start mongrel when reboot

ตั้ง config ให้ mongrel cluster ของเราถูกเรียกขึ้นมาใหม่ทุกครั้งที่เปิดเครื่องใหม่

  1. sudo mkdir /etc/mongrel_cluster
  2. sudo ln -s /var/www/application_name/config/mongrel_cluster.yml /etc/mongrel_cluster/application_name.yml
  3. sudo cp /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster /etc/init.d/
  4. sudo chmod +x /etc/init.d/mongrel_cluster

ทดลองเรียก start stop จาก init.d ดูครับ

  1. sudo /etc/init.d/mongrel_cluster start < Test
  2. sudo /etc/init.d/mongrel_cluster stop < Test

จากนั้นสั่ง update rc.d เพื่อให้เรียก mongrel cluster ทุกครั้ง

  1. sudo /usr/sbin/update-rc.d -f mongrel_cluster defaults  

สำหรับ Ubuntu

  1. sudo /sbin/chkconfig --level 345 mongrel_cluster on <- redhat

สำหรับ Linux

2. ติดตั้ง Watch dog เป็น ยามเฝ้า server

ติดตั้งโปรแกรม monit ก่อน

  1. sudo apt-get install monit

config monit

สร้างไฟล์ monitrc ขึ้นมา

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

ใส่ config นี้ลงไป

  1. check process mongrel_deployit_8000
  2.   with pidfile /var/www/application_name/tmp/pids/mongrel.8000.pid
  3.   start program = "/usr/bin/mongrel_rails cluster::start -C /etc/mongrel_cluster/application_name.yml  --clean --only 8000"
  4.   stop program = "/usr/bin/mongrel_rails cluster::stop -C /etc/mongrel_cluster/application_name.yml --only 8000"
  5.   if totalmem is greater than 110.0 MB for 4 cycles then restart
  6.   if cpu is greater than 80% for 4 cycles then restart
  7.   if 20 restarts within 20 cycles then timeout
  8.   group deployit
  9.  
  10. check process mongrel_deployit_8001
  11.   with pidfile /var/www/application_name/tmp/pids/mongrel.8001.pid
  12.   start program = "/usr/bin/mongrel_rails cluster::start -C /etc/mongrel_cluster/application_name.yml  --clean --only 8001"
  13.   stop program = "/usr/bin/mongrel_rails cluster::stop -C /etc/mongrel_cluster/application_name.yml --only 8001"
  14.   if totalmem is greater than 110.0 MB for 4 cycles then restart
  15.   if cpu is greater than 80% for 4 cycles then restart
  16.   if 20 restarts within 20 cycles then timeout
  17.   group deployit
  18.  
  19. check process mongrel_deployit_8002
  20.   with pidfile /var/www/application_name/tmp/pids/mongrel.8002.pid
  21.   start program = "/usr/bin/mongrel_rails cluster::start -C /etc/mongrel_cluster/application_name.yml  --clean --only 8002"
  22.   stop program = "/usr/bin/mongrel_rails cluster::stop -C /etc/mongrel_cluster/application_name.yml --only 8002"
  23.   if totalmem is greater than 110.0 MB for 4 cycles then restart
  24.   if cpu is greater than 80% for 4 cycles then restart
  25.   if 20 restarts within 20 cycles then timeout
  26.   group deployit

จากนั้นแก้ config อีกสองไฟล์

  1. sudo vi /etc/default/monit

แก้ startup = 1

  1. sudo vi /etc/monit/monitrc

ให้ enable บรรทัดต่อไปนี้

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/*

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

  1. sudo /etc/init.d/monit restart
  2. sudo monit restart all -g deployit
  3. sudo monit stop mongrel_deployit_8000
  4. sudo monit start mongrel_deployit_8000
  5. sudo monit status

ลองปิดๆ เปิดๆ ควบคู่ไปกับการดู status เพื่อให้แน่ใจว่ามันปิด มันเปิดได้จริงๆ ใครจะทดลองยิง mongrel ให้ล่ม หรือลอง kill mongrel process ดูก็ได้ครับ จะได้แน่ใจว่ามันล่ม แล้วเปิดขึ้นได้จริงๆ

3. ติดตั้ง NGINX

  1. sudo apt-get install nginx

จากนั้นแก้ไฟล์ /etc/nginx/nginx.conf

  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 example.com;
  43.         root /var/www/application_name/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 http://mongrel;
  58.             break;
  59.          }
  60.        }
  61.        error_page   500 502 503 504  /50x.html;
  62.        location = /50x.html {
  63.          root   html;
  64.        }
  65.     }
  66. }

เราให้ nginx จัดการ static ไฟล์แทน mongrel แต่ถ้าใครต้องการให้ mongrel เป็นคนจัดการสามารถเอา if ต่างๆ ออกได้ตามสะดวก

4. เพื่อให้สมบูรณ์มากขึ้นเราติดตั้งโปรแกรมเอาไว้ monitor การทำงานของ nginx ไว้ด้วยเลย

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

แก้ไฟล์ /etc/nginx/nginx.conf

โดยเพิ่ม location /nginx_status ลงไป

  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. }

ใครอยากจะเพิ่มความปลอดภัยก็ให้ใส่บรรทัด allow และ deny ลงไปด้วย ถ้าไม่คิดจะปิดกั้นก็ลบไปก็ได้ครับ

ทดลองดูก่อนว่า nginx ทำงานเป็นปกติหรือเปล่าหลังจากแก้ config มันแล้ว

  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
  4. #

ถ้าปกติจะขึ้นประมาณนี้

เขียนโปรแกรมง่ายๆ เอาไว้สร้าง graph

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

ตัวโปรแกรมเป็นแบบนี้ ผมก็ลอกมาอีกที จริงๆ เขียน perl ไม่เป็น

  1. #!/usr/bin/perl
  2. use RRDs;
  3. use LWP::UserAgent;
  4.  
  5. # define location of rrdtool databases
  6. my $rrd = '/opt/rrd';
  7. # define location of images
  8. my $img = '/opt/rrd/html';
  9. # define your nginx stats URL
  10. my $URL = "http://localhost/nginx_status";
  11.  
  12. my $ua = LWP::UserAgent->new(timeout => 30);
  13. my $response = $ua->request(HTTP::Request->new('GET', $URL));
  14.  
  15. my $requests = 0;
  16. my $total =  0;
  17. my $reading = 0;
  18. my $writing = 0;
  19. my $waiting = 0;
  20.  
  21. foreach (split(/\n/, $response->content)) {
  22.   $total = $1 if (/^Active connections:\s+(\d+)/);
  23.   if (/^Reading:\s+(\d+).*Writing:\s+(\d+).*Waiting:\s+(\d+)/) {
  24.     $reading = $1;
  25.     $writing = $2;
  26.     $waiting = $3;
  27.   }
  28.   $requests = $3 if (/^\s+(\d+)\s+(\d+)\s+(\d+)/);
  29. }
  30.  
  31. #print "RQ:$requests; TT:$total; RD:$reading; WR:$writing; WA:$waiting\n";
  32.  
  33. # if rrdtool database doesn't exist, create it
  34. if (! -e "$rrd/nginx.rrd") {
  35.   RRDs::create "$rrd/nginx.rrd",
  36.         "-s 60",
  37.     "DS:requests:COUNTER:120:0:100000000",
  38.     "DS:total:ABSOLUTE:120:0:60000",
  39.     "DS:reading:ABSOLUTE:120:0:60000",
  40.     "DS:writing:ABSOLUTE:120:0:60000",
  41.     "DS:waiting:ABSOLUTE:120:0:60000",
  42.     "RRA:AVERAGE:0.5:1:2880",
  43.     "RRA:AVERAGE:0.5:30:672",
  44.     "RRA:AVERAGE:0.5:120:732",
  45.     "RRA:AVERAGE:0.5:720:1460";
  46. }
  47.  
  48. # insert values into rrd database
  49. RRDs::update "$rrd/nginx.rrd",
  50.   "-t", "requests:total:reading:writing:waiting",
  51.   "N:$requests:$total:$reading:$writing:$waiting";
  52.  
  53. # Generate graphs
  54. CreateGraphs("day");
  55. CreateGraphs("week");
  56. CreateGraphs("month");
  57. CreateGraphs("year");
  58.  
  59. #------------------------------------------------------------------------------
  60. sub CreateGraphs($){
  61.   my $period = shift;
  62.  
  63.   RRDs::graph "$img/requests-$period.png",
  64.         "-s -1$period",
  65.         "-t Requests on nginx",
  66.         "--lazy",
  67.         "-h", "150", "-w", "700",
  68.         "-l 0",
  69.         "-a", "PNG",
  70.         "-v requests/sec",
  71.         "DEF:requests=$rrd/nginx.rrd:requests:AVERAGE",
  72.         "LINE2:requests#336600:Requests",
  73.         "GPRINT:requests:MAX:  Max\\: %5.1lf %S",
  74.         "GPRINT:requests:AVERAGE: Avg\\: %5.1lf %S",
  75.         "GPRINT:requests:LAST: Current\\: %5.1lf %Sreq/sec",
  76.         "HRULE:0#000000";
  77.   if ($ERROR = RRDs::error) {
  78.     print "$0: unable to generate $period graph: $ERROR\n";
  79.   }
  80.  
  81.   RRDs::graph "$img/connections-$period.png",
  82.         "-s -1$period",
  83.         "-t Requests on nginx",
  84.         "--lazy",
  85.         "-h", "150", "-w", "700",
  86.         "-l 0",
  87.         "-a", "PNG",
  88.         "-v requests/sec",
  89.         "DEF:total=$rrd/nginx.rrd:total:AVERAGE",
  90.         "DEF:reading=$rrd/nginx.rrd:reading:AVERAGE",
  91.         "DEF:writing=$rrd/nginx.rrd:writing:AVERAGE",
  92.         "DEF:waiting=$rrd/nginx.rrd:waiting:AVERAGE",
  93.  
  94.         "LINE2:total#22FF22:Total",
  95.         "GPRINT:total:LAST:   Current\\: %5.1lf %S",
  96.         "GPRINT:total:MIN:  Min\\: %5.1lf %S",
  97.         "GPRINT:total:AVERAGE: Avg\\: %5.1lf %S",
  98.         "GPRINT:total:MAX:  Max\\: %5.1lf %S\\n",
  99.        
  100.         "LINE2:reading#0022FF:Reading",
  101.         "GPRINT:reading:LAST: Current\\: %5.1lf %S",
  102.         "GPRINT:reading:MIN:  Min\\: %5.1lf %S",
  103.         "GPRINT:reading:AVERAGE: Avg\\: %5.1lf %S",
  104.         "GPRINT:reading:MAX:  Max\\: %5.1lf %S\\n",
  105.        
  106.         "LINE2:writing#FF0000:Writing",
  107.         "GPRINT:writing:LAST: Current\\: %5.1lf %S",
  108.         "GPRINT:writing:MIN:  Min\\: %5.1lf %S",
  109.         "GPRINT:writing:AVERAGE: Avg\\: %5.1lf %S",
  110.         "GPRINT:writing:MAX:  Max\\: %5.1lf %S\\n",
  111.        
  112.         "LINE2:waiting#00AAAA:Waiting",
  113.         "GPRINT:waiting:LAST: Current\\: %5.1lf %S",
  114.         "GPRINT:waiting:MIN:  Min\\: %5.1lf %S",
  115.         "GPRINT:waiting:AVERAGE: Avg\\: %5.1lf %S",
  116.         "GPRINT:waiting:MAX:  Max\\: %5.1lf %S\\n",
  117.  
  118.         "HRULE:0#000000";
  119.   if ($ERROR = RRDs::error) {
  120.     print "$0: unable to generate $period graph: $ERROR\n";
  121.   }
  122. }

edit cron

บอก cron ให้สั่ง run script ของเราทุกๆ นาที

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

ทดสอบเรียก sudo /etc/nginx/rrd_nginx.pl โปรแกรมจะสร้างรูปขึ้นมาที่ /opt/rrd/html ผมใช้โปรแกรม feh เอาไว้ดูรูป ใครจะเขียน HTML ขึนมาดูรูปก็ได้ครับ

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

เป็นอันเสร็จพิธี ขั้นตอนอาจจะดูยาวครับ แต่ทำจริงๆ แป๊บเดียว ต้องขอบคุณ apt-get มากๆ ช่วยให้งานเร็วขึ้นเยอะทีเดียว

reference: http://wiki.codemongers.com/NginxInstall reference: http://www.circlingminds.com/advanced-rails/using-nginx-mongrel-rails-on-ubuntu/

AttachmentSize
web_solution.png35.44 KB

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.