monit:如何在不使伺服器超載的情況下重新啟動許多 Tomcat?
我的伺服器有幾個單獨的 Apache Tomcat 實例,每個實例都需要大量時間和 CPU 才能啟動。不可能同時啟動所有這些。這會產生過多的 I/O,每個服務將需要更長的時間才能啟動,並且服務甚至可能由於內部超時而無法啟動。
這是一些描述我想要做的虛擬碼。我將如何使用 monitrc 文件完成此操作?
check process service01 with pidfile /var/run/service01.pid start program = "/usr/sbin/service service01 start" with timeout 60 seconds stop program = "/usr/sbin/service service01 stop" if does not exist then wait a random number of seconds (between 2 and 5 minutes) if the cpu load is < 100% then start program else do nothing (check again in the next cycle) check process service02 with pidfile /var/run/service02.pid ....
將為 10 個服務中的每一個重複此程式碼塊。
關鍵步驟是隨機等待。否則,如果伺服器空閒並且沒有服務在執行(例如在 ‘killall -9 java’ 之後),monit 將檢查所有服務,發現 cpu 負載現在很低,並立即啟動所有服務。
我現在已經找到了可以完成這項工作的設置。重啟或多個程序失敗後,檢查CPU負載,每個服務只有在CPU負載低於1或延遲較長時間後才會啟動。下面的腳本在我的環境中工作得很好:
編輯/etc/monitor/monitorrc:
... ## Start Monit in the background (run as a daemon): # set daemon 120 # check services at 2-minute intervals with start delay 240 # optional: delay the first check by 4-minutes (by # # default Monit check immediately after Monit start)
對於每個服務,將其添加到 /etc/monit/conf.d:
check process myname with pidfile /var/run/app0000.pid start program = "/usr/sbin/service app0000 start" with timeout 60 seconds stop program = "/usr/sbin/service app0000 stop" if does not exist then exec "/root/bin/service_with_delay app0000 start"
創建腳本 /root/bin/service_with_delay:
#!/bin/bash ( # Wait for lock on /var/lock/service_with_delay.lock (fd 9) flock -n 9 || exit 1 for i in `seq 1 10`; do # start the service if the cpu load is < 1.0 or after waiting for 300 seconds read load ignore </proc/loadavg flag=`expr ${load} '<' 1` if [ ${flag} -eq 1 ] || [ ${i} -eq 10 ]; then echo `date` service_with_delay $1: pid $$ load ${load} i ${i} - starting >> /var/log/service_with_delay.log /usr/sbin/service $1 start # make sure next script getting the lock sees some load sleep 60 break fi # wait echo `date` service_with_delay $1: pid $$ load ${load} i ${i} >> /var/log/service_with_delay.log sleep 30 done ) 9> /var/lock/service_with_delay.lock
您沒有過多介紹您的作業系統,我只能假設它是 Linux(
kill -9 ...
部分)。我對monit也不太了解,但假設它是一個靈活的解決方案,允許您在服務失敗時重試啟動服務。我假設 Tomcat 實例是使用 shell 啟動腳本啟動的。在這些腳本的開頭添加某處:
# edit the 3 lines to set your limits LOAD_THRESHOLD=0.75 LOCK_TIME=30 TIME_LIMIT=120 LOCK_FILE='/var/lock/tomcat-delay.lock' if [ -z "${TOMCAT_NOLOCK}" ]; then # simple locking mechanism to avoid simultaneous start of instances if [ -f "${LOCK_FILE}" ] && [ $(cat "${LOCK_FILE}") -gt $(date '+%s') ]; then exit 1 else expr $(date '+%s') + ${LOCK_TIME} 1>"${LOCK_FILE}" fi fi T_TIME=0 while true; do # check for non-empty TOMCAT_NOWAIT if [ -n "${TOMCAT_NOWAIT}" ]; then break 1 fi read T_LOAD60 T_REST </proc/loadavg # check current 60 sec. average value for system load if expr ${T_LOAD60} '<' ${LOAD_THRESHOLD} 1>/dev/null; then break 1 fi # check for timeout if [ ${T_TIME} -ge ${TIME_LIMIT} ]; then # change to 'exit 1' to fail on timeout instead of proceeding break 1 fi sleep 1s echo -n '.' T_TIME=$((${T_TIME} + 1)) done
上面的程式碼實際上並不僅僅檢查 CPU 負載,而是檢查系統負載平均值,根據設計,它包括所有可能降低性能的因素。TIME_LIMIT以秒為單位。如果負載在給定時間內未低於給定門檻值,腳本將最終嘗試啟動您的服務 - 最後
break 1
一部分可以更改為exit 1以中止啟動並告訴monit守護程序重試。如果您嘗試手動啟動服務(而不是從monit),它也會等待,我認為這是一個優勢。您可以使用非空值導出 env TOMCAT_NOWAIT以避免它。
**編輯#1:**添加簡單的鎖定機製作為同時實例啟動問題的解決方法。非空環境 TOMCAT_NOLOCK禁用鎖定。將LOCK_TIME 設置為實例的預熱時間,以便正確檢測到高負載。