# Nginx 负载均衡会话共享
# 1. 什么是会话保持
当用户登陆一个网站服务器,网站服务器会将用户的登陆信息存储下来(存储下来的内容叫 Session )以保证
我们能够一直处于 ” 登陆在线 “ 状态。
- 客户端:cookies
- 服务端:sessionID
# 2. 为什么需要会话保持
由于我们使用的是负载均衡轮询机制,会导致用户请求分散在不同的节点,从而造成会话无法保持。假设用户 A,通过负载均衡登陆了网站,此时会话信息存储在 A 节点,那么当它一刷新,负载均衡会将请求分发给 B 节点,那么 B 节点没有用户 A 的登陆信息,就会提示用户 A 登陆,当 A 用户点击登陆时又会将请求分发给 C 节点,从而造成用户 A 无法实现会话保持。
# 3. 如何实现会话保持
- 1. 粘性 session (演示):指 Ngnix 每次都将同一用户的所有请求转发至同一台服务器上,及 Nginx 的 IP_hash。
- 2.session 复制(不用):每次 session 发生变化,就广播给集群中的服务器,使所有的服务器上的 session 相同。
- 3.session 共享(√):缓存 session 至内存数据库中,使用 redis,memcached 实现。
- 4.session 持久化:将 session 存储至数据库中,像操作数据一样操作 session。
# 4. 会话保持场景演示
session 共享实现过程:
- 1. 用户第一次发起 HTTP 请求,默认不会携带 Cookies 信息;
- 2. 服务器接收到请求后,发现没有 Cookies 信息,认为是第一次请求,所以会生成一个随机 SessionID,存储在 Redis 中,然后通过 Set-Cookies 的 Header 中下发给客户端;
- 3. 客户端拿着 SessionID+User+Password 提交给负载均衡,负载均衡调度至 web02 节点;
- 4.web02 节点查询 Redis 中是否存在该 SessionID,如果存在,则验证用户名和密码,如果成功,则将 Redis 中的 SessionID 初始化已登录状态;
# 4.1 配置 web 节点
1. 首先安装并配置 phpmyadmin
[root@web01 ~]# cd /code | |
[root@web01 code]# wget https://files.phpmyadmin.net/phpMyAdmin/4.8.4/phpMyAdmin-4.8.4-all-languages.zip | |
[root@web01 code]# unzip phpMyAdmin-4.8.4-all-languages.zip | |
[root@web01 code]# ln -s /code/phpMyAdmin-4.8.4-all-languages /code/phpmyadmin | |
[root@web01 phpmyadmin]# chown -R www.www /var/lib/php/session |
2. 修改 phpmyadmin 连接远程的数据库
[root@web01 code]# cd phpmyadmin/ | |
[root@web01 phpmyadmin]# cp config.sample.inc.php config.inc.php | |
[root@web01 phpmyadmin]# vim config.inc.php | |
/* Server parameters */ | |
$cfg['Servers'][$i]['host'] = '192.168.40.51'; |
3. 在多台 web 上准备 phpmyadmin 的 nginx 配置文件
[root@web01 phpmyadmin]# cat /etc/nginx/conf.d/phpmyadmin.hmallleasing.com.conf | |
server { | |
listen 80; | |
server_name phpmyadmin.hmallleasing.com; | |
root /code/phpmyadmin; | |
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 服务 | |
[root@web02 phpmyadmin]# nginx -t | |
[root@web02 phpmyadmin]# systemctl restart nginx |
# 4.2 配置负载均衡
1. 编写一份 proxy 负载均衡的配置文件,将请求调度到后端 web 节点
[root@lb01 conf.d]# cat phpmyadmin.hmallleasing.com.conf | |
upstream phpmyadmin { | |
server 192.168.40.7:80; | |
server 192.168.40.8:80; | |
} | |
server { | |
listen 80; | |
server_name phpmyadmin.hmallleasing.com; | |
location / { | |
proxy_pass http://phpmyadmin; | |
include proxy_params; | |
} | |
} | |
[root@lb01 ~]# cat /etc/nginx/proxy_params | |
proxy_http_version 1.1; | |
proxy_set_header Connectin ""; | |
proxy_set_header Host $http_host; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_connect_timeout 60; | |
proxy_send_timeout 60; | |
proxy_read_timeout 120; | |
proxy_buffering on; | |
proxy_buffer_size 32k; | |
proxy_buffers 4 128k; | |
proxy_temp_file_write_size 10240k; | |
proxy_max_temp_file_size 10240k; |
2. 检查语法并重载 nginx
[root@proxy01 conf.d]# nginx -t | |
[root@proxy01 conf.d]# systemctl restart nginx |
# 4.3 配置 Redis 服
1. 安装 redis 内存数据库
[root@redis ~]# yum install redis -y |
2. 配置 redis 监听在本地的内网网卡上
[root@redis ~]# sed -i '/^bind/c bind 127.0.0.1 192.168.40.41' /etc/redis.conf |
3. 启动 redis
[root@redis ~]# systemctl start redis && systemctl enable redis |
# 4.4 配置 php 连接 Redis
1. 修改 /etc/php.ini 文件。[所有节点都需要操作]
#1.php 已经引用 redis 的扩展模块 | |
[root@web01 ~]# cat /etc/php.d/redis.ini | |
; Enable redis extension module | |
extension = redis.so | |
; phpredis can be used to store PHP sessions. | |
; To do this, uncomment and configure below | |
;session.save_handler = redis | |
;session.save_path = "tcp://host1:6379?weight=1, tcp://host2:6379?weight=2&timeout=2.5, tcp://host3:6379?weight=2" | |
#2.php 连接 redis | |
[root@web ~]# vim /etc/php.ini | |
;session.save_handler = files | |
session.save_handler = redis | |
session.save_path = "tcp://192.168.40.41:6379" | |
;session.save_path = "tcp://192.168.40.41:6379?auth=123456" #如果 redis 存在密码,则使用该方式 |
2. 注释 php-fpm.d/www.conf 里面的两条内容,否则 session 内容会一直写入 /var/lib/php/session 目录中,从而造成会话共享失败。[所有节点都需要操作]
[root@web01 ~]# vim /etc/php-fpm.d/www.conf | |
;php_value[session.save_handler] = files | |
;php_value[session.save_path] = /var/lib/php/session |
3. 重启 php-fpm 服务。[所有节点都需要操作]
[root@web02 phpmyadmin]# php-fpm -t | |
[root@web02 phpmyadmin]# systemctl restart php-fpm |
# 4.5 测试集群会话共享
1. 使用浏览器登陆网站,获取对应的 cookie 信息
2. 检查 redis 中是否存在 cookie 对应的 session 信息
127.0.0.1:6379> keys * | |
1) "PHPREDIS_SESSION:33ed378672b5b53f491d6e409d44032f" |