2014/08/22

Nginx upstream 的容錯設定方法

自己的 Redmine server 是使用 Thin 執行,在透過 Nginx 將 request 轉送給 Thin。

Nginx 中設定 Thin server pool:
upstream redmine_thin_servers {
  server unix:/home/redmine/run/thin.0.socket;
  server unix:/home/redmine/run/thin.1.socket;
  server unix:/home/redmine/run/thin.2.socket;
  server unix:/home/redmine/run/thin.3.socket;
}

Nginx server:
  location / {
    try_files $uri/index.html $uri/index.htm @redmine_thin_servers;
  }

  location @redmine_thin_servers {
    proxy_pass http://redmine_thin_servers;
  }

這樣設定,Nginx 會將 request 平均轉送給 4 個 Thin instance。

但若其中一個 Thin instance 處理叫複雜或是較花時間的工作,如 checkout repository 等,會長時間沒有回應,可能沒辦法再同時處理另一個 request。此時若 Nginx 將另一個 request 轉送到已經 pending 的 Thin instance,使用者就會一直等到 Nginx 預設的 proxy timeout 後,出現 HTTP 500 Internal Sever Error 錯誤訊息。但實際上可以讓 Nginx 暫時略過 pending 的 server,將 request 優先轉送給其他 3 個正在 stand by 的 server。

利用 ngx_http_upstream_module 中的 parameter,將 timeout 的 server 標記先移出 pool,讓 request 不會送到 pending 的 server,過一段時間以後再拉進 pool 繼續使用。

以下設定若該 server 超過 10 秒沒有回應,則移出 pool,過 5 分鐘在拉回 pool:
upstream redmine_thin_servers {
  server unix:/home/redmine/run/thin.0.socket fail_timeout=10s slow_start=300s;
  ....
}

另外也可讓 Nginx 主動去檢查 server status,不要在使用者送 request failed 後才將 server 移出 pool。health_check 會讓 Nginx 主動發送間單的 request,透過 HTTP status 來判斷 server 狀態:
  location / {
    try_files $uri/index.html $uri/index.htm @redmine_thin_servers;
  }

  location @redmine_thin_servers {
    proxy_pass http://redmine_thin_servers;
    health_check interval=3s 
  }


測試機上,不曉得是不是 Nginx 1.6.0 還不支援這幾個參數,以上的設定在 configtest 會出現錯誤訊息:
invalid parameter "slow_start=300s"
unknown directive "health_check"


後來是繞路換一個方法。Nginx 的 ngx_http_proxy_module 中,可以設定當 server 多久沒有收到回應 (proxy_read_timeout) 時,直接當作失效並從 pool 中找下一台 server 送 request:
  location / {
    try_files $uri/index.html $uri/index.htm @redmine_thin_servers;
  }

  location @redmine_thin_servers {
    proxy_pass http://redmine_thin_servers;

    # 超過 3 秒沒有收到 response 則當作 timeout
    proxy_read_timeout 3s;

    # 若 response 是 HTTP 50x 也當作 server 失效
    proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
  }

2014/08/18

MySQL pager

MySQL 中的 query 結果太多時,超過螢幕高度就只能看到最後方的資料,要靠 terminal cache 才能看到前半部。

但其實 MySQL 有 pager 功能:
mysql> pager
Default pager wasn't set, using stdout.

把 pager 設定成 less:
mysql> pager less
PAGER set to 'less'

這樣一來,查詢結果就會送到 less 中,可以按照自己的閱讀速度捲動閱讀。

ps. pager 好像是綁 session,再次登入又要重新設定


ref:
Neat tricks for the MySQL command-line pager

2014/07/14

限制 Linux sudoer 可用的指令

若要讓某個開發人員除錯,可以重新啟動特定 service,但不可以 sudo 做其他事情,可以透過修改 /etc/sudoers 達成:
zero  ALL=(ALL)  /usr/sbin/service httpd [start|stop|restart]*

以上設定,zero 僅能使用 sudo service httpd,但是沒辦法 sudo service mysql 以及其他操作。

ps. sudoers 中的指令,必須是絕對路徑

2014/06/10

免 root 權限修改預設 login shell

Linux 帳號、密碼,通常都是放在 /etc/passwd:
zero:x:1002:1002:,,,:/home/zero:/bin/bash

該列最後一個欄位值「/bin/bash」便是預設要使用的 shell。

由於 /etc/passwd 的檔案權限,不是 root 沒辦法修改
-rw-r--r--  1 root root    1725 May 10 13:14 passwd

若沒有 root 權限,可以透過 chsh、ypchsh 來修改預設 shell。
$ chsh
Password:
Changing the login shell for johnroyer
Enter the new value, or press ENTER for the default
        Login Shell [/bin/sh]: /bin/bash


若使用者帳號設定不存在 local,則使用 ypchsh 做修改,用法相同。