Nginx+Tomcat+Redis实现session共享

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nginx+Tomcat+Redis实现session共享相关的知识,希望对你有一定的参考价值。

通过nginx作为前端的负载,把请求分发到后端的Tomcat服务器上,提高并发数;但是单纯的通过Nginx的ip_hash负载是很多问题的。只要用户一切换网络或者后端Tomcat主机宕机session就失效;

架构图:

技术分享图片

基本环境 
 
主机名 IP地址    安装软件    用途 
 
Nginx   192.168.122.10 nginx-1.8.1.tar.gz  负载均衡 
 
Tomcat1 192.168.122.12 apache-tomcat-7.0.68.tar.gz、jdk-7u79-linux-x64.gz   Tomcat服务 
 
Tomcat2 192.168.122.13 apache-tomcat-7.0.68.tar.gz、jdk-7u79-linux-x64.gz   Tomcat服务 
 
Redis   192.168.122.14 redis-3.0.7.tar.gz  Session存储

Tomcat要在Redis上实现Session共享的话就要以下几个依赖包:【把它们复制到/tomcat/lib/目录下】不同版本有可能造成错误。

commons-pool2-2.2.jar

jedis-2.5.2.jar

tomcat-redis-session-manage-tomcat7.jar


一、安装Nginx

1.建立用户和组:

groupadd nginx 
useradd –s /sbin/nologin –g nginx –M nginx –c “Nginx web user”

2.安装一些所需依赖包:

yum install gcc gcc-c++ zlib zlib-devel pcre-devel openssl-devel perl-devel perl-ExtUtils-Embed libxml2 libxml2-devel libxslt libxslt-devel -y

3.编译参数:【由于只做负载均衡,按需要安装相对的功能】

./configure \ 
--prefix=/usr/local/nginx-1.8.1 \ 
--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=/var/run/nginx/nginx.pid \ 
--lock-path=/var/lock/nginx.lock \ 
--user=nginx \ 
--group=nginx \ 
--with-http_ssl_module
--with-http_stub_status_module \ 
--with-http_gzip_static_module \ 
--with-http_realip_module 
 
make && make install

4.添加启动脚本

#!/bin/sh 
  
# nginx - this script starts and stops the nginx daemon 
  
# chkconfig: - 85 15 
 
# description: Nginx is an HTTP(S) server, HTTP(S) reverse 
 
# proxy and IMAP/POP3 proxy server 
 
# processname: nginx 
 
# config: /etc/nginx/nginx.conf 
 
# config: /etc/sysconfig/nginx 
 
# pidfile: /var/run/nginx.pid 
 
  
# Source function library. 
 
. /etc/rc.d/init.d/functions 
 
# Source networking configuration. 
 
. /etc/sysconfig/network 
  
# Check that networking is up. 
 
[ "$NETWORKING" = "no" ] && exit 0 
 
nginx="/usr/sbin/nginx" 
 
prog=$(basename $nginx) 
  
NGINX_CONF_FILE="/etc/nginx/nginx.conf" 
  
 
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx 
 
 
lockfile=/var/lock/subsys/nginx  
 
start() { 
 
[ -x $nginx ] || exit 5 
 
[ -f $NGINX_CONF_FILE ] || exit 6 
 
echo -n $"Starting $prog: " 
 
daemon $nginx -c $NGINX_CONF_FILE 
 
retval=$? 
 
echo 
 
[ $retval -eq 0 ] && touch $lockfile 
 
return $retval 
 
}  
 
stop() { 
 
echo -n $"Stopping $prog: " 
 
killproc $prog -QUIT 
 
retval=$? 
 
echo 
 
[ $retval -eq 0 ] && rm -f $lockfile 
 
return $retval 
 
killall -9 nginx 
 
} 
 
 
restart() { 
 
configtest || return $? 
 
stop 
 
sleep 1 
 
start 
 
} 
 
 
reload() { 
 
configtest || return $? 
 
echo -n $"Reloading $prog: " 
 
killproc $nginx -HUP 
 
RETVAL=$? 
 
echo 
 
} 
 
force_reload() { 
 
restart 
 
} 
 
 
configtest() { 
 
$nginx -t -c $NGINX_CONF_FILE 
 
} 
 
 
rh_status() { 
 
status $prog 
 
} 
 
 
 
rh_status_q() { 
 
rh_status >/dev/null 2>&1 
 
} 
 
 
case "$1" in 
 
start) 
 
rh_status_q && exit 0 
 
$1 
 
;; 
 
stop) 
 
rh_status_q || exit 0 
 
$1 
 
;; 
 
restart|configtest) 
 
$1 
 
;; 
 
reload) 
 
rh_status_q || exit 7 
 
$1 
 
;; 
 
force-reload) 
 
force_reload 
 
;; 
 
status) 
 
rh_status 
 
;; 
 
condrestart|try-restart) 
 
rh_status_q || exit 0 
 
;; 
 
*) 
 
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" 
 
exit 2 
 
esac

5.添加到开机启动

chkconfig --add nginx 
chkconfig nginx on

6.配置Nginx

upstream myServer { 
    server 10.0.10.121:8080 weight=1 max_fails=2 fail_timeout=30s;; 
    server 10.0.10.122:8080 weight=1 max_fails=2 fail_timeout=30s;; 
  } 
  server { 
    listen 80; 
    server_name a.test01.com; 
    location / { 
      proxy_pass http://myServer; 
    } 
}

7.启动Nginx [此时启动后是无法连接的,因为后端的服务都没安装]

service nginx start

二、配置Tomcat服务【10.0.10.121、10.0.10.122】

安装JDK环境

tar xf jdk-7u79-linux-x64.gz -C /usr/local/

配置环境变量:vim /etc/profile    【最后添加下面配置,根据情况配置】

JAVA_HOME=/usr/local/jdk1.7.0_79/ 
JAVA_BIN=$JAVA_HOME/bin 
JRE_HOME=$JAVA_HOME/jre 
PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin 
CLASSPATH=$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/jre/lib/charsets.jar 
export  JAVA_HOME  JAVA_BIN JRE_HOME  PATH  CLASSPATH

1.安装Tomcat服务

tar xf apache-tomcat-7.0.68.tar.gz -C /usr/local/

作一个软连接:【软连接方便日志升级】

ln -s /usr/local//apache-tomcat-7.0.57/ /usr/local/tomcat7

2.修改配置文件,添加一个测试页。

vim /usr/local/tomcat7/conf/context.xml   【在<Context>中间添加 </Context>】 
 
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /> 
 
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"   
 
         host="192.168.122.14"   
 
         port="6379"   
 
         database="0"   
 
         maxInactiveInterval="60" />

注释:上面host指Redis的主机IP,port就是端口,database就是数据库0,maxInactiveInterval超时时间为60秒,60秒后就会变化Session值。

setMaxInactiveInterval和session-config的优先级: 

1>、setMaxInactiveInterval的优先级高,如果setMaxInactiveInterval没有设置,则默认是session-config中设置的时间。 

2>、setMaxInactiveInterval设置的是当前会话的失效时间,不是整个web服务的。 

3>、setMaxInactiveInterval的参数是秒,session-config当中配置的session-timeout是分钟。

4>.测试页面:vim /usr/local/tomcat7/webapps/ROOT/test.jsp

Server Info: 
SessionID:<%=session.getId()%> 
<br> 
SessionIP:<%=request.getServerName()%> 
<br> 
SessionPort:<%=request.getServerPort()%> 
<br> 
<% 
out.println("127"); //标记后端节点 
%>

3.把几个Session同步的jar包复制到tomcat目录下的lib目录下:

  1. commons-pool2-2.2.jar 

  2. jedis-2.5.2.jar 

  3. tomcat-redis-session-manage-tomcat7.jar 

4.把/usr/local/jdk1.7.0_79/目录和/usr/local/apache-tomcat-7.0.57/ 目录,还有/etc/profile文件也同步到其它的Tomcat主机的相应目录下。

scp –r /usr/local/jdk1.7.0_79 10.0.10.122:/usr/local/ 
scp –r /data/apache-tomcat-7.0.57 10.0.10.122:/data/ 
scp –r /etc/profile 10.0.10.122:/etc/profile

三、安装Redis【10.0.10.123】

自动安装脚本:

#!/bin/bash 
#==================================================== 
# Author: Swper    EMail:hz328.com 
# Create Date: 2016-03-21 
# Description:redis单机单实例一键安装脚本  
#==================================================== 
# Filename: auto_install_redis.sh 
# 注意事项 
# 仅适用于Linux/Centos 64位 
# 安装时需联网 
 
# 步骤 
# 1.检查源码包是否存在,不存在就连网下载并安装redis 
# 2.配置redis 
# 3.准备redis启动停止脚本 
# 4.启动redis 
 
#定义存放软件目录 
software="/root/software" 
 
#如果软件目录不存在则新建该目录 
if [[ ! -e $software ]]; then 
    mkdir $software 
fi 
 
#定义判断是否安装成功函数 
function installIsOK(){ 
    if [[ $2 == 0 ]]; then 
        echo "$1 install ......  OK !" 
    else 
        echo "$1 install ......  Failure!" 
        exit 1 
    fi 
} 
 
#进入软件目录 
cd $software 
 
 
# 1.下载并安装redis [判断是否存在] 
redis='redis-3.0.7' 
redis_dir='/data/redis' 
 
if [[ ! -f ${redis}.tar.gz ]]; then 
    curl -LO http://download.redis.io/releases/${redis}.tar.gz 
fi 
 
tar zxf ${redis}.tar.gz 
cd $redis 
make PREFIX=${redis_dir} install 
if [[ $? == 0 ]]; then 
    installIsOK ${redis} 0 
else 
    installIsOK ${redis} 3 
fi 
 
# 2.配置redis 
mkdir -p ${redis_dir}/{etc,run,log} 
mkdir -p ${redis_dir}/data/6379 
cp redis.conf ${redis_dir}/redis.conf 
#cp ${redis_dir}/redis.conf ${redis_dir}/etc/redis_6379.conf 
 
#生成配置文件 
redis_6379="${redis_dir}/etc/redis_6379.conf" 
cat >> ${redis_6379} << "EOF" 
daemonize yes 
pidfile /data/redis/run/redis_6379.pid 
port 6379 
#bind 127.0.0.1 
timeout 300 
loglevel notice 
logfile /data/redis/log/redis.log 
databases 16 
save 900 1 
save 300 10 
save 60 10000 
stop-writes-on-bgsave-error no 
rdbcompression yes 
rdbchecksum no 
dbfilename dump.rdb 
dir /data/redis/data/6379 
#slave-serve-stale-data yes 
maxmemory 256mb 
maxmemory-policy volatile-lru 
maxmemory-samples 3 
appendonly yes 
appendfsync everysec 
no-appendfsync-on-rewrite no 
auto-aof-rewrite-percentage 100 
auto-aof-rewrite-min-size 64mb 
lua-time-limit 5000 
slowlog-log-slower-than 10000 
slowlog-max-len 1024 
hash-max-ziplist-entries 512 
hash-max-ziplist-value 64 
list-max-ziplist-entries 512 
list-max-ziplist-value 64 
set-max-intset-entries 512 
zset-max-ziplist-entries 128 
zset-max-ziplist-value 64 
activerehashing yes 
client-output-buffer-limit normal 0 0 0 
client-output-buffer-limit slave 256mb 64mb 60 
client-output-buffer-limit pubsub 32mb 8mb 60 
EOF 
 
# 3.redis启动停止脚本 
redis_start="/etc/init.d/redis" 
cat >> ${redis_start} << "END" 
#!/bin/bash 
export PATH="/data/redis/bin:$PATH" 
EXEC="/data/redis/bin/redis-server" 
CLIEXEC="/data/redis/bin/redis-cli" 
PIDFILE="/data/redis/run/redis_6379.pid" 
CONF="/data/redis/etc/redis_6379.conf" 
PORT="6379" 
 
case "$1" in 
    start) 
        if [ -f $$PIDFILE ] 
        then 
                echo "$PIDFILE exists, process is already running or crashed." 
        else 
                echo "Starting Redis server..." 
                $EXEC $CONF 
        fi 
        ;; 
    stop) 
        if [ ! -f $PIDFILE ] 
        then 
                echo "$PIDFILE does not exist, process is not running." 
        else 
                PID=$(cat $PIDFILE) 
                echo "Stopping ..." 
                $CLIEXEC -p $PORT shutdown 
                while [ -x /proc/${PID} ] 
                do 
                    echo "Waiting for Redis to shutdown ..." 
                    sleep 1 
                done 
                echo "Redis stopped." 
        fi 
        ;; 
    restart) 
        $0 stop && $0 start 
        ;; 
    *) 
        echo "Usage: $0 {start|stop|restart}" >&2 
        exit 1 
        ;; 
esac 
 
END 
 
#增加可执行权限 
chmod u+x ${redis_start} 
 
# 4.启动redis 
${redis_start} start 
if [[ $? == 0 ]]; then 
    echo "redis start ......  OK" 
else 
    echo "redis start ...... Failure" 
fi

执行脚本自动安装

sh auto_install_redis.sh

执行后会自动在/root/目录下创建一个software目录,同时会自动下载redis。完成后自动启动。

ss –lnt 检查端口6379是否在使用即说明正常运行。

完成上面操作后启动服务:

1、启动redis,由于安装时已经启动了就不需要手工启动。

2、启动Tomcat服务

3、启动Nginx服务

Nginx简单配置:

vim /etc/nginx/nginx.conf

upstream myServer {  
    server 192.168.122.12:8080 weight=1 max_fails=2 fail_timeout=30s;  
    server 192.168.122.13:8080 weight=1 max_fails=2 fail_timeout=30s;  
}  
server {  
    listen 80;  
    server_name a.test01.com;  
    location / {  
        proxy_ignore_client_abort on;  
        proxy_redirect off;  
        proxy_set_header Host $host;  
        proxy_set_header X-Real-IP $remote_addr;  
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
        proxy_pass http://tomcat_server;  
        client_max_body_size    10m;  
        client_body_buffer_size 128k;  
        proxy_connect_timeout   300;  
        proxy_send_timeout      300;  
        proxy_read_timeout      300;  
        proxy_buffer_size       4k;  
        proxy_buffers           4 32k;  
        proxy_busy_buffers_size 64k;  
        proxy_temp_file_write_size 64k;  
    }  
}

测试效果:打开浏览器访问nginx的IP即可看到成功访问页面。

技术分享图片

此时如果一直刷新存入到redis的session值是不会变的,但是如果30秒用户没反应就会失效。

可以通过修改tomcat目录conf/web.xml文件:

<session-config> 
    <session-timeout>300</session-timeout> 
</session-config>

此处默认为60,分钟为单位;但是经过redis的包时就变成了60秒,此处是个问题;所以这里修改成300变成秒了;注意上面的注释,由于setMaxInactiveInterval在这里没有配置,所以优先级以session-timeout;

通过redis-c查看到失效时间:

127.0.0.1:6379> ttl 7B088CABA49FAADF8BF1F23801104958 
(integer) 291   #此处为秒数,如果客户端刷新一下网页,此值就会又人300开始;

总结:其实此处用到的jar存在着很多问题,不建议在正式的生产环境使用;

以上是关于Nginx+Tomcat+Redis实现session共享的主要内容,如果未能解决你的问题,请参考以下文章

Redis+Tomcat+Nginx集群实现Session共享,Tomcat Session共享

Nginx+Tomcat+Redis实现负载均衡资源分离session共享

Redis+Tomcat+Nginx集群实现Session共享,Tomcat Session共享

Linux学习-keepalived+nginx+Tomcat+redis实现高可用和Session共享

Linux学习-keepalived+nginx+Tomcat+redis实现高可用和Session共享

Redis+Tomcat+Nginx实现session共享