Nginx负载均衡

8624 字
43 分钟
Nginx负载均衡

Nginx负载均衡#

[TOC]


概述#

image-20260217105521828
image-20260217105521828

Terminal window
基于代理实现负载均衡
1.为什么要使用负载均衡???
当我们的Web服务器直接面向用户,往往要承载大量并发请求,单台服务器难以负荷
使用多台Web服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后端服务器集群中,实现负载的分发。那么会大大提升系统的吞吐率、请求性能、高容灾
2.称谓
负载
Load Balance
LB
3.公有云称呼
SLB 阿里云负载均衡
CLB 腾讯云负载均衡
4.硬件负载均衡VS软件负载均衡
硬件负载均衡:
1)专用硬件设备
2)高吞吐、低延迟
3)成本昂贵
软件负载均衡:
1)运行在服务器或虚拟机/容器上
2)性能依赖CPU
3)开源免费或低成本

常见负载均衡#

Terminal window
'软件负载均衡'
Nginx: 只支持七层负载
Haproxy: 只支持七层负载
LVS: 支持四层和七层负载

七层负载代理#

image-20260221193712020
image-20260221193712020

image-20260221201422297
image-20260221201422297

Terminal window
1)七层:应用层
优点: 可以对域名转发,比较灵活
缺点: 速度慢,有限制
http://10.0.0.5:80 # 典型的HTTP应用层协议
Terminal window
Nginx负载均衡:它是代理着我们笔记本10.0.0.1:123(随机端口)去请求后端服务器
10.0.0.1:123------>10.0.0.5:80
# 不是转发
10.0.0.5:111(随机端口)------>10.0.0.6:80
10.0.0.5:222(随机端口)------>10.0.0.7:80
'负载均衡服务器需要生成新的端口与后端服务器同时建立连接'
这是一个用户10.0.0.1:123,如果再来一个用户1.2.3.4:555需要再次生成随机的端口建立连接
1.2.3.4:555------>10.0.0.5:80
10.0.0.5:333(随机端口)------>10.0.0.6:80
10.0.0.5:444(随机端口)------>10.0.0.7:80
随着用户和请求的增加,谁的端口先不够用?
负载均衡服务器10.0.0.5的端口
从而引来的两个问题
1)负载均衡端口限制问题
2)负载均衡单点故障问题
# 后面介绍

四层负载转发#

image-20260221202512641
image-20260221202512641

Terminal window
2)四层:传输层
'IP+端口,不解析应用层内容'
优点: 速度快,不存在端口限制
缺点: 只能对IP+端口进行转发,不能对域名进行转发
10.0.0.5:22 # IP地址+端口
http://10.0.0.5 # 典型的HTTP应用层协议
# 加上协议后,就变为了7层,需要通过浏览器进行访问

综合案例#

image-20260221212404846
image-20260221212404846

image-20260221205208251
image-20260221205208251

Terminal window
'目标地址映射'
如果客户端来找我,我把你的目标IP地址进行改写
实际上我们的客户端,直接和后面的服务器建立连接了
# 四层负载只做转发,不存在端口限制
客户端只认10.0.0.4四层负载的IP地址和MAC地址
DNS:www.wp.com----->10.0.0.4 MAC 1122
所以我们后端的服务器需要配虚拟IP地址和MAC地址,得和前面四层负载保持一致
看起来是四层负载回给客户端的,实际上是后面服务器回的数据包
四层负载企业里面很少用到,一般来说七层负载就够用了
# 缓存抗住了很多的压力

实现流程#

image-20260217110543995
image-20260217110543995

Terminal window
Nginx要实现负载均衡需要用到proxy_pass代理模块配置
# 上一个笔记有完整的配置过程
1)web01配置静态页面:
[root@web01 ~]#cd /etc/nginx/conf.d/
[root@web01 conf.d]#vim test.conf
server {
listen 80;
server_name test.kpyun.com;
root /code/test;
location / {
index index.html;
}
}
[root@web01 conf.d]#mkdir /code/test
[root@web01 conf.d]#echo web01_index > /code/test/index.html
nginx -t
systemctl reload nginx
2)web02配置静态页面:
[root@web02 ~]#scp 172.16.1.7:/etc/nginx/conf.d/test.conf /etc/nginx/conf.d/
root@172.16.1.7's password: '
test.conf 100% 132 231.1KB/s 00:00
[root@web02 ~]#ll /etc/nginx/conf.d/
-rw-r--r-- 1 root root 132 Feb 9 17:01 test.conf
[root@web02 ~]#mkdir /code/test
[root@web02 ~]#echo 'web02-index' > /code/test/index.html
nginx -t
systemctl reload nginx
3)lb负载均衡配置转发:
[root@lb01 conf.d]#cat lb.conf
upstream webs {
server 172.16.1.7;
server 172.16.1.8;
}
# upstream 是 Nginx 用于定义一组后端服务器的指令
# webs 是这个服务器组的名称,也叫地址池;你可以自定义
'upstream 模块必须定义在 server 块的外部'
# ❌ 错误:upstream 不能放在 server 块内
server {
listen 80;
server_name test.kpyun.com;
location / {
proxy_pass http://webs;
# 表示将匹配到的请求反向代理到名为 webs 的 upstream 服务器组
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
}
}
nginx -t
systemctl reload nginx
4)负载测试
[root@lb01 conf.d]#vim /etc/hosts
10.0.0.5 test.kpyun.com
[root@lb01 conf.d]#curl test.kpyun.com
web01_index
[root@lb01 conf.d]#curl test.kpyun.com
web02-index
'实现负载均衡'

wordpress负载#

Terminal window
10.0.0.7 wp.kpyun.com
# 先映射为web01,打开浏览器访问

image-20260222093411754
image-20260222093411754

  • db01要打开,数据库用来存储动态的资源

image-20260222093708738
image-20260222093708738

  • 也需要把nfs打开,用来存储静态的资源
Terminal window
[root@web01 ~]#mount 172.16.1.31:/data/wp /code/wordpress/wp-content/uploads/
[root@web01 ~]#df -h
........
172.16.1.31:/data/wp 49G 3.8G 45G 8% /code/wordpress/wp-content/uploads
# Ctrl+F5强制刷新浏览器

image-20260222093947739
image-20260222093947739

Terminal window
[root@web02 ~]#mount -t nfs 172.16.1.31:/data/wp /code/wordpress/wp-content/uploads/
[root@web02 ~]#df -h
......
172.16.1.31:/data/wp 49G 3.8G 45G 8% /code/wordpress/wp-content/uploads
# web02也进行挂载
10.0.0.8 wp.kpyun.com
# 修改Windows中的映射
再次访问浏览器

image-20260222094541113
image-20260222094541113

依然可以正常访问

  • 你得先确定我们的两台web都能够正常的进行访问后,再上负载均衡
Terminal window
[root@lb01 ~]#cd /etc/nginx/conf.d/
[root@lb01 conf.d]#ll
total 4
-rw-r--r-- 1 root root 510 Feb 9 17:07 lb.conf
[root@lb01 conf.d]#mv lb.conf wp.conf
[root@lb01 conf.d]#vim wp.conf
upstream webs {
server 172.16.1.7;
server 172.16.1.8;
}
server {
listen 80;
server_name wp.kpyun.com;
location / {
proxy_pass http://webs;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
}
}
[root@lb01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]#systemctl reload nginx
10.0.0.5 wp.kpyun.com
# 修改Windows中的映射
'改为我们负载均衡服务器的IP地址'
浏览器访问:http://wp.kpyun.com/
它会将总的请求平均的分发给两台web服务器
# 如果总的请求数为12,web01有6个请求,web02也有6个请求
可以通过 tail -f /var/log/nginx/access.log 追踪日志进行查看!
如果其中一台web崩了,则由另一台web抗压

优化#

Terminal window
proxy_set_header Host $http_host;
.......
proxy_buffers 4 128k;
这一大长串,很重要,但是太长了!每次编写配置文件都需要带上,太麻烦了!
[root@lb01 conf.d]#vim ../proxy_set
# 因为主配置文件在/etc/nginx/nginx.conf
# proxy_set和主配置文件在同一层级
# ..上一层目录
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
[root@lb01 conf.d]#vim wp.conf
upstream webs {
server 172.16.1.7;
server 172.16.1.8;
}
server {
listen 80;
server_name wp.kpyun.com;
location / {
proxy_pass http://webs;
include proxy_set;
# 把我们刚才编写的配置文件包含进来
# 子配置文件也被包含在主配置文件中
}
}
# 这样就方便,并且优化了许多
[root@lb01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]#systemctl reload nginx
打开浏览器测试访问,仍然能够正常分担请求!

典型故障#

Terminal window
# 我们这里展示5xx也就是服务端的错误
# 更详细的状态码,可以参考笔记http访问流程
HTTP: 500 依赖服务(数据库、缓存)突然不可用
HTTP: 502 后端服务崩溃或未启动
HTTP: 503 服务暂时不可用,如后端负载高、升级维护中
HTTP: 504 后端处理时间过长(如复杂SQL查询)
[root@web01 ~]#echo web01 > /code/wordpress/test.html
# test.html用来标识web服务器
[root@web02 ~]#echo web02 > /code/wordpress/test.html
# 一个是web01一个是web02
[root@lb01 conf.d]#vim /etc/hosts
10.0.0.5 wp.kpyun.com
# 来到负载均衡服务器
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
# 平均访问两台web!
[root@web01 ~]#systemctl stop nginx
# web01关闭Nginx
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
# 只能拉取到web02服务器
'如果出现一个节点down掉的时候,Nginx会将请求转移到其他的节点上'
# 一个节点停止Nginx服务没有关系
----------------------------------------
[root@web01 ~]#systemctl start nginx
[root@web01 ~]#systemctl stop php-fpm
# 开启web01的nginx,并关闭它的php服务
[root@lb01 conf.d]#curl wp.kpyun.com
<head><title>502 Bad Gateway</title></head>
[root@lb01 conf.d]#curl wp.kpyun.com
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>test &#8211; 又一个WordPress站点</title>
......
# 一个拉取的是web01(不能正常访问)一个是web02
'如果后端web Nginx没有down掉,但是返回错误异常码了如:504、502、500,这个时候你需要加一个负载均衡的设置,如下:proxy_next_upstream http_500 | http_502 | http_503 | http_504'
# 当其中一台返回错误码5xx等错误时,可以分配到下一台服务器,提高平台访问成功率
1)如果后端web的nginx挂掉自动访问下一台,不需要额外的配置
2)如果后端web的nginx没有挂掉而是PHP或者数据库挂掉,则需要额外配置参数proxy_next_upstream的状态码
# 遇到以下状态码自动访问下一台server
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
[root@lb01 conf.d]#vim wp.conf
upstream webs {
server 172.16.1.7;
server 172.16.1.8;
}
server {
listen 80;
server_name wp.kpyun.com;
location / {
proxy_pass http://webs;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
include proxy_set;
}
}
[root@lb01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]#systemctl reload nginx
[root@lb01 conf.d]#curl wp.kpyun.com
# 再次拉取页面,每次都能够成功访问

调度算法#

调度算法(名称)中文说明工作原理优点缺点
轮询按时间顺序逐一分配请求依次轮流分配给后端服务器,循环往复简单、公平、无状态未考虑服务器性能差异,可能导致负载不均
加权轮询根据权重分配请求每台服务器设置 weight 值,weight 越高,被选中的概率越大可根据服务器性能调整负载,更灵活静态权重,无法动态响应服务器实时负载变化
IP Hash基于客户端 IP 的哈希分配对客户端 IP 地址进行哈希计算,将同一 IP 的请求 始终分配 到同一台后端服务器实现 ==会话保持==,无需额外机制若某 IP 访问量大,会导致该后端过载;NAT 下多用户共用 IP 时失效
URL Hash基于请求 URL 的哈希分配对请求的 URL 进行哈希,相同 URL 的请求总被分配到同一台服务器(常用于缓存场景)提高缓存命中率,适合静态资源分发若某些 URL 热点集中,会造成后端负载不均
最少连接数分配给当前连接数最少的服务器动态选择当前活跃连接数最少的后端服务器处理新请求能较好适应服务器实时负载,适合长连接或复杂任务需要维护连接状态,开销略高;短连接场景优势不明显
Terminal window
1.默认为轮询
# 最为常用
2.加权轮询
# 在后端web服务器硬件配置不相同的情况下使用
[root@web01 ~]#systemctl start php-fpm
# 先把web01的php服务启动起来
[root@lb01 conf.d]#vim wp.conf
upstream webs {
server 172.16.1.7 weight=3;
# web01处理3个请求 然后web02处理1个请求
server 172.16.1.8;
}
...
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
# 请求数量是3:1
3.ip_hash
[root@lb01 conf.d]#vim wp.conf
upstream webs {
server 172.16.1.7;
server 172.16.1.8;
ip_hash;
# 按IP固定分配给web服务器
}
....
[root@lb01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]#systemctl reload nginx
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
# 第一次访问的是web02,以后一直都是web02
[root@web02 ~]#systemctl stop nginx
# 除非web02挂了
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
# 才会访问到web01
[root@web02 ~]#systemctl start nginx
# 开启web02的Nginx
缺点: 会让负载均衡变得不均衡
1)若某IP访问量大,会导致该后端过载
2)NAT下多用户共用IP时,失效

image-20260222154220218
image-20260222154220218

后端状态#

Terminal window
1)down
[root@lb01 conf.d]#vim wp.conf
upstream webs {
server 172.16.1.7 down;
# web01不参与调度,相当于给它删除、注释了
server 172.16.1.8;
}
...
[root@lb01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]#systemctl reload nginx
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
# 这样只会访问到web02
2)backup
[root@lb01 conf.d]#vim wp.conf
upstream webs {
server 172.16.1.7;
server 172.16.1.8 backup;
# 当其他server挂掉后,backup的server才会参与调度,类似备胎(web02)
}
...
[root@lb01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]#systemctl reload nginx
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
[root@web01 ~]#systemctl stop nginx
# 模拟web01挂掉
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
# 才会访问到web02
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web02
[root@web01 ~]#systemctl start nginx
# 重新开启web01
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
[root@lb01 conf.d]#curl wp.kpyun.com/test.html
web01
# 又访问不到web02了

编译安装#

Terminal window
我们之前用的是yum安装,自带的有一些模块
如果你想用额外的模块,yum安装就装不上了,必须使用编译安装!
'组装,把没有的模块重新编译进去'
# 模块不重要、重要的是Nginx编译过程
1)下载编译过程中用到的命令
[root@lb01 ~]#yum install -y gcc glibc gcc-c++ pcre-devel openssl-devel patch
2)下载Nginx源码包必须和安装过的版本一致
# 如果原来没有安装过,不必一致,下载自己想要下载的版本就可以了
[root@lb01 ~]#nginx -v
nginx version: nginx/1.26.1
[root@lb01 ~]#mkdir /server/tmp
[root@lb01 ~]#cd /server/tmp/
[root@lb01 tmp]#wget http://nginx.org/download/nginx-1.26.1.tar.gz
[root@lb01 tmp]#ll
total 1216
-rw-r--r-- 1 root root 1244738 May 29 2024 nginx-1.26.1.tar.gz
3)下载nginx_upstream_check第三方模块
# 上传模块到/server/tmp目录
[root@lb01 tmp]#ll
-rw-r--r-- 1 root root 1244738 May 29 2024 nginx-1.26.1.tar.gz
-rw-r--r-- 1 root root 177080 Feb 22 17:03 nginx_upstream_check_module-master.zip
[root@lb01 tmp]#unzip -d /root nginx_upstream_check_module-master.zip
[root@lb01 tmp]#tar xf nginx-1.26.1.tar.gz -C /root
# 解压至/root目录下
[root@lb01 tmp]#ll /root/
total 4
drwxr-xr-x 8 502 games 158 May 29 2024 nginx-1.26.1
drwxr-xr-x 6 root root 4096 Nov 6 2022 nginx_upstream_check_module-master
4)打补丁(nginx的版本是1.26补丁就选择1.26相近的)
[root@lb01 tmp]#cd /root/nginx_upstream_check_module-master/
[root@lb01 nginx_upstream_check_module-master]#ll
total 280
-rw-r--r-- 1 root root 0 Nov 6 2022 CHANGES
-rw-r--r-- 1 root root 7921 Nov 6 2022 check_1.11.1+.patch
-rw-r--r-- 1 root root 8330 Nov 6 2022 check_1.11.5+.patch
-rw-r--r-- 1 root root 8060 Nov 6 2022 check_1.12.1+.patch
-rw-r--r-- 1 root root 8054 Nov 6 2022 check_1.14.0+.patch
-rw-r--r-- 1 root root 8409 Nov 6 2022 check_1.16.1+.patch
-rw-r--r-- 1 root root 8419 Nov 6 2022 check_1.20.1+.patch
-rw-r--r-- 1 root root 5483 Nov 6 2022 check_1.2.1.patch
-rw-r--r-- 1 root root 7130 Nov 6 2022 check_1.2.2+.patch
-rw-r--r-- 1 root root 7094 Nov 6 2022 check_1.2.6+.patch
-rw-r--r-- 1 root root 6791 Nov 6 2022 check_1.5.12+.patch
-rw-r--r-- 1 root root 8295 Nov 6 2022 check_1.7.2+.patch
-rw-r--r-- 1 root root 8346 Nov 6 2022 check_1.7.5+.patch
-rw-r--r-- 1 root root 8509 Nov 6 2022 check_1.9.2+.patch
.....
[root@lb01 nginx_upstream_check_module-master]#cd ../nginx-1.26.1/
# 进入nginx源码目录
[root@lb01 nginx-1.26.1]#patch -p1 < ../nginx_upstream_check_module-master/check_1.20.1+.patch
# patch工具为源代码打补丁的常见方式
# p1代表在nginx源码目录
patching file src/http/modules/ngx_http_upstream_hash_module.c
patching file src/http/modules/ngx_http_upstream_ip_hash_module.c
patching file src/http/modules/ngx_http_upstream_least_conn_module.c
patching file src/http/ngx_http_upstream_round_robin.c
patching file src/http/ngx_http_upstream_round_robin.h
5)./configure 配置路径以及模块
./configure 的作用:
它就像"智能检查员",负责:
1.检查你的系统环境
2.检查依赖环境:gcc
如果缺了某个依赖,它会直接报错,而不是让你在 make 时莫名其妙失败
根据你的系统环境(比如安装路径、CPU架构)生成一个 Makefile 文件,告诉 make 命令如何编译代码
3.允许你自定义安装选项
通过参数指定安装路径(--prefix=/usr/local)
启用/禁用某些功能(--enable-feature --disable-feature)
通过 nginx -V(大写) 找出默认 yum 安装的一个配置参数,以便复用原有配置并扩展新模块
--add-module=/root/nginx_upstream_check_module-master
# 加上这一条,注意模块的路径/root/nginx...
[root@lb01 nginx-1.26.1]#cd
[root@lb01 ~]#nginx -V
nginx version: nginx/1.26.1
configure arguments: --prefix=/etc/nginx ....
# 主要是后面省略的...一些配置
----报错----
[root@lb01 ~]#./configure --prefix=/etc/nginx ...
-bash: ./configure: No such file or directory
# 没有这个目录或文件
后知后觉必须进入到Nginx源代码目录中才能够执行这条命令
[root@lb01 ~]#cd nginx-1.26.1/
[root@lb01 nginx-1.26.1]#ll
total 824
....
-rwxr-xr-x 1 502 games 2611 May 28 2024 configure
# 源代码目录有configure这个文件
[root@lb01 nginx-1.26.1]#./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --add-module=/root/nginx_upstream_check_module-master --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
6)make
make:编译源代码,生成可执行文件(如 myapp)
7)make install
make install:把编译好的文件“正式安装”到系统里,让你能直接运行
# 相当于又安装了一次;可以理解为增量的拷贝,你原来有的我不管你,没有的我给你拷贝过去
---------------------------
1.yum安装Nginx后
我们可以直接通过systemctl来管理我们的Nginx
简单快捷,自动解决依赖
2.如果你只是通过编译安装,没有进行过yum安装
需要自行配置启动方式
高度定制化,可以自由选择模块,自定义安装路径
---------------------------
'如果编译安装,就要用这种方式启停!'
/usr/sbin/nginx # 启动
/usr/sbin/nginx -s stop # 停止
/usr/sbin/nginx -s reload # 重新加载
# 同一时间通常用一种方式来管理启动方式
# 要么是用命令、要么是用systemd
8)最后检查是否编译成功
nginx -V
# 只要有我们的--add-module=/root/nginx_upstream_check_module-master
# 就算是添加成功了
[root@lb01 nginx-1.26.1]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 nginx-1.26.1]#systemctl restart nginx
# 这里是restart重新启动Nginx,因为我们重新编译安装了一遍了

Ubuntu 编译安装#

image-20260616231700867
image-20260616231700867

Terminal window
root@Ubuntu ~# cd /tmp/
root@Ubuntu tmp# rm -rf ./*
'去官网找最新的稳定版'

https://nginx.org/en/download.html

image-20260616231825245
image-20260616231825245

image-20260616231856051
image-20260616231856051

Terminal window
1)下载解压
root@Ubuntu ~# Version=1.30.2
# 1.30.2 最新的稳定版
root@Ubuntu ~# wget http://nginx.org/download/nginx-${Version}.tar.gz -O ./nginx.tar.gz
root@Ubuntu ~# tar zxvf nginx.tar.gz -C /root/
root@Ubuntu ~# pwd
/root --> '都在根目录下'
root@Ubuntu ~# ls | grep nginx
nginx-1.30.2 <-- '解压后的包'
nginx.tar.gz
2)更换软件源&下载依赖
# /etc/apt/sources.list.d/ubuntu.sources
root@Ubuntu ~# sed -i '/^URI/c\URIs: https://mirrors.tuna.tsinghua.edu.cn/ubuntu/' /etc/apt/sources.list.d/ubuntu.sources
'软件源换为清华的好使一点' --> 使用 sed 一键替换
Types: deb
URIs: https://mirrors.tuna.tsinghua.edu.cn/ubuntu/
Suites: noble noble-updates noble-backports
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Types: deb
URIs: https://mirrors.tuna.tsinghua.edu.cn/ubuntu/
Suites: noble-security
Components: main restricted universe multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
# 更新软件源并修复依赖
root@Ubuntu ~# sudo apt update
root@Ubuntu ~# sudo apt upgrade -y
# Ubuntu系统
root@Ubuntu ~# sudo apt install -y build-essential libpcre2-dev zlib1g-dev libssl-dev libaio-dev
# 安装依赖 --> 不然会报错
3)健康检查模块&打补丁
root@Ubuntu ~# wget https://ghproxy.net/https://github.com/yaoweibin/nginx_upstream_check_module/archive/refs/heads/master.tar.gz -O nginx_upstream_check_module-master.tar.gz
root@Ubuntu ~# tar xf nginx_upstream_check_module-master.tar.gz
root@Ubuntu ~# rm -f nginx_upstream_check_module-master.tar.gz nginx.tar.gz
# 把压缩包都删除了
root@Ubuntu ~# ls | grep nginx
nginx-1.30.2
nginx_upstream_check_module-master
root@Ubuntu ~# apt -y install patch
# 用于打补丁
root@Ubuntu ~# cd nginx-1.30.2/
root@Ubuntu nginx-1.30.2# patch -p1 < ../nginx_upstream_check_module-master/check_1.20.1+.patch
4)创建 www 用户(统一后续服务使用)
root@Ubuntu nginx-1.30.2# cd ~
root@Ubuntu ~# groupadd -g 888 www
root@Ubuntu ~# useradd -r -g 888 -u 888 -s /sbin/nologin www
-r # 系统用户
root@Ubuntu ~# id www
uid=888(www) gid=888(www) 组=888(www)
5)编译安装
# 进入源码目录
root@Ubuntu ~# cd nginx-1.30.2/
root@Ubuntu nginx-1.30.2#

Nginx 默认的 --prefix 不是 /opt,而是 /usr/local/nginx

如果你只执行裸的 ./configure && make && make install,所有文件都会塞进这一个目录里:

文件类型默认路径
配置文件/usr/local/nginx/conf/nginx.conf
可执行文件/usr/local/nginx/sbin/nginx
日志文件/usr/local/nginx/logs/
临时文件/usr/local/nginx/temp/
PID/Lock/usr/local/nginx/logs/nginx.pid

⚠️ 这种”全挤在一个目录”的结构不利于后期运维、日志轮转和 systemd 管理

所以生产环境通常都会显式指定路径,将其拆分到 /etc/var/log/usr/sbin 等标准 FHS 目录中

Terminal window
'别忘了手动创建日志目录'
root@Ubuntu ~# mkdir -p /var/log/nginx
=======================================
make install 会自动创建 --prefix 下的目录树 --> /etc/nginx/
# /usr/sbin 是系统自带目录
# /run/nginx.pid 的父目录 /run 系统自带,不需要建
# /var/log/nginx/error.log,/var/log 存在,但它的子目录 nginx/ 不存在
这种不在 prefix 路径内的,nginx不会自动建 启动时日志目录不存在就直接报错退出
Terminal window
root@Ubuntu ~# cd nginx-1.30.2/
root@Ubuntu nginx-1.30.2# ./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/run/nginx.pid \
--lock-path=/run/nginx.lock \
--user=www \
--group=www \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-stream \
--with-stream_ssl_module \
--with-threads \
--with-file-aio \
--add-module=/root/nginx_upstream_check_module-master \
--with-cc-opt='-O2 -g -fstack-protector-strong -fPIC' \
--with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
Terminal window
root@Ubuntu nginx-1.30.2# make && make install
root@Ubuntu nginx-1.30.2# cd ~
root@Ubuntu ~# nginx -V
nginx version: nginx/1.30.2
built by gcc 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04.1)
built with OpenSSL 3.0.13 30 Jan 2024
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/run/nginx.pid --lock-path=/run/nginx.lock --user=www --group=www --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-stream --with-stream_ssl_module --with-threads --with-file-aio --add-module=/root/nginx_upstream_check_module-master --with-cc-opt='-O2 -g -fstack-protector-strong -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
root@Ubuntu ~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
root@Ubuntu ~# nginx
# 启动nginx
root@Ubuntu ~# nginx
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
'不能重复启动~'
现在的 nginx 只能手动 /usr/sbin/nginx 启动,systemctl不认识它
# 自行编写一个 systemd unit 文件 --> 这里并没有编写 --> 手动完全能活

systemd 无非就多三样东西:

1. 开机自启 — 不然每次重启都得手动拉
2. 崩溃自动拉起来 — Restart=on-failure
3. systemctl reload nginx — 和 nginx -s reload 一样,只是统一用 systemctl 管理
Terminal window
root@Ubuntu ~# ss -lntup | grep nginx
tcp LISTEN 0.0.0.0:80 users:(("nginx",pid=191912,fd=6))
root@Ubuntu ~# ps aux | grep nginx
root 191911 Ss nginx: master process nginx
'master process;主进程'
www 191912 S nginx: worker process
'worker process:工作的进程'

image-20260617094321666
image-20260617094321666

Terminal window
user www;
worker_processes 4;
worker_cpu_affinity auto; # cpu亲和
pid /run/nginx.pid;
error_log /var/log/nginx/error.log notice;
worker_rlimit_nofile 65535; # 每个work能打开的文件描述符
events {
worker_connections 32768;
# 每个worker进程可以同时处理最大连接数
# 一个连接平均占用两个文件描述符
multi_accept on;
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
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;
server_tokens off; # 禁止浏览器显示nginx版本号
client_max_body_size 20m; # 文件上传大小限制调整 默认1M
sendfile on;
tcp_nopush on;
# tcp_nodelay on;
keepalive_timeout 65;
# Gzip
gzip on;
# 小于1KB的文件不压缩(避免小文件压缩后反而变大)
gzip_min_length 1k;
gzip_comp_level 6; # 压缩等级6(通用)
gzip_types text/plain application/javascript text/css application/xml application/json;
# 压缩的类型:必须用空格隔开
# 子配置目录
include /etc/nginx/conf.d/*.conf;
}
Terminal window
root@Ubuntu nginx# mkdir conf.d
root@Ubuntu nginx# cd conf.d/
root@Ubuntu conf.d# ls
root@Ubuntu conf.d# vim default.conf
root@Ubuntu conf.d# cat default.conf
server {
listen 80 default_server;
server_name _;
root /etc/nginx/html;
location / {
index index.html index.htm;
error_page 500 502 503 504 /50x.html;
}
}

健康检查模块#

Terminal window
'模块本身并不重要,主要是为了体验编译安装的过程'
[root@lb01 nginx-1.26.1]#cd /etc/nginx/conf.d/
[root@lb01 conf.d]#vim wp.conf
upstream webs {
server 172.16.1.7 max_fails=2 fail_timeout=10s;
server 172.16.1.8 max_fails=2 fail_timeout=10s;
check interval=3000 rise=2 fall=3 timeout=1000 type=tcp;
}
补充说明:
max_fails=2:在fail_timeout时间内最大允许失败的次数为 2
check interval=3000:每 3000 毫秒(即 3 秒)执行一次健康检查
rise:检查2次成功,将服务器标记为up
fall:检查3次失败,将服务器标记为down
timeout=1000:每次健康检查的超时时间为 1000 毫秒(1 秒)
type=tcp:使用 TCP 连接进行健康检查(不发送 HTTP 请求,仅检测端口是否可达)
.....
location /check {
check_status;
# 当访问wp.kpyun.com/check时则返回状态模块对应的信息
}
[root@lb01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]#systemctl reload nginx
浏览器访问测试: wp.kpyun.com/check

image-20260223084406037
image-20260223084406037

会话保持#

Terminal window
'大白话介绍一下会话保持'
想象一下你去一家大型超市买东西,超市里有好几个收银台(相当于后端的多个服务器)
你第一次去结账,排在了3号收银台。这时候你买了一半的东西,突然想起来还要买点别的,于是你又跑回去拿东西
等你再回来结账时,你希望还是找3号收银台,因为人家已经知道你买了啥、付了多少钱、有没有优惠券……如果你换到5号收银台,人家啥都不知道,还得从头开始,特别麻烦!
这个“让你一直回到同一个收银台”的机制,就叫 会话保持(Session Persistence)
那么 Nginx 怎么做到这一点呢?
Nginx 默认是“轮询”分发请求的,把请求平均分发下去
但这样就可能出现你一会儿连服务器A,一会儿连服务器B,而你的登录状态、购物车信息只存在某一台服务器上
为了让用户始终连到同一台后端服务器,可以通过以下几种常见方式实现会话保持:
1.使用nginx的ip_hash,根据客户端的IP,将请求分配到同一台服务器,但是会造成负载不均衡
2.基于Cookie的会话保持(最常用)
'这个功能在 Nginx Plus(商业版)里直接支持;开源版 Nginx 需要配合其他方法'
Nginx 在你第一次访问时,偷偷在你浏览器里放一个特殊的 Cookie,下次你再访问,Nginx 看到这个 Cookie,就知道:“哦,这个人上次是 web01 服务的,这次还送它回去。”
# 以上两点都是靠 Nginx 把用户“绑”在某一台服务器上
-------------------------------------
3.基于服务端的session会话共享
# 让所有服务器都能看到同一个用户的会话数据
'下面的实验都是用的这个方法去实现的会话保持'
类比项Cookie(钥匙)Session(宝箱)
作用携带访问凭证,告诉服务器:“我是谁”保存真实用户数据,是真正的“身份仓库”
存储位置客户端(浏览器)服务端(内存/数据库)
是否敏感可能被窃取(需保护)更安全,只在服务端可见
如何工作浏览器自动带上 Cookie 发送请求服务器根据 Cookie 中的 Session ID 查找对应数据
如果丢失需重新登录(相当于丢钥匙)数据还在,但无法访问(没钥匙打不开锁)

💡 总结一句话: Cookie 是一把“钥匙”,Session 是一个“保险箱” 没有钥匙(Cookie)就打不开保险箱(Session),但保险箱本身不会暴露在外部

✅ Cookie 是由 服务器 生成并返回给 客户端浏览器

  • 这也是为什么它能作为“钥匙”——因为这把钥匙是服务器“配好”并交给你的 😊

phpmyadmin业务#

image-20260223113625639
image-20260223113625639

Terminal window
这里我们部署phpmyadmin业务(用页面管理数据库的业务),登录后会将session会话保存在本地服务器
# 而我们之前的wordpress是通过代码的方式写到了mysql数据库中
1.web01部署phpmyadmin业务
[root@web01 ~]#cd /etc/nginx/conf.d/
[root@web01 conf.d]#vim admin.conf
server {
listen 80;
server_name admin.kpyun.com;
root /code/admin;
location / {
index index.php index.html;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
[root@web01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@web01 conf.d]#systemctl restart nginx
[root@web01 conf.d]#cd /server/tmp/
[root@web01 tmp]#ll
total 15416
-rw-r--r-- 1 root root 15782614 Feb 23 11:43 phpMyAdmin-5.2.2-all-languages.zip
# 上传phpmyadmin代码
[root@web01 tmp]#mkdir /code/admin
[root@web01 tmp]#unzip -d /code/admin phpMyAdmin-5.2.2-all-languages.zip
[root@web01 tmp]#cd /code/admin/
[root@web01 admin]#ll
total 4
drwxr-xr-x 12 root root 4096 Jan 20 2025 phpMyAdmin-5.2.2-all-languages
[root@web01 admin]#mv phpMyAdmin-5.2.2-all-languages/* .
# 多了一个层级,移动到当前目录中(/code/admin)
[root@web01 admin]#ll
total 700
-rw-r--r-- 1 root root 69 Jan 20 2025 babel.config.json
-rw-r--r-- 1 root root 19492 Jan 20 2025 ChangeLog
drwxr-xr-x 3 root root 18 Jan 20 2025 doc
.....
[root@web01 admin]#rm -rf phpMyAdmin-5.2.2-all-languages/
# 现在这个目录是空目录,把它删除了
[root@web01 admin]#cp config.sample.inc.php config.inc.php
# 它只认config.inc.php这个名字,复制实例配置文件的信息
[root@web01 admin]#vim config.inc.php
# 修改数据指向为172.16.1.51,本来是localhost
# 因为我们本地没有mysql数据库,这个业务是用来管理mysql数据库的
[root@web01 admin]#grep 172.16.1.51 config.inc.php
$cfg['Servers'][$i]['host'] = '172.16.1.51';
[root@web01 admin]#ll -d /var/lib/php/session/
drwxrwx--- 2 root apache 6 Aug 29 17:40 /var/lib/php/session/
# 默认启动用户是apache,而我们早已更改为www
[root@web01 admin]#chown www.www /var/lib/php/session
# php的启动用户www需要在/var/lib/php/session这个目录下创建会话信息
# 所以需要修改这个目录的属主,不然www没有办法创建文件
[root@web01 admin]#ll -d /var/lib/php/session/
drwxrwx--- 2 www www 6 Aug 29 17:40 /var/lib/php/session/
# windows hosts解析
10.0.0.7 admin.kpyun.com;

image-20260223122902118
image-20260223122902118

Terminal window
这个用户名和密码本质是mysql的;
jiuzhao
oldboy123.com

🧩 实际流程示例#

image-20260223123652073
image-20260223123652073

Terminal window
服务器返回浏览器的cookie的值是7pu0u1hinsb8mkqd3mbgo8c38j
[root@web01 admin]#cd /var/lib/php/session/
[root@web01 session]#ll
total 4
-rw------- 1 www www 103 Feb 23 12:27 sess_7pu0u1hinsb8mkqd3mbgo8c38j
# 和we01本地保存的session_id一致!
'当我刷新浏览器时cookie再次发生变化'
# 跟后端的代码有关系
phpMyAdmin l1fbcao185naq0h46o90a2kft8
[root@web01 session]#ll
total 4
-rw------- 1 www www 103 Feb 23 12:40 sess_l1fbcao185naq0h46o90a2kft8
# web01本地的session_id也跟随着变化
# 我们还没有做Redis缓存,它的这个会话是保存在本地
  1. 用户登录 → 服务器创建 Session(锁头),并生成 Session ID:7pu0u1hxxx/var/lib/php/session/ 下创建文件:sess_7pu0u1hxxx

  2. 服务器返回 Set-Cookie: session_id = 7pu0u1xxx(把钥匙交给浏览器)

  3. 用户下次访问 → 浏览器自动携带 Cookie: session_id = 7pu0u1xxx

  4. 服务器收到后,查找 Session ID 对应的数据 → 打开“锁头”

  5. 返回用户个性化内容

问题答案
谁创建 Cookie?服务器(通过 Set-Cookie 响应头)
谁保存 Cookie?客户端浏览器
谁使用 Cookie?浏览器(自动发送)、服务器(读取内容)

image-20260223132441532
image-20260223132441532

Terminal window
当我们登录上去之后,cookie固定,会话保持
'无论怎么刷新浏览器,都还是那个cookie'
# 要保留缓存的刷新,如果清除缓存,则继续更新cookie
phpMyAdmin jgcr6rn4ohgd2e1d3kvbvjrg9u
[root@web01 session]#ll
total 4
-rw------- 1 www www 2519 Feb 23 13:24 sess_jgcr6rn4ohgd2e1d3kvbvjrg9u
Terminal window
# web02部署phpmyadmin服务
[root@web02 conf.d]#vim admin.conf
server {
listen 80;
server_name admin.kpyun.com;
root /code/admin;
location / {
index index.php index.html;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
nginx -t
systemctl reload nginx
scp -r 10.0.0.7:/code/admin /code/
chown www.www /var/lib/php/session
ll -d /var/lib/php/session
测试:
windows hosts文件
10.0.0.8 admin.kpyun.com
# 成功登录进去

image-20260223133301485
image-20260223133301485

Terminal window
# phpmyadmin接入负载均衡
[root@lb01 conf.d]#ll
total 4
-rw-r--r-- 1 root root 450 Feb 23 08:39 wp.conf
[root@lb01 conf.d]#cp wp.conf admin.conf
[root@lb01 conf.d]#vim admin.conf
upstream testwebs {
# 更改了一下这个地址池的名字
server 172.16.1.7;
server 172.16.1.8;
}
server {
listen 80;
server_name admin.kpyun.com;
location / {
proxy_pass http://testwebs;
# 这个也要进行更改
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
include proxy_set;
}
location /check {
check_status;
}
}
[root@lb01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 conf.d]#systemctl reload nginx
# windows解析到负载均衡
10.0.0.5 admin.kpyun.com

image-20260223133857047
image-20260223133857047

Terminal window
[root@web01 ~]#cd /var/lib/php/session/
[root@web01 session]#rm -rf ./*
[root@web01 session]#ll
total 0
[root@web02 conf.d]#cd /var/lib/php/session/
[root@web02 session]#rm -rf ./*
[root@web02 session]#ll
total 0
# 把原来的会话信息都删除了

image-20260223134759527
image-20260223134759527

Terminal window
[root@web01 session]#ll
total 4
-rw------- 1 www www 103 Feb 23 13:46 sess_hbha8vbl2tqdcu7jdg818kqr6j
# 与web01中的session_id一致

image-20260223135426956
image-20260223135426956

Terminal window
[root@web01 session]#ll
total 4
-rw------- 1 www www 103 Feb 23 13:46 sess_hbha8vbl2tqdcu7jdg818kqr6j
# web01还是之前的
[root@web02 session]#ll
total 4
-rw------- 1 www www 103 Feb 23 13:49 sess_au7hbtlk58t8tcai86nmf723m7
# web02中的session_id才是对应的cookie值,au7hb...
# 说明这次请求分配到web02
'再次输入正确的用户名和密码,并登录'
phpMyAdmin v9f4ka5m509tljdg21000eq8o5
# 浏览器的cookie再一次的发生了变化
[root@web02 session]#ll
total 4
-rw------- 1 www www 103 Feb 23 13:49 sess_au7hbtlk58t8tcai86nmf723m7
# web02没有发生变化
[root@web01 session]#ll
total 8
-rw------- 1 www www 103 Feb 23 13:46 sess_hbha8vbl2tqdcu7jdg818kqr6j
-rw------- 1 www www 103 Feb 23 13:54 sess_v9f4ka5m509tljdg21000eq8o5
# web01有正确的,说明这次分配到了web01,v9f4k...
'再次输入正确的用户名和密码,并尝试登录'
phpMyAdmin d8f0iu6qo72hn5uundspmd3gc2
# 又一次的发生了变化
[root@web01 session]#ll
total 8
-rw------- 1 www www 103 Feb 23 13:46 sess_hbha8vbl2tqdcu7jdg818kqr6j
-rw------- 1 www www 198 Feb 23 13:57 sess_v61ugg49e0ackfb3hbgd2mqe4k
[root@web02 session]#ll
total 8
-rw------- 1 www www 103 Feb 23 13:49 sess_au7hbtlk58t8tcai86nmf723m7
-rw------- 1 www www 103 Feb 23 13:57 sess_d8f0iu6qo72hn5uundspmd3gc2
# 这次请求分配给了web02.....
'如此的循环往复,一直登录不上去'
--------------------------------
我们应该怎么做?把原本存在单台服务器里的session,统一存到一个所有服务器都能访问的共享存储里,比如 Redis、mysql数据库等
当我们登录上去之后,cookie固定,会话保持
1)用户浏览器每次请求都会自动带上相同的cookie
2)任何一台后端服务器收到请求后,都去共享存储里查对应的session数据
3)所以不管请求被分到哪台服务器,都能拿到用户的登录状态、购物车等信息

部署redis#

Terminal window
'以下操作都是在db01也就是安装了MySQL的web服务器172.16.1.51中操作'
第一步:
[root@db01 ~]#yum -y install redis
# 安装redis
[root@db01 conf.d]#vim /etc/redis.conf
bind 127.0.0.1 172.16.1.51
# 修改监听IP:不仅监听本地,还监听自己的内网IP(别人好连接我)
port 6379
# 默认端口是6379,不需要更改
requirepass 123456
# 设置密码为123456,原来是注释着的
[root@db01 conf.d]#grep ^bind /etc/redis.conf
bind 127.0.0.1 172.16.1.51
[root@db01 conf.d]#grep ^requirepass /etc/redis.conf -n
1044:requirepass 123456
[root@db01 ~]#systemctl start redis
[root@db01 ~]#systemctl enable redis
Created symlink /etc/systemd/system/multi-user.target.wants/redis.service /usr/lib/systemd/system/redis.service.
# 启动redis,并开机自启动
[root@db01 ~]#netstat -lntup
tcp 0 0 172.16.1.51:6379 0.0.0.0:* LISTEN 59407/redis-server
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 59407/redis-server
# 主要是这个内网172.16.1.51,为了别人可以连接我,从而可以和我通信
[root@db01 ~]#redis-cli -a '123456'
127.0.0.1:6379> keys *
(empty array)
# 里面是空的,没有东西
第二步:
# 配置PHP session指向redis
web01修改:
[root@web01 session]#vim /etc/php.ini
1226 session.save_handler = redis
# 默认是file,文件的形式,修改为redis的形式
1259 session.save_path = "tcp://172.16.1.51:6379?auth=123456"
# 存储路径
[root@web01 session]#tail -4 /etc/php-fpm.d/www.conf
#注释倒数3和4行
;php_value[session.save_handler] = files # 这行
;php_value[session.save_path] = /var/lib/php/session # 这行
# 分号注释
php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache
;php_value[opcache.file_cache] = /var/lib/php/opcache
第三步: 编译PHP连接redis的插件
[root@web01 session]#rpm -qa | grep php
...
php-mysqlnd-8.0.30-10.p02.ky10.x86_64
# 因为这个插件php能连接MySQL数据库
# 但是php默认没有redis的插件,所以不兼容
PHP安装redis插件
第一步: 下载redis源码包
[root@web01 session]#wget -P /server/tmp/ https://pecl.php.net/get/redis-5.3.7.tgz
# -P:下载到指定目录
第二步: 解压代码
[root@web01 session]#tar -zxf /server/tmp/redis-5.3.7.tgz -C /root/
[root@web01 session]#ll /root
drwxr-xr-x 4 root root 4096 Feb 23 14:54 redis-5.3.7
第三步: 配置
[root@web01 session]#cd /root/redis-5.3.7/
[root@web01 redis-5.3.7]#phpize
Configuring for:
PHP Api Version: 20200930
Zend Module Api No: 20200930
Zend Extension Api No: 420200930
[root@web01 redis-5.3.7]#./configure
第四步: 编译安装
[root@web01 redis-5.3.7]#make && make install
第五步: 开启redis插件功能,配置文件增加以下一行内容
[root@web01 redis-5.3.7]#grep redis.so /etc/php.ini -n
883:extension=redis.so
# 取消注释,并更改内容
# 也有可能是879行!
[root@web01 redis-5.3.7]#php-fpm -t
[23-Feb-2026 15:04:41] NOTICE: configuration file /etc/php-fpm.conf test is successful
第六步: 重启服务
[root@web01 redis-5.3.7]#systemctl restart php-fpm
'web02执行web01相同的动作'
scp 10.0.0.7:/etc/php.ini /etc/
scp 10.0.0.7:/etc/php-fpm.d/www.conf /etc/php-fpm.d/
#下面的命令直接复制到web02回车执行
wget -P /server/tmp/ https://pecl.php.net/get/redis-5.3.7.tgz
tar -zxf /server/tmp/redis-5.3.7.tgz -C /root/
cd /root/redis-5.3.7/
phpize
./configure
make && make install
sed -n '883p' /etc/php.ini
# 也有可能是879行!
[root@web02 redis-5.3.7]#php-fpm -t
[23-Feb-2026 15:11:36] NOTICE: configuration file /etc/php-fpm.conf test is successful
# 检测是否成功
[root@web02 redis-5.3.7]#systemctl restart php-fpm
# 重启php-fpm生效
# 最后测试登录phpmyadmin

image-20260223151511786
image-20260223151511786

Terminal window
phpMyAdmin jqf91b8qfi28lf2m7rghbbe4lo
# 浏览器cookie
127.0.0.1:6379> keys *
1) "PHPREDIS_SESSION:jqf91b8qfi28lf2m7rghbbe4lo"
# redis数据库(172.16.1.51)
# 两台web服务器都将session存放在redis中
浏览器刷新试试
用户: jiuzhao@web01
用户: jiuzhao@web02

Valkey#

Valkey 是 Redis 的完全兼容开源分支,配置文件基本 100% 相同,所以你之前对 Redis 的配置经验可以直接套用到 Valkey 上,只需要注意几个文件路径和命令名称的差异即可

🔍 Valkey vs Redis#

项目Redis (你的旧例子)Valkey (你现在装的)
配置文件路径/etc/redis.conf/etc/valkey/valkey.conf
哨兵配置文件/etc/redis-sentinel.conf/etc/valkey/sentinel.conf
服务名redisvalkey (主服务) 和 valkey-sentinel
客户端命令redis-clivalkey-cli
服务端命令redis-servervalkey-server
日志/数据目录/var/lib/redis, /var/log/redis/var/lib/valkey, /var/log/valkey
配置选项语法完全相同(bind, port, requirepass, save, appendonly 等)完全相同
PHP扩展使用 redis 扩展仍然使用 redis 扩展(协议兼容)
连接字符串tcp://IP:PORT?auth=密码完全相同
Terminal window
1)更改基本的配置
dnf install valkey -y
# vim /etc/valkey/valkey.conf
bind 127.0.0.1 10.2.3.80
port 6379
requirepass 123456
# 密码默认注释,需要取消并给一个密码
[root@share01 ~]# systemctl enable valkey --now
[root@share01 ~]# netstat -lntup | grep 6379
tcp 127.0.0.1:6379 LISTEN 3509/valkey-server
tcp 10.2.3.80:6379 LISTEN 3509/valkey-server
2)更改php配置
# vim /etc/php.ini
[Session]
session.save_handler = redis
session.save_path = "tcp://10.2.3.80:6379?auth=123456"
# vim /etc/php-fpm.d/www.conf
# 注释这两行
;php_value[session.save_handler] = files
;php_value[session.save_path] = /var/lib/php/session
php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache
3)下载对应的插件
dnf install -y php-redis
php-fpm -t
systemctl restart php-fpm

WordPress设置缓存#

Terminal window
vim /wp/wordpress/wp-config.php
Terminal window
<?php
define( 'DB_NAME', 'wp' );
define( 'DB_USER', 'wpuser' );
define( 'DB_PASSWORD', 'passwd' );
define( 'DB_HOST', '10.2.3.80' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
define( 'AUTH_KEY', 'YYpir)>G!LZ53VG&{hG8j7$M+`Vc`a0S;uj*o)Cz$2vp>AZI-mt_c4`oVvZw:f7P' );
define( 'SECURE_AUTH_KEY', '.Z$ntLw%}<7Cb9h2zA_].4k%ME6#Mkl^b@&F%s?ke<.Cnwt>WvEGJhL0:vl@e}m ' );
define( 'LOGGED_IN_KEY', '8l=Atror^mZ>JkyzS`GlrR{muk8aZ=Jwy2<*s*|p@$DKBcxW{4S7vb@s*EbwP`bN' );
define( 'NONCE_KEY', 'pqS&i&3-r#PhgGS{ {7/Sg}+Jk%{G9Zt+4NsD80&n!a.8%Cr_,o^Ex2xRbTy-zsa' );
define( 'AUTH_SALT', '+SluVE?F;||2f0&a&`;-b=K{}_(5h6Gx(~=&S8&R_+mr[b/H](8*5ES&r(Yb[<(G' );
define( 'SECURE_AUTH_SALT', 'O`SY9|ks|,}SSk3#7m`I6HYav,(rNQDVXt#ETaduD#A@V,Y&EsAN-x-vf{wGUdX>' );
define( 'LOGGED_IN_SALT', '$1VZ-eT5d4;:h#NppV]ROT:$>j]W Dbgx{#MxrV[}.E|@g#Sj=$;:!V#^~=Vs= }' );
define( 'NONCE_SALT', 'qc.s=BnM}uFC{Ws{JKkl@=0A+1*,RKuDw*+X7`;11u?3eT.a?X}N!&Oi5e$C6U)m' );
$table_prefix = 'wp_';
define( 'WP_DEBUG', false );
/* Add any custom values between this line and the "stop editing" line. */
define('WP_REDIS_HOST', '10.2.3.80');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_PASSWORD', '123456');
/* That's all, stop editing! Happy publishing. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
require_once ABSPATH . 'wp-settings.php';

image-20260702093112694
image-20260702093112694

image-20260702093140272
image-20260702093140272

image-20260702093153705
image-20260702093153705

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Nginx负载均衡
https://www.kpyun.fun/posts/web/nginx/nginx05/
作者
久棹
发布于
2025-11-19
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
久棹
只要胆子大,天天寒暑假!
公告
欢迎来到久棹的技术小站!本站专注 Linux 运维学习笔记分享,如有问题欢迎交流探讨 🎉
分类
标签
站点统计
文章
98
分类
11
标签
203
总字数
244,453
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.5
文章许可
CC BY-NC-SA 4.0

文章目录