说明:记录一次对请求分发,无法登录系统的问题。
场景
如下,在此结构下,如何判断该用户是已登录的用户;
常规操作,用户登录后给用户发Token,同时将发放的Token存入到Redis中。要求用户后续请求需要用户携带Token访问。后端接口在处理请求之前,鉴别用户的Token(合法有效),通过校验才处理请求,不然返回对应的错误信息(未登录、已过期)。
在此之上,只需要后端服务器连接同一台Redis即可。
问题
我现在面临的问题是,两台后端服务器连接的Redis就是同一台。Nginx分发请求,策略是轮询,登录时访问的是后端服务器A,登录完成后接口访问后端服务器B,报“用户未登录或登录过期”信息;
我推测项目中应该没有给登录用户发放Token,而是使用了进程内缓存(ThreadLocal)来存储相关信息的,也就是说把登录成功的数据存在了代码里。
解决
于是,我想到一种方案,将Nginx分发策略改为 IP哈希 ,这种策略会将IP地址相同的请求分发给同一台后端服务器处理,这样既实现了分发请求,又保证了上述鉴权问题。
如下,是对某项目请求分发的Nginx配置(部分)
# 分发请求,将请求分发到这两台服务器上,默认策略是轮询;
upstream back_server {
server 192.168.100.1:8080;
server 192.168.100.2:8080;
}
server {
listen 80;
server_name localhost;
location / {
alias /html/projects;
index index.html index.htm;
}
location /controller/ {
proxy_pass http://back_server/controller/;
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_set_header X-Scheme $scheme;
proxy_read_timeout 180s;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_redirect off;
}
}
在此基础上,可将分发策略改为ip_hash
,可解决请求分发场景下的鉴权问题;
upstream back_server {
ip_hash;
server 192.168.100.1:8080;
server 192.168.100.2:8080;
}