分布式下Session一致性架构举例

一、问题及方案

见这篇文章:分布式下Session一致性问题

二、分布式环境搭建:

分布式下Session一致性架构举例_第1张图片
image

系统环境

[root@centos7 ~]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
[root@centos7 ~]# 

2.1 安装jdk

# 下载jdk-8u141-linux-x64.tar.gz
# 创建目录
mkdir -p /opt/java
# 解压
tar -xzvf jdk-8u141-linux-x64.tar.gz -C /opt/java
# 创建链接
ln -s /opt/java/jdk1.8.0_141 /usr/local/jdk
# 设置变量 /etc/profile末尾添加
export JAVA_HOME=/usr/local/jdk
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
# 使变量生效
source /etc/profile
export PATH=$JAVA_HOME/bin:$PATH
# 验证
java -version

2.2 安装tomcat

安装3个tomcat并设置其端口号

# 下载apache-tomcat-8.5.16.tar.gz
# 创建目录
mkdir -p /opt/tomcat
# 解压
tar -xzvf apache-tomcat-8.5.16.tar.gz -C /opt/tomcat
# 清空ROOT目录
rm -rf /opt/tomcat/apache-tomcat-8.5.16/webapps/ROOT/*
# 复制3个tomcat
cd /opt/tomcat
cp -a apache-tomcat-8.5.16 tomcat1
cp -a apache-tomcat-8.5.16 tomcat2
cp -a apache-tomcat-8.5.16 tomcat3
# 修改端口号
sed -i '22s/8005/8'"$i"'05/' $file
sed -i '69s/8080/8'"$i"'80/' $file
sed -i '116s/8009/8'"$i"'09/' $file

修改如下3个端口号

分布式下Session一致性架构举例_第2张图片
image

用如下脚本修改:a.sh

#!/bin/sh

for i in {1..3}
do
  file=/opt/tomcat/tomcat"$i"/conf/server.xml
  sed -i '22s/8005/8'"$i"'05/' $file
  sed -i '69s/8080/8'"$i"'80/' $file
  sed -i '116s/8009/8'"$i"'09/' $file
  #sed -i '148s#appBase=".*"#appBase="/data/webapps"#' $file
done

执行脚本修改端口

sh a.sh
执行后,3个tomcat的端口号分别改为
8180,8280,8380

启动并验证这3个tomcat

# 分别向3个tomcat写入一个测试文件a.txt
for i in {1..3};do echo 8"$i"80>/opt/tomcat/tomcat"$i"/webapps/ROOT/a.txt;done

# 启动
for i in {1..3};do /opt/tomcat/tomcat"$i"/bin/startup.sh;done

# 验证
for i in {1..3};do curl 127.0.0.1:8"$i"80/a.txt;done
分布式下Session一致性架构举例_第3张图片
image

2.3 安装nginx

# 下载nginx-1.13.9.tar.gz
mkdir -p /opt/nginx/nginx-1.3.13.9
# 创建用户
useradd nginx -s /sbin/nologin -M
# 安装pcre openssl
yum install pcre pcre-devel openssl openssl-devel -y
# 解压、编译安装
tar -xzvf nginx-1.13.9.tar.gz
cd nginx-1.13.9
./configure --user=nginx --group=nginx --prefix=/opt/nginx/nginx-1.13.9 --with-http_stub_status_module --with-http_ssl_module
make
make install
# 创建链接
ln -s /opt/nginx/nginx-1.13.9 /usr/local/nginx
# 设置环境变量
echo 'export PATH=/usr/local/nginx/sbin:$PATH' >> /etc/profile
source /etc/profile

nginx常用命令

# 启动
nginx
# 检查配置文件
nginx -t
# 平滑启动
nginx -s reload
# 检查
netstat -tunlp | grep nginx

遇到的问题:

nginx: [emerg] getpwnam("nginx") failed
未创建nginx用户

配置nginx

/usr/local/nginx/conf/nginx.conf

worker_processes  1;
events {
    worker_connections  1024;
}

# http最外层模块
http {
    # 全局变量参数
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream web_pool {
        server 127.0.0.1:8180 weight=1;
        server 127.0.0.1:8280 weight=1;
        server 127.0.0.1:8380 weight=2;
    }

    # server相当于虚拟站点
    server {
        listen       80;
        server_name  localhost;
        location / {
            proxy_pass  http://web_pool;
            index  index.html index.htm;
        }
    }
}

测试一下

for i in {1..9};do curl 127.0.0.1/a.txt;done
分布式下Session一致性架构举例_第4张图片
image

2.4 安装redis

wget http://download.redis.io/releases/redis-4.0.8.tar.gz
mkdir -p /opt/redis
tar -xzvf redis-4.0.8.tar.gz -C /opt/redis/
ln -s /opt/redis/redis-4.0.8 /usr/local/redis
cd /usr/local/redis
make && make install

# 配置让其他机器也可以访问
vi /usr/local/redis/redis.conf
#bind 127.0.0.1
bind 0.0.0.0

操作redis

# 查看redis版本
redis-cli -v
# 启动redis
redis-server redis.conf > /tmp/redis.log 2>&1 &
# or
nohup redis-server redis.conf &
# 监控redis
redis-cli -h 192.168.234.130 -p 6379 monitor
# 关闭redis
redis-cli -h 127.0.0.1 -p 6379 shutdown

客户端

# 连接
redis-cli -h 192.168.5.220
# 查看
keys *
# 清空
flushall

三、问题重现

3.1 web应用

java-web-login

只实现登录功能

/login   登录页面,已登录跳转到/index
/logout  退出
/index   首页,未登录跳转到/login

将这个应用部署到3个tomcat上

重启tomcat

for i in {1..3};do /opt/tomcat/tomcat"$i"/bin/shutdown.sh;done
for i in {1..3};do /opt/tomcat/tomcat"$i"/bin/startup.sh;done
分布式下Session一致性架构举例_第5张图片
image
分布式下Session一致性架构举例_第6张图片
image

3.2 问题描述

登录界面是8280端口,输入用户名密码点击登录,由于nginx配置的是基于轮询的算法进行分发,8380端口的服务器处理的登录,因此session创建于8380端口,而8280处于非登录状态。

四、解决实现

4.1 session sticky

修改nginx的分发算法改为基于ip

upstream web_pool {
    # 默认是轮询
    ip_hash;
    server 127.0.0.1:8180 weight=1;
    server 127.0.0.1:8280 weight=1;
    server 127.0.0.1:8380 weight=2;
}

修改后重启nginx

nginx -t
nginx -s reload

4.2 session replication

http://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html

tomcat配置server.xml






    
    
        
        
        
        
            
        
        
        
    
    
    
    
    

tomcat的配置web.xml

# 修改每个tomcat下的conf/web.xml不起作用
# 一定要修改每个应用的web.xml,在这个节点下添加

4.3 session数据集中存储

数据存储到redis,使用spring-data-redis

见应用java-web-login

把web_spring-redis.xml重命名为web.xml,部署到tomcat即可,得先启动redis参照“安装redis”这一节。

spring-redis.xml

    


    
    
        
            
                classpath*:redis.properties
            
        
    

    
        
    

    
        
        
    

    
        
        
        
        
        
    

注意:

  • Spring版本的选择 >=4.0.3

pom.xml


    4.0.0
    com.yysue
    java-web-login
    war
    java-web-login
    0.0.1-SNAPSHOT

    
        1.8
        4.0.3.RELEASE
    

    
    
        
            javax.servlet
            javax.servlet-api
            3.0.1
            provided
        

        
            javax.servlet.jsp
            jsp-api
            2.2
            provided
        

        
            javax.servlet
            jstl
            1.2
        

        
            org.springframework
            spring-core
            ${spring.version}
        
        
            org.springframework
            spring-web
            ${spring.version}
        
        
            org.springframework
            spring-oxm
            ${spring.version}
        
        
            org.springframework
            spring-tx
            ${spring.version}
        
        
            org.springframework
            spring-webmvc
            ${spring.version}
        
        
            org.springframework
            spring-context
            ${spring.version}
        
        
            org.springframework
            spring-context-support
            ${spring.version}
        
        
            org.springframework
            spring-aop
            ${spring.version}
        

        
            org.springframework.data
            spring-data-redis
            1.5.2.RELEASE
        

        
            org.springframework.session
            spring-session-data-redis
            1.2.2.RELEASE
        

        
            redis.clients
            jedis
            2.8.1
        

    

    
        
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    ${java.version}
                    ${java.version}
                
            
        
    

你可能感兴趣的:(分布式下Session一致性架构举例)