负载均衡后端的会话保持详解
cookie和session
什么是cookie?
为了解决网络访问的用户是谁的问题,因此cookie应运而生,当用户登陆成功后,服务器会在返回响应数据的同时也携带着cookie信息给到客户端浏览器,之后客户端每次发起请求只要携带着这个cookie信息,服务端就会验证这个cookie信息,进而判断用户是谁,用户则会处于登录的状态,无需再登录,同时也改善了网络传输效率。
但是由于cookie是保存在客户端浏览器的数据,因此也很容易被获取,存在安全方面隐患。
什么是session?
session本质是通过以cookie的方式向客户端发送随机字符串,每次客户端发起请求时只要携带该随机字符串便可被服务端获取进而验证用户登录的身份。session的实现依赖于cookie。
session信息是保存在服务端的数据,所以比较安全。
用户请求整个session过程的基本原理
- 用户发出登录请求。
- 服务端判断用户账户密码是否正确
- 如正确,则返回数据并在cookie中写随机字符串(session ID),并且在服务端以{随机字符串:{'k':'v'}}的形式存储用户相关数据。
- 客户端接收服务端在cookie中写随机字符串(session ID),并且保留在浏览器本地。
- 下次同一个客户发送请求,携带cookie(包含session ID)信息在请求报文里。
- 服务端会判断客户端提交的cookie信息是否包含session ID,如有再去服务器中查询该session ID 是否有对应的session数据,如果有则说明是登录过的用户,返回请求的数据。
利用session复制实现会话保持
即采用复制的方法,当产生session时,同步复制到所有集群节点,把session共享(重要普遍):
将session集中存储到某一固定地点:
- 文件中存放(PHP服务默认)。
- 数据库中存放即采用将session存储至MySQL数据库中(例如:discuz论坛)
- 内存数据库(memcache,redis)中存放(推荐)
优点:速度快。缺点:需要配置内存数据库,并且要配置动态服务配置文件。
用redis实现session共享案例
- web01与web02安装phpmyadmin
# web01:
cat phpmyadmin.etiantian.org.conf
server {
listen 80;
server_name phpmyadmin.etiantian.org;
root /data/phpmyadmin;
index index.php index.html;
location ~ .php$ {
root /data/phpmyadmin;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# web02:
cat phpmyadmin.etiantian.org.conf
server {
listen 80;
server_name phpmyadmin.etiantian.org;
root /data/phpmyadmin;
index index.php index.html;
location ~ .php$ {
root /data/phpmyadmin;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
- 部署lb代理
cat phpmyadmin.etiantian.org.conf
server 10.0.0.10 weight=1;
server 10.0.0.11 weight=1;
}
server {
listen 80;
server_name phpmyadmin.etiantian.org;
location / {
proxy_pass http://backend;
proxy_set_header Host $http_host;
}
}
- 安装redis:
# 在web01和web02上查看php redis访问支持
rpm -qa|grep redis
php71w-pecl-redis-3.1.6-1.w7.x86_64
# 安装配置redis 10.0.0.16
yum install redis -y
vim /etc/redis.confbind 0.0.0.0
bind 0.0.0.0 #表示允许所有ip访问
systemctl restart redis
systemctl status redis
systemctl enable redis
- 分别将web01,web02的php应用服务器的session信息、修改存储至Redis中(/etc/php.ini)
vim /etc/php.ini
session.save_handler = redis
session.save_path = "tcp://10.0.0.16:6379?weight=1&timeout=2.5"
# 使用;注释如下两行
vim /etc/php-fpm.d/www.conf
;php_value[session.save_handler] = files
;php_value[session.save_path] = /var/lib/php/session
# Redis有密码的配置方法:这里没密码不用配置
session.save_path = "tcp://10.0.0.16:6379?auth=1qaz@WSX"
- 重启php-fpm
web01和web02都重启
systemctl restart php-fpm
- 测试访问
将lb01负载均衡调度修改为默认轮询的方式测试。
检查是不是登录后依然是登录状态。
再次刷新:
看到实现了负载均衡并且没有登录界面,也实现了用redis共享session。
同时,查看redis中是否有session数据。
127.0.0.1:6379> keys *
1. "PHPREDIS_SESSION:785bd4a0ec24595f52088ba7c7dfef6d"
2. "PHPREDIS_SESSION:9089726f488eb193b044e8be9041111c"