目录
6. 实验完成基于LNMP和Redis的phpmyadmin的会话保持,记录完整步骤
6.2 编译安装 PHP-7.4 和 PHP-Redis 模块
1. 完成nginx编译安装脚本
[root@centos8 ~] cat install-nginx.sh
#! /bin/bash
NGINX_VERSION=1.22.1
#NGINX_VERSION=1.22.0
#NGINX_VERSION=1.20.2
#NGINX_VERSION=1.18.0
NGINX_FILE=nginx-${NGINX_VERSION}.tar.gz
NGINX_URL=http://nginx.org/download/
NGINX_INSTALL_DIR=/apps/nginx
SRC_DIR=/usr/local/src
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
check () {
[ -e ${NGINX_INSTALL_DIR} ] && { color "nginx 已安装,请卸载后再安装" 1; exit; }
cd ${SRC_DIR}
if [ -e ${NGINX_FILE}${TAR} ];then
color "相关文件已准备好" 0
else
color '开始下载 nginx 源码包' 0
wget ${NGINX_URL}${NGINX_FILE}${TAR}
[ $? -ne 0 ] && { color "下载 ${NGINX_FILE}${TAR}文件失败" 1; exit; }
fi
}
install () {
color "开始安装 nginx" 0
if id nginx &> /dev/null;then
color "nginx 用户已存在" 1
else
useradd -s /sbin/nologin -r nginx
color "创建 nginx 用户" 0
fi
color "开始安装 nginx 依赖包" 0
if [ $ID == "centos" ] ;then
if [[ $VERSION_ID =~ ^7 ]];then
yum -y install gcc make pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
elif [[ $VERSION_ID =~ ^8 ]];then
yum -y install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
else
color '不支持此系统!' 1
exit
fi
elif [ $ID == "rocky" ];then
yum -y install gcc make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
else
apt update
apt -y install gcc make libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev
fi
[ $? -ne 0 ] && { color "安装依赖包失败" 1; exit; }
cd $SRC_DIR
tar xf ${NGINX_FILE}
NGINX_DIR=`echo ${NGINX_FILE}| sed -nr 's/^(.*[0-9]).*/\1/p'`
cd ${NGINX_DIR}
./configure --prefix=${NGINX_INSTALL_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
make -j $CPUS && make install
[ $? -eq 0 ] && color "nginx 编译安装成功" 0 || { color "nginx 编译安装失败,退出!" 1 ;exit; }
chown -R nginx.nginx ${NGINX_INSTALL_DIR}
ln -s ${NGINX_INSTALL_DIR}/sbin/nginx /usr/local/sbin/nginx
echo "PATH=${NGINX_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/nginx.sh
cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=${NGINX_INSTALL_DIR}/sbin/nginx -t
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now nginx &> /dev/null
systemctl is-active nginx &> /dev/null || { color "nginx 启动失败,退出!" 1 ; exit; }
color "nginx 安装完成" 0
}
check
install
2. 完成nginx平滑升级,总结步骤
- 只有旧版nginx的master和worker进程
- 旧版和新版nginx的master和worker进程并存,由旧版nginx接收处理用户的新请求
- 旧版和新版nginx的master和worker进程并存,由新版nginx接收处理用户的新请求
- 只有新版nginx的master和worker进程
# 下载最新稳定版[root@centos8 ~] #wget http://nginx.org/download/nginx-1.20.1.tar.gz[root@centos8 ~] #tar xvf nginx-1.20.1.tar.gz[root@centos8 ~] #cd nginx-1.20.1# 查看当前使用的版本及编译选项。结果如下:[root@centos8 nginx-1.20.1] #/apps/nginx/sbin/nginx -Vnginx version: nginx/1.18.0built by gcc 8 .3.1 20191121 (Red Hat 8 .3.1-5) (GCC)built with OpenSSL 1 .1.1g FIPS 21 Apr 2020TLS SNI support enabledconfigure arguments: --prefix = /apps/nginx --user = nginx --group = nginx --withhttp_ssl_module --with-http_v2_module --with-http_realip_module --withhttp_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream--with-stream_ssl_module --with-stream_realip_module#configure arguments 后面是以前编译时的参数。现在编译使用一样的参数# 开始编译新版本[root@centos8 nginx-1.20.1] #./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --withhttp_realip_module --with-http_stub_status_module --with-http_gzip_static_module--with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module# 只执行 make ,不执行 make install[root@centos8 nginx-1.20.1] #make[root@centos8 nginx-1.20.1] #objs/nginx -vnginx version: nginx/1.20.1# 查看两个版本[root@centos8 nginx-1.20.1] #ll objs/nginx /apps/nginx/sbin/nginx-rwxr-xr-x 1 nginx nginx 7591096 Jun 7 16 :28 /apps/nginx/sbin/nginx-rwxr-xr-x 1 root root 7723272 Jun 7 17 :27 objs/nginx# 把之前的旧版的 nginx 命令备份[root@centos8 nginx-1.20.1] #cp /apps/nginx/sbin/nginx /opt/nginx.old# 把新版本的 nginx 命令复制过去覆盖旧版本程序文件 , 注意 : 需要加 -f 选项强制覆盖 , 否则会提示 Text file busy[root@centos8 nginx-1.20.1] #cp -f ./objs/nginx /apps/nginx/sbin/# 如果 cp 不加 -f 选项,会出现下面提示[root@rocky8 nginx-1.21.6] #cp objs/nginx /apps/nginx/sbin/cp : overwrite '/apps/nginx/sbin/nginx' ? ycp : cannot create regular file '/apps/nginx/sbin/nginx' : Text file busy# 检测新版本和配置文件语法兼职容性[root@centos8 nginx-1.20.1] #/apps/nginx/sbin/nginx -t# 发送信号 USR2 平滑升级可执行程序 , 将存储有旧版本主进程 PID 的文件重命名为 nginx.pid.oldbin ,并启动新的nginx# 此时两个 master 的进程都在运行 , 只是旧的 master 不在监听 , 由新的 master 监听 80# 此时 Nginx 开启一个新的 master 进程,且这个新 master 进程会生成新的 worker 进程,即升级后的 Nginx 进程,此时老的进程不会自动退出,新的请求仍由旧进程处理。[root@centos8 nginx-1.20.1] #kill -USR2 `cat /apps/nginx/logs/nginx.pid`# 可以看到两个 master, 新的 master 是旧版 master 的子进程 , 并生成新版的 worker 进程# 注意 : 在 Nginx-1.22.1 版中如果看不到下面新版进程 , 需要重新使用 service 方式重新启动 nginx 服务再发送USR2 信号[root@centos8 nginx-1.20.1] #ps auxf|grep nginxroot 12018 0 .0 0 .0 12112 1092 pts/0 S + 17 :32 0 :00 |\_ grep --color = auto nginxroot 8814 0 .0 0 .2 42460 3760 ? Ss 16 :58 0 :00 nginx: masterprocess /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.confnginx 8957 0 .0 0 .2 77172 4724 ? S 17 :23 0 :00 \_ nginx:worker processnginx 8958 0 .0 0 .2 77172 4724 ? S 17 :23 0 :00 \_ nginx:worker processroot 12014 0 .0 0 .3 42448 5512 ? S 17 :32 0 :00 \_ nginx:master process /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.confnginx 12015 0 .0 0 .2 77192 4904 ? S 17 :32 0 :00 \_nginx: worker processnginx 12016 0 .0 0 .2 77192 4908 ? S 17 :32 0 :00 \_nginx: worker process[root@centos8 nginx-1.20.1] #lsof -i :80COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEnginx 8814 root 8u IPv4 40843 0t0 TCP *:http (LISTEN)nginx 8957 nginx 8u IPv4 40843 0t0 TCP *:http (LISTEN)nginx 8958 nginx 8u IPv4 40843 0t0 TCP *:http (LISTEN)nginx 12014 root 8u IPv4 40843 0t0 TCP *:http (LISTEN)nginx 12015 nginx 8u IPv4 40843 0t0 TCP *:http (LISTEN)nginx 12016 nginx 8u IPv4 40843 0t0 TCP *:http (LISTEN)# 如果有新请求,仍由旧版本提供服务[root@ubuntu2204 ~] #curl -I http://10.0.0.200HTTP/1.1 200 OKServer: nginx/1.18.0# 先关闭旧 nginx 的 worker 进程 , 而不关闭旧 nginx 主进程方便回滚# 向原老的 Nginx 主进程发送 WINCH 信号,它会平滑关闭老的工作进程(主进程不退出),这时所有新请求都会由新版Nginx 处理[root@centos8 nginx-1.20.1] #kill -WINCH `cat /apps/nginx/logs/nginx.pid.oldbin`# 如果旧版 worker 进程有用户的旧的请求 , 会一直等待处理完后才会关闭,即平滑关闭[root@centos8 nginx-1.20.1] #ps auxf|grep nginxroot 12066 0 .0 0 .0 12112 1112 pts/0 S + 17 :38 0 :00 |\_ grep --color = auto nginxroot 8814 0 .0 0 .1 42460 2656 ? Ss 16 :58 0 :00 nginx: masterprocess /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.confnginx 8957 0 .0 0 .1 77172 3484 ? S 17 :23 0 :00 \_ nginx:worker process is shutting downroot 12014 0 .0 0 .2 42448 3664 ? S 17 :32 0 :00 \_ nginx:master process /apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.confnginx 12015 0 .0 0 .1 77192 3284 ? S 17 :32 0 :00 \_nginx: worker processnginx 12016 0 .0 0 .1 77192 3280 ? S 17 :32 0 :00 \_nginx: worker process[root@centos8 nginx-1.20.1] #pstree -p|grep nginx|-nginx(8814)---nginx(12014)- + -nginx (12015)| `-nginx(12016)# 如果有新请求,由新版本提供服务[root@ubuntu2204 ~] #curl -I http://10.0.0.200HTTP/1.1 200 OKServer: nginx/1.20.1################# 注意 : 此处如果是虚拟机先做快照方便测试回滚 ################################################ 升级 ##################################经过一段时间测试,新版本服务没问题,最后发送 QUIT 信号 , 退出老的 master ,完成全部升级过程[root@centos8 nginx-1.20.1] #kill -QUIT `cat /apps/nginx/logs/nginx.pid.oldbin`# 查看版本是不是已经是新版了[root@centos8 nginx-1.20.1] #nginx -vnginx version: nginx/1.20.1[root@centos8 nginx-1.20.1] #curl -I 127.0.0.1HTTP/1.1 200 OKServer: nginx/1.20.1Date: Mon, 07 Jun 2021 09 :48:48 GMTContent-Type: text/htmlContent-Length: 612Last-Modified: Mon, 07 Jun 2021 08 :28:12 GMTConnection: keep-aliveETag: "60bdd89c-264"Accept-Ranges: bytes# 如果有旧的连接,不会立即关闭旧版本的 Master 和对应的 Worker 进程,直到所有旧连接断开,才会关闭所的旧的进程[root@ubuntu2204 nginx-1.20.1] #ps auxf|grep nginxroot 4381 0 .0 0 .1 9584 2308 pts/0 S + 10 :44 0 :00 | \_grep--color = auto nginxroot 1215 0 .0 0 .1 10160 2088 ? Ss 10 :12 0 :00 nginx: masterprocess /apps/nginx/sbin/nginxnginx 1219 0 .0 0 .2 10896 4428 ? S 10 :12 0 :00 \_ nginx:worker process is shutting downroot 4342 0 .0 0 .3 10172 6476 ? S 10 :34 0 :00 \_ nginx:master process /apps/nginx/sbin/nginxnginx 4343 0 .0 0 .2 10908 4104 ? S 10 :34 0 :00 \_nginx: worker processnginx 4344 0 .0 0 .1 10908 3608 ? S 10 :34 0 :00 \_nginx: worker processnginx 4345 0 .0 0 .2 10908 4168 ? S 10 :34 0 :00 \_nginx: worker processnginx 4346 0 .0 0 .1 10908 3608 ? S 10 :34 0 :00 \_nginx: worker process###################### 回滚 ############################################如果升级的新版本发现问题需要回滚 , 可以发送 HUP 信号 , 重新拉起旧版本的 worker[root@centos8 nginx-1.20.1] #kill -HUP `cat /apps/nginx/logs/nginx.pid.oldbin`[root@centos8 nginx-1.20.1] #pstree -p |grep nginx|-nginx(8814)- + -nginx (12014)- + -nginx (12015)| | `-nginx(12016)| |-nginx(12090)| `-nginx(12091)# 最后关闭新版的 master 和 worker ,如果不执行上面的 HUP 信号,此步 QUIT 信号也可以重新拉起旧版本的worker进程[root@centos8 nginx-1.20.1] #kill -QUIT `cat /apps/nginx/logs/nginx.pid`# 恢复旧版的文件[root@rocky8 ~] #mv /opt/nginx.old /apps/nginx/sbin/mv : overwrite '/apps/nginx/sbin/nginx' ? y
3. 总结nginx核心配置,并实现nginx多虚拟主机
- 主配置文件:nginx.conf
- 子配置文件: include conf.d/*.conf
- fastcgi, uwsgi,scgi 等协议相关的配置文件
- mime.types:支持的mime类型,MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,MIME消息能包含文本、图像、音频、视频以及其他应用程序专用的数据,是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。MIME参考文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_ Typ
配置文件由指令与指令块构成每条指令以 ; 分号结尾,指令与值之间以空格符号分隔可以将多条指令放在同一行 , 用分号分隔即可 , 但可读性差 , 不推荐指令块以 { } 大括号将多条指令组织在一起 , 且可以嵌套指令块include 语句允许组合多个配置文件以提升可维护性使用 # 符号添加注释,提高可读性使用 $ 符号使用变量部分指令的参数支持正则表达式
主配置文件结构:四部分
main block :主配置段,即全局配置段,对 http,mail 都有效# 事件驱动相关的配置event {...}#http/https 协议相关配置段http {...}# 默认配置文件不包括下面两个块#mail 协议相关配置段mail {...}#stream 服务器相关配置段stream {...}
默认的nginx.conf 配置文件格式说明
# 全局配置端,对全局生效,主要设置 nginx 的启动用户 / 组,启动的工作进程数量,工作模式, Nginx 的 PID路径,日志路径等。user nginx nginx;worker_processes 1 ; # 启动工作进程数数量events { #events 设置块,主要影响 nginx 服务器与用户的网络连接,比如是否允许同时接受多个网络连接,使用哪种事件驱动模型处理请求,每个工作进程可以同时支持的最大连接数,是否开启对多工作进程下的网络连接进行序列化等。worker_connections 1024 ; # 设置单个 nginx 工作进程可以接受的最大并发,作为 web 服务器的时候最大并发数为worker_connections * worker_processes ,作为反向代理的时候为(worker_connections * worker_processes)/2}http { #http 块是 Nginx 服务器配置中的重要部分,缓存、代理和日志格式定义等绝大多数功能和第三方模块都可以在这设置,http 块可以包含多个 server 块,而一个 server 块中又可以包含多个 location 块, server块可以配置文件引入、 MIME-Type 定义、日志自定义、是否启用 sendfile 、连接超时时间和单个链接的请求上限等。include mime.types;default_type application/octet-stream;sendfile on; # 作为 web 服务器的时候打开 sendfile 加快静态文件传输,指定是否使用sendfile 系统调用来传输文件 ,sendfile 系统调用在两个文件描述符之间直接传递数据 ( 完全在内核中操作) ,从而避免了数据在内核缓冲区和用户缓冲区之间的拷贝,操作效率很高,被称之为零拷贝,硬盘 >> kernel buffer (快速拷贝到 kernelsocket buffer) >> 协议栈。keepalive_timeout 65 ; # 长连接超时时间,单位是秒server { # 设置一个虚拟机主机,可以包含自己的全局快,同时也可以包含多个 location 模块。比如本虚拟机监听的端口、本虚拟机的名称和IP 配置,多个 server 可以使用一个端口,比如都使用 80 端口提供web服务、listen 80 ; # 配置 server 监听的端口server_name localhost; # 本 server 的名称,当访问此名称的时候 nginx 会调用当前serevr 内部的配置进程匹配。location / { #location 其实是 server 的一个指令,为 nginx 服务器提供比较多而且灵活的指令,都是在 location 中体现的,主要是基于 nginx 接受到的请求字符串,对用户请求的 UIL 进行匹配,并对特定的指令进行处理,包括地址重定向、数据缓存和应答控制等功能都是在这部分实现,另外很多第三方模块的配置也是在location 模块中配置。root html; # 相当于默认页面的目录名称,默认是安装目录的相对路径,可以使用绝对路径配置。index index.html index.htm; # 默认的页面文件名称}error_page 500 502 503 504 /50x.html; # 错误页面的文件名称location = /50x.html { #location 处理对应的不同错误码的页面定义到 /50x.html ,这个跟对应其 server 中定义的目录下。root html; # 定义默认页面所在的目录}}# 和邮件相关的配置#mail {# ...# } mail 协议相关配置段#tcp 代理配置, 1.9 版本以上支持#stream {# ...# } stream 服务器相关配置段# 导入其他路径的配置文件#include /apps/nginx/conf.d/*.conf}
http {...... # 各 server 的公共配置server { # 每个 server 用于定义一个虚拟主机 , 第一个 server 为默认虚拟服务器...}server {...server_name # 虚拟主机名root # 主目录alias # 路径别名location [OPERATOR] URL { # 指定 URL 的特性...if CONDITION {...}}}}
http {include mime.types; # 导入支持的文件类型 , 是相对于 /apps/nginx/conf 的目录default_type application/octet-stream; # 除 mime.types 中文件类型外 , 设置其它文件默认类型,访问其它类型时会提示下载不匹配的类型文件# 日志配置部分#log_format main '$remote_addr - $remote_user [$time_local] "$request" '# '$status $body_bytes_sent "$http_referer" '# '"$http_user_agent" "$http_x_forwarded_for"';#access_log logs/access.log main;# 自定义优化参数sendfile on;#tcp_nopush on; # 开启 sendfile 的情况下,合并请求后统一发送给客户端 , 必须开启sendfile#tcp_nodelay off; # 开启 keepalived 模式下的连接是否启用 TCP_NODELAY 选项,为 off 时,延迟 0.2s 发送,默认 On 时,不延迟发送,立即发送用户响应报文。#keepalive_timeout 0;keepalive_timeout 65 65 ; # 设置会话保持时间 , 第二个值为响应首部 :keepAlived:timeout=65, 可以和第一个值不同#gzip on; # 开启文件压缩server {listen 80 default_server; # 设置监听地址和端口 , 多个虚拟机时当前是否是默认的虚拟主机, default_server 表示是默认主机,否则排在前面 server 为默认主机server_name localhost; # 设置 server name ,可以以空格隔开写多个并支持正则表达式,如 :*.wang.com www.wang.* ~^www\d+\.wang\.com$ 示例 : .wang.org 相当于*.wang.org 和 wang.org#charset koi8-r; # 设置编码格式,默认是俄语格式,建议改为 utf-8#access_log logs/host.access.log main;location / {root html;index index.html index.htm;}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html#error_page 500 502 503 504 /50x.html; # 定义错误页面location = /50x.html {root html;}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ { # 以 http 的方式转发 php 请求到指定 web 服务器# proxy_pass http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ { # 以 fastcgi 的方式转发 php 请求到 php 处理# root html;# fastcgi_pass 127.0.0.1:9000;# fastcgi_index index.php;# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;# include fastcgi_params;#}# deny access to .htaccess files, if Apache's document root# concurs with nginx's one##location ~ /\.ht { # 拒绝 web 形式访问指定文件,如很多的网站都是通过 .htaccess 文件来改变自己的重定向等功能。# deny all;#}location ~ /passwd.html {deny all;}}# another virtual host using mix of IP-, name-, and port-based configuration##server { # 自定义虚拟 server# listen 8000;# listen somename:8080;# server_name somename alias another.alias;# location / {# root html;# index index.html index.htm; # 指定默认网页文件,此指令由ngx_http_index_module 模块提供# }#}# HTTPS server##server { #https 服务器配置# listen 443 ssl;# server_name localhost;# ssl_certificate cert.pem;# ssl_certificate_key cert.key;# ssl_session_cache shared:SSL:1m;# ssl_session_timeout 5m;# ssl_ciphers HIGH:!aNULL:!MD5;# ssl_prefer_server_ciphers on;# location / {# root html;# index index.html index.htm;# }#}
location指令
# 语法规则:location [ = | ~ | ~* | ^~ ] uri { ... }= # 用于标准 uri 前,需要请求字串与 uri 精确匹配,大小敏感 , 如果匹配成功就停止向下匹配并立即处理请求^~ # 用于标准 uri 前,表示包含正则表达式 , 并且匹配以指定的正则表达式开头 , 对 uri 的最左边部分做匹配检查,不区分字符大小写~ # 用于标准 uri 前,表示包含正则表达式 , 并且区分大小写~* # 用于标准 uri 前,表示包含正则表达式 , 并且不区分大写不带符号 # 匹配起始于此 uri 的所有的 uri\ # 用于标准 uri 前,表示包含正则表达式并且转义字符。可以将 . * ? 等转义为普通符号# 匹配优先级从高到低:= , ^~, ~/~*, 不带符号
范例:
# cat /etc/nginx/conf.d/www.wang.org.confserver {listen 80 ;server_name location.wang.org;location = / {default_type text/html;return 200 'location = /' ;}location / {default_type text/html;return 200 'location /' ;}location /documents/ {default_type text/html;return 200 'location /documents/' ;}location ^~ /images/ {default_type text/html;return 200 'location ^~ /images/' ;}location ~* \.(gif|jpg|jpeg) $ {default_type text/html;return 200 'location ~* \.(gif|jpg|jpeg)' ;}}# 测试结果如下 , 建议是 curl 测试#1. 请求 http://location.wang.org/ 会被 location =/ 匹配#2. 请求 http://location.wang.org/index.html 会被 location / 匹配#3. 请求 http://location.wang.org/documents/1.html 会被 location /documents/ 匹配#4. 请求 http://location.wang.org/images/1.gif 会被 location ^~ /images/ 匹配#5. 请求 http://location.wang.org/documents/1.jpg 会被 location ~* \.(gif|jpg|jpeg)$ 匹配
Location @重定向
# cat /etc/nginx/conf.d/www.wang.org.confserver {listen 80 ;server_name www.wang.org;root /data/www;location / {index index.html;}# 如果出现异常 , 则重新定向到 @error_404 这个 location 上error_page 404 @error_404;location @error_404 {default_type text/html;charset utf8;return 200 ' 你访问的页面可能走丢了 !' ;}}
实现多虚拟主机
server {
listen 80;
server_name huang.com;
location / {
proxy_set header Host $host;
proxy_set header X-Real-IP $remote_addr;
proxy_set header X-Forwarded-For $remote_addr;
root /data/huang.com/html
index index.html;
}
}
server {
listen 80;
server_name huang.org;
location / {
proxy_set header Host $host;
proxy_set header X-Real-IP $remote_addr;
proxy_set header X-Forwarded-For $remote_addr;
root /data//huang.org/html
index index.html;
}
}
server {
listen 80;
server_name huang.net;
location / {
proxy_set header Host $host;
proxy_set header X-Real-IP $remote_addr;
proxy_set header X-Forwarded-For $remote_addr;
root /data/huang.net/html
index index.html;
}
}
4. 总结nginx日志格式定制
Syntax: access_log path [format [buffer = size] [gzip[ = level]] [flush = time][if = condition]];access_log off; # 关闭访问日志 , 比如在反向代理上可以关闭日志功能Default:access_log logs/access.log combined;Context: http, server, location, if in location, limit_except
$remote_addr # 记录客户端 IP 地址$remote_user # 记录客户端用户名$time_local # 记录通用的本地时间$time_iso8601 # 记录 ISO8601 标准格式下的本地时间$request # 记录请求的方法以及请求的 http 协议$status # 记录请求状态码 ( 用于定位错误信息 )$body_bytes_sent # 发送给客户端的资源字节数,不包括响应头的大小$bytes_sent # 发送给客户端的总字节数 $msec # 日志写入时间。单位为秒,精度是毫秒。$http_referer # 记录从哪个页面链接访问过来的$http_user_agent # 记录客户端浏览器相关信息$http_x_forwarded_for # 记录客户端 IP 地址$request_length # 请求的长度(包括请求行,请求头和请求正文)。$request_time # 请求花费的时间,单位为秒,精度毫秒# 注 : 如果 Nginx 位于负载均衡器, nginx 反向代理之后, web 服务器无法直接获取到客 户端真实的 IP 地址。# $remote_addr 获取的是反向代理的 IP 地址。 反向代理服务器在转发请求的 http 头信息中,# 增加 X-Forwarded-For 信息,用来记录客户端 IP 地址和客户端请求的服务器地址
默认日志格式
http {log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"' ;access_log /var/log/nginx/access.log main;
# 注意 : 此指令只支持 http 块 , 不支持 server 块log_format access_log_format '$remote_addr - $remote_user [$time_local]"$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"''$server_name:$server_port' ;# 注意 : 此指令一定要在放在 log_format 命令后access_log logs/access.log access_log_format;# 重启 nginx 并访问测试日志格式== > /apps/nginx/logs/access.log < ==10 .0.0.1 - - [22/Feb/2019:08:44:14 + 0800 ] "GET /favicon.ico HTTP/1.1" 404 162 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0 " " - "www.wang.org:80
5. 总结 nginx反向代理及https安全加密
- 正向代理:代理客户端访问服务器,可以实现缓存,科学上网,访问控制等功能
- 反向代理:reverse proxy,指的是代理外网用户的请求到内部的指定的服务器,并将数据返回给用户的一种方式,这是用的比较多的一种方式。
ngx_http_proxy_module : # 将客户端的请求以 http 协议转发至指定服务器进行处理ngx_http_upstream_module # 用于定义为 proxy_pass,fastcgi_pass,uwsgi_pass 等指令引用的后端服务器分组ngx_stream_proxy_module : # 将客户端的请求以 tcp 协议转发至指定服务器处理ngx_http_fastcgi_module : # 将客户端对 php 的请求以 fastcgi 协议转发至指定服务器助理ngx_http_uwsgi_module : # 将客户端对 Python 的请求以 uwsgi 协议转发至指定服务器处理
5.1 Nginx 反向代理:
# 官方文档: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_passSyntax: proxy_pass URL;Default: —Context: location, if in location, limit_except# 用来设置将客户端请求转发给的后端服务器的主机,可以是主机名 ( 将转发至后端服务做为主机头首部 ) 、IP:port 方式# 说明 : proxy_pass http://FQDN/ 中的 FQDN 决定转发至后端哪个虚拟主机 , 而与用户请求的 URL 无关# 如果转到后端的哪个服务器由用户请求决定 , 可以向后端服务转发请求的主机头实现# 示例 : proxy_set_header Host $http_host;# 示例 :location /web {index index.html;proxy_pass http://10.0.0.18:8080; #8080 后面无 uri, 即无 / 符号 , 需要将 location 后面url 附加到 proxy_pass 指定的 url 后面 , 此行为类似于 root#proxy_pass 指定的 uri 不带斜线将访问的 /web, 等于访问后端服务器http://10.0.0.18:8080/web/index.html ,即后端服务器配置的站点根目录下要有 web 目录才可以被访问# http://nginx/web/index.html ==> http://10.0.0.18:8080/web/index.htmlproxy_pass http://10.0.0.18:8080/; #8080 后面有 uri, 即有 / 符号 , 相当于置换 , 即访问 /web 时实际返回 proxy_pass 后面 uri 内容 . 此行为类似于 alias#proxy_pass 指定的 uri 带斜线,等于访问后端服务器的 http://10.0.0.18:8080/index.html 内容返回给客户端} # http://nginx/web/index.html ==> http://10.0.0.18:8080# 重启 Nginx 测试访问效果:#curl -L http://www.wang.org/web# 如果 location 定义其 uri 时使用了正则表达式模式 ( 包括 ~,~*, 但不包括 ^~) ,则 proxy_pass 之后必须不能使用uri; 即不能有 / , 用户请求时传递的 uri 将直接附加至后端服务器之后server {...server_name HOSTNAME;location ~|~* /uri/ {proxy_pass http://host:port; #proxy_pass 后面的 url 不能加 /}...}http://HOSTNAME/uri/ -- > http://host/uri/proxy_hide_header field;# 用于 nginx 作为反向代理的时候,在返回给客户端 http 响应时,隐藏后端服务器相应头部的信息,可以设置在http,server 或 location 块# 示例 : 隐藏后端服务器 ETag 首部字段location /web {index index.html;proxy_pass http://10.0.0.18:8080/;proxy_hide_header ETag;}proxy_pass_header field;# 默认 nginx 在响应报文中不传递后端服务器的首部字段 Date, Server, X-Pad, X-Accel 等参数,如果要传递的话则要使用 proxy_pass_header field 声明将后端服务器返回的值传递给客户端#field 首部字段大小不敏感# 示例 : 透传后端服务器的 Server 和 Date 首部给客户端 , 同时不再响应报中显示前端服务器的 Server 字段proxy_pass_header Server;proxy_pass_header Date;proxy_pass_request_body on | off;# 是否向后端服务器发送 HTTP 实体部分 , 可以设置在 http,server 或 location 块,默认即为开启proxy_pass_request_headers on | off;# 是否将客户端的请求头部转发给后端服务器,可以设置在 http,server 或 location 块,默认即为开启proxy_set_header;# 可更改或添加客户端的请求头部信息内容并转发至后端服务器,比如在后端服务器想要获取客户端的真实 IP的时候,就要更改每一个报文的头部# 示例 :#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;$proxy_add_x_forwarded_forthe “X-Forwarded-For” client request header field with the $remote_addr variableappended to it, separated by a comma. If the “X-Forwarded-For” field is notpresent in the client request header, the $proxy_add_x_forwarded_for variable isequal to the $remote_addr variable.proxy_set_header X-Real-IP $remote_addr ;# 添加 HOST 到报文头部,如果客户端为 NAT 上网那么其值为客户端的共用的公网 IP 地址,常用于在日之中记录客户端的真实 IP 地址。# 在后端 httpd 服务器修改配置 , 添加日志记录 X-Forwarded-For 字段LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{XReal-IP}i\"" combinedproxy_connect_timeout time;# 配置 nginx 服务器与后端服务器尝试建立连接的超时时间,默认为 60 秒,用法如下:proxy_connect_timeout 6s;#60s 为自定义 nginx 与后端服务器建立连接的超时时间 , 超时会返回客户端 504 响应码proxy_read_timeout time;# 配置 nginx 服务器向后端服务器或服务器组发起 read 请求后,等待的超时时间,默认 60sproxy_send_timeout time;# 配置 nginx 项后端服务器或服务器组发起 write 请求后,等待的超时 时间,默认 60sproxy_http_version 1 .0;# 用于设置 nginx 提供代理服务的 HTTP 协议的版本,默认 http 1.0, 建议修改 1.1 支持长连接# 注意 : 需要配合实现 proxy_set_header Connection "" 实现长连接,否则在高并发时,可能会造成server 端出现大量 TIME_WAITproxy_ignore_client_abort off;# 当客户端网络中断请求时, nginx 服务器中断其对后端服务器的请求。即如果此项设置为 on 开启,则服务器会忽略客户端中断并一直等着代理服务执行返回,如果设置为 off ,则客户端中断后 Nginx 也会中断客户端请求并立即记录 499 日志,默认为 offproxy_headers_hash_bucket_size 128 ;# 当配置了 proxy_hide_header 和 proxy_set_header 的时候,用于设置 nginx 保存 HTTP 报文头的 hash表的上限proxy_headers_hash_max_size 512 ;# 设置 proxy_headers_hash_bucket_size 的最大可用空间server_names_hash_bucket_size 512 ;#server_names 的 hash 表申请空间大小server_names_hash_max_size 512 ;# 设置服务器名称 hash 表的上限大小proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 |http_503 | http_504;# 当一台后端朋务器出错 , 超时 , 无效首部 ,500 等时 , 切换至下一个后端服务器提供服务
[root@centos8 ~] # cat /apps/nginx/conf/conf.d/pc.confserver {listen 80 ;server_name www.huang.org;location / {proxy_pass http://10.0.0.100/; # http://10.0.0.18/ 最后的 / 可加或不加proxy_set_header Host $http_host ; # 转发主机头至后端服务器proxy_connect_timeout 10s;}}# 重启 Nginx 并访问测试
5.2 Https 加密
https 实现过程如下:1. 客户端发起 HTTPS 请求:客户端访问某个 web 端的 https 地址,一般都是 443 端口2. 服务端的配置:采用 https 协议的服务器必须要有一套证书,可以通过一些组织申请,也可以自己制作,目前国内很多网站都自己做的,当你访问一个网站的时候提示证书不可信任就表示证书是自己做的,证书就是一个公钥和私钥匙,就像一把锁和钥匙,正常情况下只有你的钥匙可以打开你的锁,你可以把这个送给别人让他锁住一个箱子,里面放满了钱或秘密,别人不知道里面放了什么而且别人也打不开,只有你的钥匙是可以打开的。3. 传送证书:服务端给客户端传递证书,其实就是公钥,里面包含了很多信息,例如证书得到颁发机构、过期时间等等。4. 客户端解析证书:这部分工作是有客户端完成的,首先回验证公钥的有效性,比如颁发机构、过期时间等等,如果发现异常则会弹出一个警告框提示证书可能存在问题,如果证书没有问题就生成一个随机值,然后用证书对该随机值进行加密,就像2 步骤所说把随机值锁起来,不让别人看到。5. 传送 4 步骤的加密数据:就是将用证书加密后的随机值传递给服务器,目的就是为了让服务器得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值进行加密解密了。6. 服务端解密信息:服务端用私钥解密 5 步骤加密后的随机值之后,得到了客户端传过来的随机值 ( 私钥 ) ,然后把内容通过该值进行对称加密,对称加密就是将信息和私钥通过算法混合在一起,这样除非你知道私钥,不然是无法获取其内部的内容,而正好客户端和服务端都知道这个私钥,所以只要机密算法够复杂就可以保证数据的安全性。7. 传输加密后的信息 :服务端将用私钥加密后的数据传递给客户端,在客户端可以被还原出原数据内容。8. 客户端解密信息:客户端用之前生成的私钥获解密服务端传递过来的数据,由于数据一直是加密的,因此即使第三方获取到数据也无法知道其详细内容。
Https 配置参数
ssl on | off;# 为指定的虚拟主机配置是否启用 ssl 功能,此功能在 1.15.0 废弃,使用 listen [ssl] 替代listen 443 ssl http2;ssl_certificate /path/to/file;# 指向包含当前虚拟主机和 CA 的两个证书信息的文件,一般是 crt 文件ssl_certificate_key /path/to/file;# 当前虚拟主机使用的私钥文件,一般是 key 文件ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];# 支持 ssl 协议版本,早期为 ssl 现在是 TLS ,默认为后三个 , 最新的浏览器已经不再支持 TLS1.0 和 TLS1.1ssl_session_cache off | none | [builtin[:size]] [shared:name:size];# 配置 ssl 缓存off : # 关闭缓存none: # 通知客户端支持 ssl session cache ,但实际不支持builtin[:size] : # 使用 OpenSSL 内建缓存,为每 worker 进程私有 , 使用此内置缓存可能会导致内存碎片[shared:name:size] : # 在各 worker 之间使用一个共享的缓存,需要定义一个缓存名称和缓存空间大小,1M 可以存储 4000 个会话信息,多个虚拟主机可以使用相同的缓存名称ssl_session_timeout time; # 客户端连接可以复用 ssl session cache 中缓存的有效时长,默认 5 分钟
示例: 官方性能优化
https://nginx.org/en/docs/http/ngx_http_ssl_module.htmlTo reduce the processor load it is recommended toset the number of worker processes equal to the number of processors,enable keep-alive connections,enable the shared session cache,disable the built-in session cache,and possibly increase the session lifetime (by default, 5 minutes):worker_processes auto;http {...server {listen 443 ssl http2;keepalive_timeout 70 ;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;ssl_certificate /usr/local/nginx/conf/cert.pem;ssl_certificate_key /usr/local/nginx/conf/cert.key;ssl_session_cache shared:SSL:10m;ssl_session_timeout 10m;...}
6. 实验完成基于LNMP和Redis的phpmyadmin的会话保持,记录完整步骤
6.1 准备 MySQL 和 Redis
[root@ubuntu2004 ~] #apt -y install mysql-server redis# 配置可不修改[root@ubuntu2004 ~] #vim /etc/mysql/mysql.conf.d/mysqld.cnf[mysqld]default_authentication_plugin = mysql_native_password[root@ubuntu2004 ~] #systemctl restart mysql# 创建用户并授权[root@ubuntu2004 ~] #mysqlmysql> create user admin@ 'localhost' identified with mysql_native_password by'123456' ;mysql> grant all on *.* to admin@ 'localhost' ;
6.2 编译安装 PHP-7.4 和 PHP-Redis 模块
[root@ubuntu2004 ~] #apt -y install gcc make autoconf libpcre3 libpcre3-devopenssl libssl-dev zlib1g-dev libxml2-dev pkg-config libsqlite3-dev libtool[root@ubuntu2004 ~] #groupadd -g 80 www && useradd -u 80 -g www www# 编译 oniguruma[root@ubuntu2004 ~] #wget -O oniguruma-6.9.4.tar.gzhttps://github.com/kkos/oniguruma/archive/refs/tags/v6.9.4.tar.gz[root@ubuntu2004 ~] #tar xf oniguruma-6.9.4.tar.gz[root@ubuntu2004 oniguruma-6.9.4] #./autogen.sh[root@ubuntu2004 oniguruma-6.9.4] #./configure && make && make install# 编译 PHP7.4[root@ubuntu2004 ~] #wget https://www.php.net/distributions/php-7.4.30.tar.gz[root@ubuntu2004 ~] #tar xf php-7.4.30.tar.gz[root@ubuntu2004 ~] #cd ../php-7.4.30[root@ubuntu2004 php-7.4.30] #./configure --prefix=/apps/php --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-openssl --with-zlib --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --enablembstring --enable-xml --enable-sockets --enable-fpm --enable-maintainer-zts --disable-fileinfo[root@ubuntu2004 php-7.4.30] #make -j 2 && make install# 查看版本验证编译成功[root@ubuntu2004 ~] #/apps/php/sbin/php-fpm -vPHP 7 .4.30 (fpm-fcgi) (built: Sep 18 2022 18 :27:30)Copyright (c) The PHP GroupZend Engine v3.4.0, Copyright (c) Zend Technologies# 编译 php-redis[root@ubuntu2004 ~] #wget https://pecl.php.net/get/redis-5.3.7.tgz[root@ubuntu2004 ~] #tar xf redis-5.3.7.tgz[root@ubuntu2004 ~] #cd redis-5.3.7/[root@ubuntu2004 redis-5.3.7] #/apps/php/bin/phpize && ./configure --with-phpconfig=/apps/php/bin/php-config && make -j 2 && make install[root@ubuntu2004 redis-5.3.7] #ls /apps/php/lib/php/extensions/no-debug-zts-20190902opcache.a opcache.so redis.so[root@ubuntu2004 redis-5.3.7] #cd /root/php-7.4.30/[root@ubuntu2004 php-7.4.30] #cp php.ini-production /etc/php.ini[root@ubuntu2004 php-7.4.30] #cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm[root@ubuntu2004 php-7.4.30] #chmod +x /etc/init.d/php-fpm[root@ubuntu2004 php-7.4.30] #cd /apps/php/etc/[root@ubuntu2004 etc] #cp php-fpm.conf.default php-fpm.conf[root@ubuntu2004 etc] #cp php-fpm.d/www.conf.default php-fpm.d/www.conf[root@ubuntu2004 ~] #vim /etc/php.inidate.timezone = Asia/Shanghaipost_max_size = 8Mupload_max_filesize = 100Mdisplay_errors = Onerror_log = syslog;extension = /apps/php/lib/php/extensions/no-debug-zts-20190902/redis.so # 不写路径也可以extension = redis.so[root@ubuntu2004 ~] #vim /apps/php/etc/php-fpm.d/www.confuser = wwwgroup = wwwlisten = 127 .0.0.1:9000pm.status_path = /php-statusping .path = /pingaccess.log = log/ $pool .access.logslowlog = log/ $pool .log.slowphp_value[session.save_handler] = redisphp_value[session.save_path] = "tcp://127.0.0.1:6379" # 指定 Redis 地址# 创建访问日志文件路径[root@ubuntu2004 ~] #mkdir /apps/php/log[root@ubuntu2004 ~] #systemctl daemon-reload[root@ubuntu2004 ~] #systemctl enable php-fpm.service# 启动 php-fpm[root@ubuntu2004 ~] #systemctl start php-fpm# 或者直接运行程序也可以 , 默认是后台运行[root@ubuntu2004 ~] #/apps/php/sbin/php-fpm
6.3 编译安装 Nginx
[root@ubuntu2004 ~] #wget http://nginx.org/download/nginx-1.22.0.tar.gz[root@ubuntu2004 ~] #tar xf nginx-1.22.0.tar.gz[root@ubuntu2004 ~] #cd nginx-1.22.0/[root@ubuntu2004 nginx-1.22.0] #./configure --prefix=/apps/nginx --user=www --group=www --with-http_ssl_module --with-http_v2_module --with-http_realip_module--with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module[root@ubuntu2004 nginx-1.22.0] #make -j 2 && make install[root@rocky8 ~] #mkdir /apps/nginx/conf.d/# 准备配置文件[root@rocky8 ~] #vim /apps/nginx/conf/nginx.confuser www; # 修改此行http {....include /apps/nginx/conf.d/*.conf; # 添加此行}# 配置 nginx 支持 php[root@ubuntu2004 ~] #vim /apps/nginx/conf.d/www.wang.org.confserver {listen 80 ;server_name www.wang.org;root /data/www/;index index.php;client_max_body_size 20m;location ~ \.php $| /ping|/php-status {root /data/www/;fastcgi_pass 127 .0.0.1:9000 ;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name ;#fastcgi_param SCRIPT_FILENAME /data/www$fastcgi_script_name;include fastcgi_params;}}[root@ubuntu2004 ~] #cat > /lib/systemd/system/nginx.service <<EOF[Unit]Description = The nginx HTTP and reverse proxy serverAfter = network.target remote-fs.target nss-lookup.target[Service]Type = forkingPIDFile = /apps/nginx/logs/nginx.pidExecStartPre = /bin/rm -f /apps/nginx/logs/nginx.pidExecStartPre = /apps/nginx/sbin/nginx -tExecStart = /apps/nginx/sbin/nginxExecReload = /bin/kill -s HUP \$MAINPIDKillSignal = SIGQUIT[Service]Type = forkingPIDFile = /apps/nginx/logs/nginx.pidExecStartPre = /bin/rm -f /apps/nginx/logs/nginx.pidExecStartPre = /apps/nginx/sbin/nginx -tExecStart = /apps/nginx/sbin/nginxExecReload = /bin/kill -s HUP \$MAINPIDKillSignal = SIGQUIT
6.4 测试访问 PHP
[root@ubuntu2004 ~] #mkdir /data/www -p# 测试访问[root@ubuntu2004 ~] #vim /data/www/test.php<?phpphpinfo();?># 在客户端实现名称解析 , 也可以配置 DNS 实现[root@ubuntu2004 ~] #vim /etc/hosts10 .0.0.100 www.wang.org# 访问下面查看是否成功http://www.wang.org/pinghttp://www.wang.org/php-statushttp://www.wang.org/test.php
6.5 准备 phpMyAdmin 程序
[root@ubuntu2004 ~] #wgethttps://files.phpmyadmin.net/phpMyAdmin/5.2.0/phpMyAdmin-5.2.0-all-languages.zip[root@ubuntu2004 ~] #unzip phpMyAdmin-5.2.0-all-languages.zip[root@ubuntu2004 ~] #mv phpMyAdmin-5.2.0-all-languages/* /data/www[root@ubuntu2004 ~] #cp /data/www/config.sample.inc.php config.inc.php[root@ubuntu2004 ~] #vim /data/www/config.inc.php$cfg [ 'Servers' ][ $i ][ 'host' ] = '127.0.0.1' ; # 本机也必须改为 127.0.0.1, 否则会出现错误 :mysqli::real_connect(): (HY000/2002): No such file or directory[root@ubuntu2004 ~] #chown -R www.www /data/www/