Nginx+Tomcat+Redis实现session共享

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介:

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

架构图:

1.jpg

1
2
3
4
5
6
7
8
9
10
11
基本环境 
  
主机名 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.建立用户和组:

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

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

1
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.编译参数:【由于只做负载均衡,按需要安装相对的功能】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
. /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.添加启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/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 
  
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 
  
[ -f $NGINX_CONF_FILE ] ||  exit 
  
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 
  
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 
  
$1 
  
;; 
  
stop) 
  
rh_status_q ||  exit 
  
$1 
  
;; 
  
restart|configtest) 
  
$1 
  
;; 
  
reload) 
  
rh_status_q ||  exit 
  
$1 
  
;; 
  
force-reload) 
  
force_reload 
  
;; 
  
status) 
  
rh_status 
  
;; 
  
condrestart|try-restart) 
  
rh_status_q ||  exit 
  
;; 
  
*) 
  
echo  $ "Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}" 
  
exit 
  
esac

5.添加到开机启动

1
2
chkconfig --add nginx 
chkconfig nginx on

6.配置Nginx

1
2
3
4
5
6
7
8
9
10
11
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 [此时启动后是无法连接的,因为后端的服务都没安装]

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
2
3
4
5
6
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服务

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

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

1
ln  -s  /usr/local//apache-tomcat-7 .0.57/  /usr/local/tomcat7

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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

1
2
3
4
5
6
7
8
9
10
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主机的相应目录下。

1
2
3
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】

自动安装脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/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 
     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 
                 done 
                 echo  "Redis stopped." 
         fi 
         ;; 
     restart) 
         $0 stop && $0 start 
         ;; 
     *) 
         echo  "Usage: $0 {start|stop|restart}"  >&2 
         exit 
         ;; 
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

执行脚本自动安装

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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即可看到成功访问页面。

2.jpg

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

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

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

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

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

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

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



本文转自 dengaosky 51CTO博客,原文链接:http://blog.51cto.com/dengaosky/2053456,如需转载请自行联系原作者

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3月前
|
缓存 NoSQL 应用服务中间件
2.2.2 redis,memcached,nginx网络组件
2.2.2 redis,memcached,nginx网络组件
|
3月前
|
NoSQL Java 应用服务中间件
4.网络设计与redis、memcached、nginx组件(二)
4.网络设计与redis、memcached、nginx组件(二)
28 0
|
3月前
|
存储 NoSQL 应用服务中间件
4.网络设计与redis、memcached、nginx组件(一)
4.网络设计与redis、memcached、nginx组件(一)
73 0
|
5月前
|
负载均衡 NoSQL 应用服务中间件
redis、memcached、nginx网络组件
redis、memcached、nginx网络组件
108 0
|
30天前
|
NoSQL 关系型数据库 MySQL
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
Docker安装详细步骤及相关环境安装配置(mysql、jdk、redis、自己的私有仓库Gitlab 、C和C++环境以及Nginx服务代理)
188 0
|
30天前
|
NoSQL Java 应用服务中间件
使用innoSetup将mysql+nginx+redis+jar包打包成windows安装包
使用innoSetup将mysql+nginx+redis+jar包打包成windows安装包
使用innoSetup将mysql+nginx+redis+jar包打包成windows安装包
|
5月前
|
NoSQL Redis
shiro的session信息放redis反序列化异常解决
shiro的session信息放redis反序列化异常解决
|
1月前
|
存储 NoSQL 前端开发
【SpringBoot】Redis集中管理Session和自定义用户参数解决登录状态及校验问题
【SpringBoot】Redis集中管理Session和自定义用户参数解决登录状态及校验问题
|
1月前
|
缓存 NoSQL 安全
【Redis】2、Redis应用之【根据 Session 和 Redis 进行登录校验和发送短信验证码】
【Redis】2、Redis应用之【根据 Session 和 Redis 进行登录校验和发送短信验证码】
48 0
|
3月前
|
NoSQL 关系型数据库 应用服务中间件
redis,memcached,nginx网络组件,网络编程——reactor的应用
目标 明白网络模块要处理那些事情 reactor 是怎么处理这些事情的 reactor 如何封装的 网络模块与业务逻辑的关系 如何优化 reactor 网络编程关注的问题
49 1