Nginx+Tomcat+Redis实现session共享

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

  1. 基本环境 
  2.  
  3. 主机名 IP地址    安装软件    用途 
  4.  
  5. Nginx   192.168.122.10 nginx-1.8.1.tar.gz  负载均衡 
  6.  
  7. Tomcat1 192.168.122.12 apache-tomcat-7.0.68.tar.gz、jdk-7u79-linux-x64.gz   Tomcat服务 
  8.  
  9. Tomcat2 192.168.122.13 apache-tomcat-7.0.68.tar.gz、jdk-7u79-linux-x64.gz   Tomcat服务 
  10.  
  11. 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.建立用户和组:

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

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

  1. yum install pcre-devel openssl-devel perl-devel perl-ExtUtils-Embed gcc libxml2 libxml2-devel libxslt libxslt-devel –y 

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

  1. ./configure \ 
  2.  
  3. --prefix=/usr/local/nginx-1.8.1 \ 
  4.  
  5. --sbin-path=/usr/sbin/nginx \ 
  6.  
  7. --conf-path=/etc/nginx/nginx.conf \ 
  8.  
  9. --error-log-path=/var/log/nginx/error.log \ 
  10.  
  11. --http-log-path=/var/log/nginx/access.log \ 
  12.  
  13. --pid-path=/var/run/nginx/nginx.pid \ 
  14.  
  15. --lock-path=/var/lock/nginx.lock \ 
  16.  
  17. --user=nginx \ 
  18.  
  19. --group=nginx \ 
  20.  
  21. --with-http_stub_status_module \ 
  22.  
  23. --with-http_gzip_static_module \ 
  24.  
  25. --with-http_realip_module 
  26.  
  27. make && make install 

4.添加启动脚本

  1. #!/bin/sh 
  2.   
  3. # nginx - this script starts and stops the nginx daemon 
  4.   
  5. # chkconfig: - 85 15 
  6.  
  7. # description: Nginx is an HTTP(S) server, HTTP(S) reverse 
  8.  
  9. # proxy and IMAP/POP3 proxy server 
  10.  
  11. # processname: nginx 
  12.  
  13. # config: /etc/nginx/nginx.conf 
  14.  
  15. # config: /etc/sysconfig/nginx 
  16.  
  17. # pidfile: /var/run/nginx.pid 
  18.  
  19.   
  20. # Source function library. 
  21.  
  22. . /etc/rc.d/init.d/functions 
  23.  
  24. # Source networking configuration. 
  25.  
  26. . /etc/sysconfig/network 
  27.   
  28. # Check that networking is up. 
  29.  
  30. [ "$NETWORKING" = "no" ] && exit 0 
  31.  
  32. nginx="/usr/sbin/nginx" 
  33.  
  34. prog=$(basename $nginx) 
  35.   
  36. NGINX_CONF_FILE="/etc/nginx/nginx.conf" 
  37.   
  38.  
  39. [ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx 
  40.  
  41.  
  42. lockfile=/var/lock/subsys/nginx  
  43.  
  44. start() { 
  45.  
  46. [ -x $nginx ] || exit 5 
  47.  
  48. [ -f $NGINX_CONF_FILE ] || exit 6 
  49.  
  50. echo -n $"Starting $prog: " 
  51.  
  52. daemon $nginx -c $NGINX_CONF_FILE 
  53.  
  54. retval=$? 
  55.  
  56. echo 
  57.  
  58. [ $retval -eq 0 ] && touch $lockfile 
  59.  
  60. return $retval 
  61.  
  62.  
  63.  
  64. stop() { 
  65.  
  66. echo -n $"Stopping $prog: " 
  67.  
  68. killproc $prog -QUIT 
  69.  
  70. retval=$? 
  71.  
  72. echo 
  73.  
  74. [ $retval -eq 0 ] && rm -f $lockfile 
  75.  
  76. return $retval 
  77.  
  78. killall -9 nginx 
  79.  
  80.  
  81.  
  82. restart() { 
  83.  
  84. configtest || return $? 
  85.  
  86. stop 
  87.  
  88. sleep 1 
  89.  
  90. start 
  91.  
  92.  
  93.  
  94. reload() { 
  95.  
  96. configtest || return $? 
  97.  
  98. echo -n $"Reloading $prog: " 
  99.  
  100. killproc $nginx -HUP 
  101.  
  102. RETVAL=$? 
  103.  
  104. echo 
  105.  
  106.  
  107. force_reload() { 
  108.  
  109. restart 
  110.  
  111.  
  112.  
  113. configtest() { 
  114.  
  115. $nginx -t -c $NGINX_CONF_FILE 
  116.  
  117.  
  118.  
  119. rh_status() { 
  120.  
  121. status $prog 
  122.  
  123.  
  124.  
  125.  
  126. rh_status_q() { 
  127.  
  128. rh_status >/dev/null 2>&1 
  129.  
  130.  
  131.  
  132. case "$1" in 
  133.  
  134. start) 
  135.  
  136. rh_status_q && exit 0 
  137.  
  138. $1 
  139.  
  140. ;; 
  141.  
  142. stop) 
  143.  
  144. rh_status_q || exit 0 
  145.  
  146. $1 
  147.  
  148. ;; 
  149.  
  150. restart|configtest) 
  151.  
  152. $1 
  153.  
  154. ;; 
  155.  
  156. reload) 
  157.  
  158. rh_status_q || exit 7 
  159.  
  160. $1 
  161.  
  162. ;; 
  163.  
  164. force-reload) 
  165.  
  166. force_reload 
  167.  
  168. ;; 
  169.  
  170. status) 
  171.  
  172. rh_status 
  173.  
  174. ;; 
  175.  
  176. condrestart|try-restart) 
  177.  
  178. rh_status_q || exit 0 
  179.  
  180. ;; 
  181.  
  182. *) 
  183.  
  184. echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" 
  185.  
  186. exit 2 
  187.  
  188. esac     

5.添加到开机启动

  1. chkconfig –add nginx 
  2. chkconfig nginx on 

6.配置Nginx

  1. upstream myServer { 
  2.     server 10.0.10.121:8080; 
  3.     server 10.0.10.122:8080; 
  4.   } 
  5.   server { 
  6.     listen 80; 
  7.     server_name a.test01.com; 
  8.     location / { 
  9.       proxy_pass http://myServer; 
  10.     } 

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

  1. service nginx start 

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

安装JDK环境

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

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

  1. JAVA_HOME=/usr/local/jdk1.7.0_79/ 
  2. JAVA_BIN=$JAVA_HOME/bin 
  3. JRE_HOME=$JAVA_HOME/jre 
  4. PATH=$PATH:$JAVA_HOME/bin:$JAVA_HOME/jre/bin 
  5. CLASSPATH=$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/jre/lib/charsets.jar 
  6. export  JAVA_HOME  JAVA_BIN JRE_HOME  PATH  CLASSPATH 

1.安装Tomcat服务

  1. mkdir /data/ 
  2. tar xf apache-tomcat-7.0.68.tar.gz -C /data/ 

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

  1. ln -s /data/apache-tomcat-7.0.57/ /data/tomcat7 

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

  1. vim /data/tomcat7/ conf/context.xml   【在<Context>中间添加 </Context>】 
  2.  
  3. <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" /> 
  4.  
  5. <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"   
  6.  
  7.          host="192.168.122.14"   
  8.  
  9.          port="6379"   
  10.  
  11.          database="0"   
  12.  
  13.          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 /data/tomcat7/webapps/ROOT/test.jsp

  1. Server Info: 
  2. SessionID:<%=session.getId()%> 
  3. <br> 
  4. SessionIP:<%=request.getServerName()%> 
  5. <br> 
  6. SessionPort:<%=request.getServerPort()%> 
  7. <br> 
  8. <
  9. out.println("127"); //标记后端节点 
  10. %> 

 

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/目录和/data/apache-tomcat-7.0.57/ 目录,还有/etc/profile文件也同步到其它的Tomcat主机的相应目录下。

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

三、安装Redis【10.0.10.123】

自动安装脚本:

  1. #!/bin/bash 
  2. #==================================================== 
  3. # Author: Swper    EMail:hz328.com 
  4. # Create Date: 2016-03-21 
  5. # Description:redis单机单实例一键安装脚本  
  6. #==================================================== 
  7. # Filename: auto_install_redis.sh 
  8. # 注意事项 
  9. # 仅适用于Linux/Centos 64位 
  10. # 安装时需联网 
  11.  
  12. # 步骤 
  13. # 1.检查源码包是否存在,不存在就连网下载并安装redis 
  14. # 2.配置redis 
  15. # 3.准备redis启动停止脚本 
  16. # 4.启动redis 
  17.  
  18. #定义存放软件目录 
  19. software="/root/software" 
  20.  
  21. #如果软件目录不存在则新建该目录 
  22. if [[ ! -e $software ]]; then 
  23.     mkdir $software 
  24. fi 
  25.  
  26. #定义判断是否安装成功函数 
  27. function installIsOK(){ 
  28.     if [[ $2 == 0 ]]; then 
  29.         echo "$1 install ......  OK !" 
  30.     else 
  31.         echo "$1 install ......  Failure!" 
  32.         exit 1 
  33.     fi 
  34.  
  35. #进入软件目录 
  36. cd $software 
  37.  
  38.  
  39. # 1.下载并安装redis [判断是否存在] 
  40. redis='redis-3.0.7' 
  41. redis_dir='/data/redis' 
  42.  
  43. if [[ ! -f ${redis}.tar.gz ]]; then 
  44.     curl -LO http://download.redis.io/releases/${redis}.tar.gz 
  45. fi 
  46.  
  47. tar zxf ${redis}.tar.gz 
  48. cd $redis 
  49. make PREFIX=${redis_dir} install 
  50. if [[ $? == 0 ]]; then 
  51.     installIsOK ${redis} 0 
  52. else 
  53.     installIsOK ${redis} 3 
  54. fi 
  55.  
  56. # 2.配置redis 
  57. mkdir -p ${redis_dir}/{etc,run,log} 
  58. mkdir -p ${redis_dir}/data/6379 
  59. cp redis.conf ${redis_dir}/redis.conf 
  60. #cp ${redis_dir}/redis.conf ${redis_dir}/etc/redis_6379.conf 
  61.  
  62. #生成配置文件 
  63. redis_6379="${redis_dir}/etc/redis_6379.conf" 
  64. cat >> ${redis_6379} << "EOF" 
  65. daemonize yes 
  66. pidfile /data/redis/run/redis_6379.pid 
  67. port 6379 
  68. #bind 127.0.0.1 
  69. timeout 300 
  70. loglevel notice 
  71. logfile /data/redis/log/redis.log 
  72. databases 16 
  73. save 900 1 
  74. save 300 10 
  75. save 60 10000 
  76. stop-writes-on-bgsave-error no 
  77. rdbcompression yes 
  78. rdbchecksum no 
  79. dbfilename dump.rdb 
  80. dir /data/redis/data/6379 
  81. #slave-serve-stale-data yes 
  82. maxmemory 256mb 
  83. maxmemory-policy volatile-lru 
  84. maxmemory-samples 3 
  85. appendonly yes 
  86. appendfsync everysec 
  87. no-appendfsync-on-rewrite no 
  88. auto-aof-rewrite-percentage 100 
  89. auto-aof-rewrite-min-size 64mb 
  90. lua-time-limit 5000 
  91. slowlog-log-slower-than 10000 
  92. slowlog-max-len 1024 
  93. hash-max-ziplist-entries 512 
  94. hash-max-ziplist-value 64 
  95. list-max-ziplist-entries 512 
  96. list-max-ziplist-value 64 
  97. set-max-intset-entries 512 
  98. zset-max-ziplist-entries 128 
  99. zset-max-ziplist-value 64 
  100. activerehashing yes 
  101. client-output-buffer-limit normal 0 0 0 
  102. client-output-buffer-limit slave 256mb 64mb 60 
  103. client-output-buffer-limit pubsub 32mb 8mb 60 
  104. EOF 
  105.  
  106. # 3.redis启动停止脚本 
  107. redis_start="/etc/init.d/redis" 
  108. cat >> ${redis_start} << "END" 
  109. #!/bin/bash 
  110. export PATH="/data/redis/bin:$PATH" 
  111. EXEC="/data/redis/bin/redis-server" 
  112. CLIEXEC="/data/redis/bin/redis-cli" 
  113. PIDFILE="/data/redis/run/redis_6379.pid" 
  114. CONF="/data/redis/etc/redis_6379.conf" 
  115. PORT="6379" 
  116.  
  117. case "$1" in 
  118.     start) 
  119.         if [ -f $$PIDFILE ] 
  120.         then 
  121.                 echo "$PIDFILE exists, process is already running or crashed." 
  122.         else 
  123.                 echo "Starting Redis server..." 
  124.                 $EXEC $CONF 
  125.         fi 
  126.         ;; 
  127.     stop) 
  128.         if [ ! -f $PIDFILE ] 
  129.         then 
  130.                 echo "$PIDFILE does not exist, process is not running." 
  131.         else 
  132.                 PID=$(cat $PIDFILE) 
  133.                 echo "Stopping ..." 
  134.                 $CLIEXEC -p $PORT shutdown 
  135.                 while [ -x /proc/${PID} ] 
  136.                 do 
  137.                     echo "Waiting for Redis to shutdown ..." 
  138.                     sleep 1 
  139.                 done 
  140.                 echo "Redis stopped." 
  141.         fi 
  142.         ;; 
  143.     restart) 
  144.         $0 stop && $0 start 
  145.         ;; 
  146.     *) 
  147.         echo "Usage: $0 {start|stop|restart}" >&2 
  148.         exit 1 
  149.         ;; 
  150. esac 
  151.  
  152. END 
  153.  
  154. #增加可执行权限 
  155. chmod u+x ${redis_start} 
  156.  
  157. # 4.启动redis 
  158. ${redis_start} start 
  159. if [[ $? == 0 ]]; then 
  160.     echo "redis start ......  OK" 
  161. else 
  162.     echo "redis start ...... Failure" 
  163. fi 

1.给脚本添加执行权限:

  1. chmod +x auto_install_redis.sh 

2.执行自动安装

  1. sh auto_install_redis.sh 

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

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

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

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

2、启动Tomcat服务

3、启动Nginx服务

Nginx简单配置:

vim /etc/nginx/nginx.conf

  1. upstream myServer { 
  2.     server 192.168.122.12:8080; 
  3.     server 192.168.122.13:8080; 
  4. server { 
  5.     listen 80; 
  6.     server_name a.test01.com; 
  7.     location / { 
  8.         proxy_ignore_client_abort on; 
  9.         proxy_redirect off; 
  10.         proxy_set_header Host $host; 
  11.         proxy_set_header X-Real-IP $remote_addr; 
  12.         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
  13.         proxy_pass http://tomcat_server; 
  14.         client_max_body_size    10m; 
  15.         client_body_buffer_size 128k; 
  16.         proxy_connect_timeout   300; 
  17.         proxy_send_timeout      300; 
  18.         proxy_read_timeout      300; 
  19.         proxy_buffer_size       4k; 
  20.         proxy_buffers           4 32k; 
  21.         proxy_busy_buffers_size 64k; 
  22.         proxy_temp_file_write_size 64k; 
  23.     } 

 

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

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

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

  1. <session-config> 
  2.     <session-timeout>300</session-timeout> 
  3. </session-config> 

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

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

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

 

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