วันอังคาร, ตุลาคม 14, 2551

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

ทดลองมาหลาย solution สุดท้ายมาได้เป็น solution ง่ายๆ แบบนี้ครับ ![web_solution](/downloads/web_solution.png) การ Deploy เราค่อยๆ ทำตามลำดับดังนี้ 1. ติดตั้ง Application ของเราบน mongrel ให้ขึ้นได้ก่อน ============================ **Adduser** สร้าง user สำหรับ run mongrel เวลากำหนดสิทธิ์จะได้ง่ายหน่อย สำหรับ Ubuntu sudo /usr/sbin/adduser mongrel สำหรับ Redhat, "-r" คือไม่ต้องสร้าง home ไม่ต้องมี attribute มากมายให้ user sudo /usr/sbin/adduser -r mongrel **Deploy application** ติดตั้ง application ของเราไว้ที่ /var/www/ sudo mkdir /var/www sudo mkdir /var/www/application_name sudo chown -R mongrel:mongrel /var/www/application_name เอา application ของเรามาใส่ไว้ในที่ๆ เตรียมไว้ จะเอาออกมาจาก svn หรือ copy มาใส่ก็ได้ ไว้ตอนต่อไปเราค่อยมา set capistano กัน svn export svn://svn_server.com/application_name/trunk/ --username name --password pass . rake db:create:all rake db:migrate RAILS_ENV="production" ทดลอง run ดูก่อนว่าทำงานได้หรือเปล่า ./script/server -e production **Setup Mongrel Cluster** เมื่อหนึ่งตัวทำงานได้ ต่อไปก็ทำให้เป็น cluster ให้ cd เข้าไปที่ /var/www/application_name แล้วสั่งสร้าง configuration file ของ mongrel_cluster 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 ดู sudo mongrel_rails cluster::start sudo mongrel_rails cluster::stop ให้ลองเปิด browser แล้วเรียก localhost:8000, localhost:8001, localhost:8002 ว่าได้ครบหรือเปล่า ในตอนนี้เราไม่สามารถเรียก web โดยตรงจาก IP เพราะต้องการเปิดแค่ localhost เท่านั้น กันคนอื่นเข้ามาเรียกตรงๆ **Start mongrel when reboot** ตั้ง config ให้ mongrel cluster ของเราถูกเรียกขึ้นมาใหม่ทุกครั้งที่เปิดเครื่องใหม่ sudo mkdir /etc/mongrel_cluster sudo ln -s /var/www/application_name/config/mongrel_cluster.yml /etc/mongrel_cluster/application_name.yml sudo cp /usr/lib/ruby/gems/1.8/gems/mongrel_cluster-1.0.5/resources/mongrel_cluster /etc/init.d/ sudo chmod +x /etc/init.d/mongrel_cluster ทดลองเรียก start stop จาก init.d ดูครับ sudo /etc/init.d/mongrel_cluster start < Test sudo /etc/init.d/mongrel_cluster stop < Test จากนั้นสั่ง update rc.d เพื่อให้เรียก mongrel cluster ทุกครั้ง sudo /usr/sbin/update-rc.d -f mongrel_cluster defaults สำหรับ Ubuntu sudo /sbin/chkconfig --level 345 mongrel_cluster on <- redhat สำหรับ Linux 2. ติดตั้ง Watch dog เป็น ยามเฝ้า server ===================== ติดตั้งโปรแกรม monit ก่อน sudo apt-get install monit **config monit** สร้างไฟล์ monitrc ขึ้นมา sudo mkdir /etc/monit.d sudo vi /etc/monit.d/mongrel.monitrc ใส่ config นี้ลงไป check process mongrel_deployit_8000 with pidfile /var/www/application_name/tmp/pids/mongrel.8000.pid start program = "/usr/bin/mongrel_rails cluster::start -C /etc/mongrel_cluster/application_name.yml --clean --only 8000" stop program = "/usr/bin/mongrel_rails cluster::stop -C /etc/mongrel_cluster/application_name.yml --only 8000" if totalmem is greater than 110.0 MB for 4 cycles then restart if cpu is greater than 80% for 4 cycles then restart if 20 restarts within 20 cycles then timeout group deployit check process mongrel_deployit_8001 with pidfile /var/www/application_name/tmp/pids/mongrel.8001.pid start program = "/usr/bin/mongrel_rails cluster::start -C /etc/mongrel_cluster/application_name.yml --clean --only 8001" stop program = "/usr/bin/mongrel_rails cluster::stop -C /etc/mongrel_cluster/application_name.yml --only 8001" if totalmem is greater than 110.0 MB for 4 cycles then restart if cpu is greater than 80% for 4 cycles then restart if 20 restarts within 20 cycles then timeout group deployit check process mongrel_deployit_8002 with pidfile /var/www/application_name/tmp/pids/mongrel.8002.pid start program = "/usr/bin/mongrel_rails cluster::start -C /etc/mongrel_cluster/application_name.yml --clean --only 8002" stop program = "/usr/bin/mongrel_rails cluster::stop -C /etc/mongrel_cluster/application_name.yml --only 8002" if totalmem is greater than 110.0 MB for 4 cycles then restart if cpu is greater than 80% for 4 cycles then restart if 20 restarts within 20 cycles then timeout group deployit จากนั้นแก้ config อีกสองไฟล์ sudo vi /etc/default/monit แก้ startup = 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/* จากนั้นทดลองสั่ง sudo /etc/init.d/monit restart sudo monit restart all -g deployit sudo monit stop mongrel_deployit_8000 sudo monit start mongrel_deployit_8000 sudo monit status ลองปิดๆ เปิดๆ ควบคู่ไปกับการดู status เพื่อให้แน่ใจว่ามันปิด มันเปิดได้จริงๆ ใครจะทดลองยิง mongrel ให้ล่ม หรือลอง kill mongrel process ดูก็ได้ครับ จะได้แน่ใจว่ามันล่ม แล้วเปิดขึ้นได้จริงๆ 3. ติดตั้ง NGINX ======= sudo apt-get install nginx จากนั้นแก้ไฟล์ /etc/nginx/nginx.conf sudo vi /etc/nginx/nginx.conf ใส่ข้อมูลตามนี้ #user deploy; worker_processes 1; error_log /var/log/nginx/error.log; #error_log logs/error.log debug; #pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; #tac_nonpush on; tcp_nodelay on; #access_log /var/log/nginx/access.log; sendfile on; #tcp_nopush on; #keepalive_timeout 0; #keepalive_timeout 65; gzip on; gzip_min_length 1100; gzip_buffers 4 8k; gzip_types text/plain; #include /etc/nginx/sites-enabled/*; upstream mongrel { server 127.0.0.1:8000; server 127.0.0.1:8001; server 127.0.0.1:8002; } server { listen 80; server_name example.com; root /var/www/application_name/public; index index.html index.htm; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect false; if (-f $request_filename/index.html) { rewrite (.*) $1/index.html break; } if (-f $request_filename.html) { rewrite (.*) $1.html break; } if (!-f $request_filename) { proxy_pass http://mongrel; break; } } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } เราให้ nginx จัดการ static ไฟล์แทน mongrel แต่ถ้าใครต้องการให้ mongrel เป็นคนจัดการสามารถเอา if ต่างๆ ออกได้ตามสะดวก 4. เพื่อให้สมบูรณ์มากขึ้นเราติดตั้งโปรแกรมเอาไว้ monitor การทำงานของ nginx ไว้ด้วยเลย ============================================== sudo apt-get install rrdtool -y sudo apt-get install librrds-perl -y แก้ไฟล์ /etc/nginx/nginx.conf โดยเพิ่ม location /nginx_status ลงไป http { ... server { listen SOME.IP.ADD.RESS; ... location /nginx_status { stub_status on; access_log off; allow SOME.IP.ADD.RESS; deny all; } ... } ... } ใครอยากจะเพิ่มความปลอดภัยก็ให้ใส่บรรทัด allow และ deny ลงไปด้วย ถ้าไม่คิดจะปิดกั้นก็ลบไปก็ได้ครับ ทดลองดูก่อนว่า nginx ทำงานเป็นปกติหรือเปล่าหลังจากแก้ config มันแล้ว # sudo /usr/sbin/nginx -t 2006/04/29 04:24:36 [info] 31676#0: the configuration file /opt/nginx/conf/nginx.conf syntax is ok 2006/04/29 04:24:36 [info] 31676#0: the configuration file /opt/nginx/conf/nginx.conf was tested successfully # ถ้าปกติจะขึ้นประมาณนี้ เขียนโปรแกรมง่ายๆ เอาไว้สร้าง graph sudo mkdir /opt/rrd sudo mkdir /opt/rrd/html sudo vi /etc/nginx/rrd_nginx.pl ตัวโปรแกรมเป็นแบบนี้ ผมก็ลอกมาอีกที จริงๆ เขียน perl ไม่เป็น #!/usr/bin/perl use RRDs; use LWP::UserAgent; # define location of rrdtool databases my $rrd = '/opt/rrd'; # define location of images my $img = '/opt/rrd/html'; # define your nginx stats URL my $URL = "http://localhost/nginx_status"; my $ua = LWP::UserAgent->new(timeout => 30); my $response = $ua->request(HTTP::Request->new('GET', $URL)); my $requests = 0; my $total = 0; my $reading = 0; my $writing = 0; my $waiting = 0; foreach (split(/\n/, $response->content)) { $total = $1 if (/^Active connections:\s+(\d+)/); if (/^Reading:\s+(\d+).*Writing:\s+(\d+).*Waiting:\s+(\d+)/) { $reading = $1; $writing = $2; $waiting = $3; } $requests = $3 if (/^\s+(\d+)\s+(\d+)\s+(\d+)/); } #print "RQ:$requests; TT:$total; RD:$reading; WR:$writing; WA:$waiting\n"; # if rrdtool database doesn't exist, create it if (! -e "$rrd/nginx.rrd") { RRDs::create "$rrd/nginx.rrd", "-s 60", "DS:requests:COUNTER:120:0:100000000", "DS:total:ABSOLUTE:120:0:60000", "DS:reading:ABSOLUTE:120:0:60000", "DS:writing:ABSOLUTE:120:0:60000", "DS:waiting:ABSOLUTE:120:0:60000", "RRA:AVERAGE:0.5:1:2880", "RRA:AVERAGE:0.5:30:672", "RRA:AVERAGE:0.5:120:732", "RRA:AVERAGE:0.5:720:1460"; } # insert values into rrd database RRDs::update "$rrd/nginx.rrd", "-t", "requests:total:reading:writing:waiting", "N:$requests:$total:$reading:$writing:$waiting"; # Generate graphs CreateGraphs("day"); CreateGraphs("week"); CreateGraphs("month"); CreateGraphs("year"); #------------------------------------------------------------------------------ sub CreateGraphs($){ my $period = shift; RRDs::graph "$img/requests-$period.png", "-s -1$period", "-t Requests on nginx", "--lazy", "-h", "150", "-w", "700", "-l 0", "-a", "PNG", "-v requests/sec", "DEF:requests=$rrd/nginx.rrd:requests:AVERAGE", "LINE2:requests#336600:Requests", "GPRINT:requests:MAX: Max\\: %5.1lf %S", "GPRINT:requests:AVERAGE: Avg\\: %5.1lf %S", "GPRINT:requests:LAST: Current\\: %5.1lf %Sreq/sec", "HRULE:0#000000"; if ($ERROR = RRDs::error) { print "$0: unable to generate $period graph: $ERROR\n"; } RRDs::graph "$img/connections-$period.png", "-s -1$period", "-t Requests on nginx", "--lazy", "-h", "150", "-w", "700", "-l 0", "-a", "PNG", "-v requests/sec", "DEF:total=$rrd/nginx.rrd:total:AVERAGE", "DEF:reading=$rrd/nginx.rrd:reading:AVERAGE", "DEF:writing=$rrd/nginx.rrd:writing:AVERAGE", "DEF:waiting=$rrd/nginx.rrd:waiting:AVERAGE", "LINE2:total#22FF22:Total", "GPRINT:total:LAST: Current\\: %5.1lf %S", "GPRINT:total:MIN: Min\\: %5.1lf %S", "GPRINT:total:AVERAGE: Avg\\: %5.1lf %S", "GPRINT:total:MAX: Max\\: %5.1lf %S\\n", "LINE2:reading#0022FF:Reading", "GPRINT:reading:LAST: Current\\: %5.1lf %S", "GPRINT:reading:MIN: Min\\: %5.1lf %S", "GPRINT:reading:AVERAGE: Avg\\: %5.1lf %S", "GPRINT:reading:MAX: Max\\: %5.1lf %S\\n", "LINE2:writing#FF0000:Writing", "GPRINT:writing:LAST: Current\\: %5.1lf %S", "GPRINT:writing:MIN: Min\\: %5.1lf %S", "GPRINT:writing:AVERAGE: Avg\\: %5.1lf %S", "GPRINT:writing:MAX: Max\\: %5.1lf %S\\n", "LINE2:waiting#00AAAA:Waiting", "GPRINT:waiting:LAST: Current\\: %5.1lf %S", "GPRINT:waiting:MIN: Min\\: %5.1lf %S", "GPRINT:waiting:AVERAGE: Avg\\: %5.1lf %S", "GPRINT:waiting:MAX: Max\\: %5.1lf %S\\n", "HRULE:0#000000"; if ($ERROR = RRDs::error) { print "$0: unable to generate $period graph: $ERROR\n"; } } **edit cron** บอก cron ให้สั่ง run script ของเราทุกๆ นาที $sudo chmod +x /etc/nginx/rrd_nginx.pl $sudo crontab -e # m h dom mon dow command * * * * * /etc/nginx/rrd_nginx.pl ทดสอบเรียก sudo /etc/nginx/rrd_nginx.pl โปรแกรมจะสร้างรูปขึ้นมาที่ /opt/rrd/html ผมใช้โปรแกรม feh เอาไว้ดูรูป ใครจะเขียน HTML ขึนมาดูรูปก็ได้ครับ sudo apt-get install feh -y 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/
blog comments powered by Disqus