php-fpm回顧和總結

  • 時間久了很容易忘,這裏作個備份
  • FastCGI協議php語言的實現,能夠高效處理來自web端的動態請求
  • php-fpm維護一個或者多個php-cgi進程池,處理請求時不須要頻繁建立進程
  • 因此比傳統的CGI協議要更高效

技術架構

  • 單master - 多worker
  • master
    • 非阻塞,異步IO模型
    • 負責管理worker進程(建立、銷燬、檢查健康狀態等)、監聽鏈接、處理管理員發出的信號、啓動時間循環等。
    • master進程執行的四個階段
      • cgi初始化:外部信號hook註冊、sapi全局變量初始化等;
      • php環境初始化:加載和解析php.ini,加載php模塊等;
      • php-fpm初始化:加載和解析php-fpm.conf,初始化進程池等;
      • php-fpm執行階段:fork worker進程和啓動事件循壞等。
  • worker
    • 阻塞模型
    • 負責接收請求,處理請求,請求結束返回。

建立worker進程的三種方式

  • static: 建立固定數目的worker進程,減小頻繁建立進程的開銷。
  • dynamic: 動態調整worker進程數量,初始時會建立最低數目的worker進程,建立的進程數最大不超過設置的閾值。
  • ondemand: 按需建立,來一個請求建立一個,請求處理完,進程結束。

master處理的信號說明

  • SIGUSR1:從新打開日誌文件,用於文件太大須要備份時的場景,從新打開不會清空原來的文件
    • kill -s USR1 master進程id
  • SIGUSR2: 重啓fpm,包括master和worker,當配置文件更改時,則須要重啓fpm讓配置文件生效
  • SIGQUIT: 平滑關閉fpm,worker處理完請求再退出
  • SIGTERM/SIGINT: 強制關閉fpm,會影響當前正在處理的請求

多進程池配置形式

  • 全局配置文件: php-fpm.conf
[global]
pid=run/php-fpm.pid
error_log=syslog
include=etc/php-fpm.d/*.conf
  • 鏈接池1的配置文件: pool1.conf
[pool1]
listen = 127.0.0.1:9000
listen.mode = 666
user = php-fpm
group = php-fpm
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
rlimit_files = 1024
  • 鏈接池2的配置文件: pool2.conf
[pool2]
#listen = /tmp/php-fcgi.sock
listen = 127.0.0.1:9001
listen.mode = 666
user = php-fpm
group = php-fpm
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
rlimit_files = 1024

管理腳本

#!/bin/bash
#
###################################
#
#@desc php-fpm進程管理
#
#@date 2019-04-04
#
#@author wadeyu
#
##################################

# master進程id保存路徑
MASTER_PID_PATH=$PHP_HOME/var/run/php-fpm.pid

# php-fpm命令
PHP_FPM_CMD=$PHP_HOME/sbin/php-fpm
# 錯誤閃爍提醒
blinkRed(){
    echo -e "\e[05m \e[1;31m $1 \e[0m"
}

# 錯誤提醒:red
errorTip(){
    echo -e "\e[1;31m $1 \e[0m"
}

# 正常提醒:blue
normalTip(){
    echo -e "\e[1;34m $1 \e[0m"
}

# 檢查php-fpm配置是否正常
isCfgOk(){
    $PHP_FPM_CMD -t
    if [[ $? -gt 0 ]]; then errorTip "配置文件異常,請檢查php-fpm配置文件!"
    fi
    return $?
}

# php-fpm正在運行中的主進程數量
getMainFpmCnt(){
    if [[ ! -e $MASTER_PID_PATH ]]; then
        return 0
    fi
    local pid=`cat $MASTER_PID_PATH`
    local cnt=`ps -ef | grep php-fpm | awk -F ' ' '{print $2}' | grep $pid | wc -l`
    return $cnt
}

# 檢查php-fpm進程狀態
checkStatus(){
    if [[ ! -e $MASTER_PID_PATH ]]; then
        errorTip "php-fpm 未運行(pid file not found)......"
        return 1
    fi
    getMainFpmCnt
    local cnt=$?
    local sts=1
    if [[ $cnt -eq 1 ]]; then
        normalTip "php-fpm 正在運行中......"
        sts=0
    else
        errorTip "php-fpm 未運行......"
    fi
    return $sts
}

# 啓動php-fpm
startFpm(){
    isCfgOk || exit 1
    checkStatus && exit 2
    normalTip "啓動php-fpm進程......"
    $PHP_FPM_CMD
    checkStatus
}

# 中止php-fpm
stopFpm(){
    checkStatus
    if [[ $? -eq 1 ]]; then
        return 0
    fi
    pid=`cat $MASTER_PID_PATH`
    normalTip "中止php-fpm進程......"
    kill -s QUIT $pid
    getMainFpmCnt
    local cnt=$?
    while [[ $cnt -gt 0 ]]; do
        sleep 1s
        getMainFpmCnt
        cnt=$?
    done
    normalTip "操做成功!"
}

# 從新加載配置
reloadFpm(){
    checkStatus || exit 1
    pid=`cat $MASTER_PID_PATH`
    kill -s USR2 $pid
    normalTip "reload信號已發出,等待一下子配置生效"
}



case "$1" in
    start)
        startFpm
        ;;
    stop)
        stopFpm
        ;;
    reload)
        reloadFpm
        ;;
    restart)
        stopFpm
        startFpm
        ;;
    status)
        checkStatus
        ;;
    *)
        echo "Usage $0 {start|stop|reload|restart|status}"
        exit 99

esac

參考資料

相關文章
相關標籤/搜索