天天看点

Nginx+Tomcat+Redis实现session共享

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

架构图:

<code>基本环境 </code>

<code> </code> 

<code>主机名 IP地址    安装软件    用途 </code>

<code>Nginx   192.168.122.10 nginx-1.8.1.</code><code>tar</code><code>.gz  负载均衡 </code>

<code>Tomcat1 192.168.122.12 apache-tomcat-7.0.68.</code><code>tar</code><code>.gz、jdk-7u79-linux-x64.gz   Tomcat服务 </code>

<code>Tomcat2 192.168.122.13 apache-tomcat-7.0.68.</code><code>tar</code><code>.gz、jdk-7u79-linux-x64.gz   Tomcat服务 </code>

<code>Redis   192.168.122.14 redis-3.0.7.</code><code>tar</code><code>.gz  Session存储</code>

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

commons-pool2-2.2.jar

jedis-2.5.2.jar

tomcat-redis-session-manage-tomcat7.jar

一、安装Nginx

1.建立用户和组:

<code>groupadd nginx </code>

<code>useradd</code> <code>–s </code><code>/sbin/nologin</code> <code>–g nginx –M nginx –c “Nginx web user”</code>

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

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

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

<code>.</code><code>/configure</code> <code>\ </code>

<code>--prefix=</code><code>/usr/local/nginx-1</code><code>.8.1 \ </code>

<code>--sbin-path=</code><code>/usr/sbin/nginx</code> <code>\ </code>

<code>--conf-path=</code><code>/etc/nginx/nginx</code><code>.conf \ </code>

<code>--error-log-path=</code><code>/var/log/nginx/error</code><code>.log \ </code>

<code>--http-log-path=</code><code>/var/log/nginx/access</code><code>.log \ </code>

<code>--pid-path=</code><code>/var/run/nginx/nginx</code><code>.pid \ </code>

<code>--lock-path=</code><code>/var/lock/nginx</code><code>.lock \ </code>

<code>--user=nginx \ </code>

<code>--group=nginx \ </code>

<code>--with-http_ssl_module</code>

<code>--with-http_stub_status_module \ </code>

<code>--with-http_gzip_static_module \ </code>

<code>--with-http_realip_module </code>

<code>make</code> <code>&amp;&amp; </code><code>make</code> <code>install</code>

4.添加启动脚本

<code>#!/bin/sh </code>

<code>  </code> 

<code># nginx - this script starts and stops the nginx daemon </code>

<code># chkconfig: - 85 15 </code>

<code># description: Nginx is an HTTP(S) server, HTTP(S) reverse </code>

<code># proxy and IMAP/POP3 proxy server </code>

<code># processname: nginx </code>

<code># config: /etc/nginx/nginx.conf </code>

<code># config: /etc/sysconfig/nginx </code>

<code># pidfile: /var/run/nginx.pid </code>

<code># Source function library. </code>

<code>. </code><code>/etc/rc</code><code>.d</code><code>/init</code><code>.d</code><code>/functions</code> 

<code># Source networking configuration. </code>

<code>. </code><code>/etc/sysconfig/network</code> 

<code># Check that networking is up. </code>

<code>[ </code><code>"$NETWORKING"</code> <code>= </code><code>"no"</code> <code>] &amp;&amp; </code><code>exit</code> <code>0 </code>

<code>nginx=</code><code>"/usr/sbin/nginx"</code> 

<code>prog=$(</code><code>basename</code> <code>$nginx) </code>

<code>NGINX_CONF_FILE=</code><code>"/etc/nginx/nginx.conf"</code> 

<code>[ -f </code><code>/etc/sysconfig/nginx</code> <code>] &amp;&amp; . </code><code>/etc/sysconfig/nginx</code> 

<code>lockfile=</code><code>/var/lock/subsys/nginx</code>  

<code>start() { </code>

<code>[ -x $nginx ] || </code><code>exit</code> <code>5 </code>

<code>[ -f $NGINX_CONF_FILE ] || </code><code>exit</code> <code>6 </code>

<code>echo</code> <code>-n $</code><code>"Starting $prog: "</code> 

<code>daemon $nginx -c $NGINX_CONF_FILE </code>

<code>retval=$? </code>

<code>echo</code> 

<code>[ $retval -</code><code>eq</code> <code>0 ] &amp;&amp; </code><code>touch</code> <code>$lockfile </code>

<code>return</code> <code>$retval </code>

<code>}  </code>

<code>stop() { </code>

<code>echo</code> <code>-n $</code><code>"Stopping $prog: "</code> 

<code>killproc $prog -QUIT </code>

<code>[ $retval -</code><code>eq</code> <code>0 ] &amp;&amp; </code><code>rm</code> <code>-f $lockfile </code>

<code>killall -9 nginx </code>

<code>} </code>

<code>restart() { </code>

<code>configtest || </code><code>return</code> <code>$? </code>

<code>stop </code>

<code>sleep</code> <code>1 </code>

<code>start </code>

<code>reload() { </code>

<code>echo</code> <code>-n $</code><code>"Reloading $prog: "</code> 

<code>killproc $nginx -HUP </code>

<code>RETVAL=$? </code>

<code>force_reload() { </code>

<code>restart </code>

<code>configtest() { </code>

<code>$nginx -t -c $NGINX_CONF_FILE </code>

<code>rh_status() { </code>

<code>status $prog </code>

<code>rh_status_q() { </code>

<code>rh_status &gt;</code><code>/dev/null</code> <code>2&gt;&amp;1 </code>

<code>case</code> <code>"$1"</code> <code>in</code> 

<code>start) </code>

<code>rh_status_q &amp;&amp; </code><code>exit</code> <code>0 </code>

<code>$1 </code>

<code>;; </code>

<code>stop) </code>

<code>rh_status_q || </code><code>exit</code> <code>0 </code>

<code>restart|configtest) </code>

<code>reload) </code>

<code>rh_status_q || </code><code>exit</code> <code>7 </code>

<code>force-reload) </code>

<code>force_reload </code>

<code>status) </code>

<code>rh_status </code>

<code>condrestart|try-restart) </code>

<code>*) </code>

<code>echo</code> <code>$</code><code>"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"</code> 

<code>exit</code> <code>2 </code>

<code>esac</code>

5.添加到开机启动

<code>chkconfig --add nginx </code>

<code>chkconfig nginx on</code>

6.配置Nginx

<code>upstream myServer { </code>

<code>    </code><code>server 10.0.10.121:8080 weight=1 max_fails=2 fail_timeout=30s;; </code>

<code>    </code><code>server 10.0.10.122:8080 weight=1 max_fails=2 fail_timeout=30s;; </code>

<code>  </code><code>} </code>

<code>  </code><code>server { </code>

<code>    </code><code>listen 80; </code>

<code>    </code><code>server_name a.test01.com; </code>

<code>    </code><code>location / { </code>

<code>      </code><code>proxy_pass http:</code><code>//myServer</code><code>; </code>

<code>    </code><code>} </code>

<code>}</code>

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

<code>service nginx start</code>

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

安装JDK环境

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

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

<code>JAVA_HOME=</code><code>/usr/local/jdk1</code><code>.7.0_79/ </code>

<code>JAVA_BIN=$JAVA_HOME</code><code>/bin</code> 

<code>JRE_HOME=$JAVA_HOME</code><code>/jre</code> 

<code>PATH=$PATH:$JAVA_HOME</code><code>/bin</code><code>:$JAVA_HOME</code><code>/jre/bin</code> 

<code>CLASSPATH=$JAVA_HOME</code><code>/jre/lib</code><code>:$JAVA_HOME</code><code>/lib</code><code>:$JAVA_HOME</code><code>/jre/lib/charsets</code><code>.jar </code>

<code>export</code>  <code>JAVA_HOME  JAVA_BIN JRE_HOME  PATH  CLASSPATH</code>

1.安装Tomcat服务

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

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

<code>ln</code> <code>-s </code><code>/usr/local//apache-tomcat-7</code><code>.0.57/ </code><code>/usr/local/tomcat7</code>

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

<code>vim </code><code>/usr/local/tomcat7/conf/context</code><code>.xml   【在&lt;Context&gt;中间添加 &lt;</code><code>/Context</code><code>&gt;】 </code>

<code>&lt;Valve className=</code><code>"com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve"</code> <code>/&gt; </code>

<code>&lt;Manager className=</code><code>"com.orangefunction.tomcat.redissessions.RedisSessionManager"</code>   

<code>         </code><code>host=</code><code>"192.168.122.14"</code>   

<code>         </code><code>port=</code><code>"6379"</code>   

<code>         </code><code>database=</code><code>"0"</code>   

<code>         </code><code>maxInactiveInterval=</code><code>"60"</code> <code>/&gt;</code>

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

setMaxInactiveInterval和session-config的优先级: 

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

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

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

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

<code>Server Info: </code>

<code>SessionID:&lt;%=session.getId()%&gt; </code>

<code>&lt;br&gt; </code>

<code>SessionIP:&lt;%=request.getServerName()%&gt; </code>

<code>SessionPort:&lt;%=request.getServerPort()%&gt; </code>

<code>&lt;% </code>

<code>out.println(</code><code>"127"</code><code>); </code><code>//</code><code>标记后端节点 </code>

<code>%&gt;</code>

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

commons-pool2-2.2.jar 

jedis-2.5.2.jar 

tomcat-redis-session-manage-tomcat7.jar 

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

<code>scp</code> <code>–r </code><code>/usr/local/jdk1</code><code>.7.0_79 10.0.10.122:</code><code>/usr/local/</code> 

<code>scp</code> <code>–r </code><code>/data/apache-tomcat-7</code><code>.0.57 10.0.10.122:</code><code>/data/</code> 

<code>scp</code> <code>–r </code><code>/etc/profile</code> <code>10.0.10.122:</code><code>/etc/profile</code>

三、安装Redis【10.0.10.123】

自动安装脚本:

<code>#!/bin/bash </code>

<code>#==================================================== </code>

<code># Author: Swper    EMail:hz328.com </code>

<code># Create Date: 2016-03-21 </code>

<code># Description:redis单机单实例一键安装脚本  </code>

<code># Filename: auto_install_redis.sh </code>

<code># 注意事项 </code>

<code># 仅适用于Linux/Centos 64位 </code>

<code># 安装时需联网 </code>

<code># 步骤 </code>

<code># 1.检查源码包是否存在,不存在就连网下载并安装redis </code>

<code># 2.配置redis </code>

<code># 3.准备redis启动停止脚本 </code>

<code># 4.启动redis </code>

<code>#定义存放软件目录 </code>

<code>software=</code><code>"/root/software"</code> 

<code>#如果软件目录不存在则新建该目录 </code>

<code>if</code> <code>[[ ! -e $software ]]; </code><code>then</code> 

<code>    </code><code>mkdir</code> <code>$software </code>

<code>fi</code> 

<code>#定义判断是否安装成功函数 </code>

<code>function</code> <code>installIsOK(){ </code>

<code>    </code><code>if</code> <code>[[ $2 == 0 ]]; </code><code>then</code> 

<code>        </code><code>echo</code> <code>"$1 install ......  OK !"</code> 

<code>    </code><code>else</code> 

<code>        </code><code>echo</code> <code>"$1 install ......  Failure!"</code> 

<code>        </code><code>exit</code> <code>1 </code>

<code>    </code><code>fi</code> 

<code>#进入软件目录 </code>

<code>cd</code> <code>$software </code>

<code># 1.下载并安装redis [判断是否存在] </code>

<code>redis=</code><code>'redis-3.0.7'</code> 

<code>redis_dir=</code><code>'/data/redis'</code> 

<code>if</code> <code>[[ ! -f ${redis}.</code><code>tar</code><code>.gz ]]; </code><code>then</code> 

<code>    </code><code>curl -LO http:</code><code>//download</code><code>.redis.io</code><code>/releases/</code><code>${redis}.</code><code>tar</code><code>.gz </code>

<code>tar</code> <code>zxf ${redis}.</code><code>tar</code><code>.gz </code>

<code>cd</code> <code>$redis </code>

<code>make</code> <code>PREFIX=${redis_dir} </code><code>install</code> 

<code>if</code> <code>[[ $? == 0 ]]; </code><code>then</code> 

<code>    </code><code>installIsOK ${redis} 0 </code>

<code>else</code> 

<code>    </code><code>installIsOK ${redis} 3 </code>

<code>mkdir</code> <code>-p ${redis_dir}/{etc,run,log} </code>

<code>mkdir</code> <code>-p ${redis_dir}</code><code>/data/6379</code> 

<code>cp</code> <code>redis.conf ${redis_dir}</code><code>/redis</code><code>.conf </code>

<code>#cp ${redis_dir}/redis.conf ${redis_dir}/etc/redis_6379.conf </code>

<code>#生成配置文件 </code>

<code>redis_6379=</code><code>"${redis_dir}/etc/redis_6379.conf"</code> 

<code>cat</code> <code>&gt;&gt; ${redis_6379} &lt;&lt; </code><code>"EOF"</code> 

<code>daemonize </code><code>yes</code> 

<code>pidfile </code><code>/data/redis/run/redis_6379</code><code>.pid </code>

<code>port 6379 </code>

<code>#bind 127.0.0.1 </code>

<code>timeout 300 </code>

<code>loglevel notice </code>

<code>logfile </code><code>/data/redis/log/redis</code><code>.log </code>

<code>databases 16 </code>

<code>save 900 1 </code>

<code>save 300 10 </code>

<code>save 60 10000 </code>

<code>stop-writes-on-bgsave-error no </code>

<code>rdbcompression </code><code>yes</code> 

<code>rdbchecksum no </code>

<code>dbfilename dump.rdb </code>

<code>dir</code> <code>/data/redis/data/6379</code> 

<code>#slave-serve-stale-data yes </code>

<code>maxmemory 256mb </code>

<code>maxmemory-policy volatile-lru </code>

<code>maxmemory-samples 3 </code>

<code>appendonly </code><code>yes</code> 

<code>appendfsync everysec </code>

<code>no-appendfsync-on-rewrite no </code>

<code>auto-aof-rewrite-percentage 100 </code>

<code>auto-aof-rewrite-min-size 64mb </code>

<code>lua-</code><code>time</code><code>-limit 5000 </code>

<code>slowlog-log-slower-than 10000 </code>

<code>slowlog-max-len 1024 </code>

<code>hash</code><code>-max-ziplist-entries 512 </code>

<code>hash</code><code>-max-ziplist-value 64 </code>

<code>list-max-ziplist-entries 512 </code>

<code>list-max-ziplist-value 64 </code>

<code>set</code><code>-max-intset-entries 512 </code>

<code>zset-max-ziplist-entries 128 </code>

<code>zset-max-ziplist-value 64 </code>

<code>activerehashing </code><code>yes</code> 

<code>client-output-buffer-limit normal 0 0 0 </code>

<code>client-output-buffer-limit slave 256mb 64mb 60 </code>

<code>client-output-buffer-limit pubsub 32mb 8mb 60 </code>

<code>EOF </code>

<code># 3.redis启动停止脚本 </code>

<code>redis_start=</code><code>"/etc/init.d/redis"</code> 

<code>cat</code> <code>&gt;&gt; ${redis_start} &lt;&lt; </code><code>"END"</code> 

<code>export</code> <code>PATH=</code><code>"/data/redis/bin:$PATH"</code> 

<code>EXEC=</code><code>"/data/redis/bin/redis-server"</code> 

<code>CLIEXEC=</code><code>"/data/redis/bin/redis-cli"</code> 

<code>PIDFILE=</code><code>"/data/redis/run/redis_6379.pid"</code> 

<code>CONF=</code><code>"/data/redis/etc/redis_6379.conf"</code> 

<code>PORT=</code><code>"6379"</code> 

<code>    </code><code>start) </code>

<code>        </code><code>if</code> <code>[ -f $$PIDFILE ] </code>

<code>        </code><code>then</code> 

<code>                </code><code>echo</code> <code>"$PIDFILE exists, process is already running or crashed."</code> 

<code>        </code><code>else</code> 

<code>                </code><code>echo</code> <code>"Starting Redis server..."</code> 

<code>                </code><code>$EXEC $CONF </code>

<code>        </code><code>fi</code> 

<code>        </code><code>;; </code>

<code>    </code><code>stop) </code>

<code>        </code><code>if</code> <code>[ ! -f $PIDFILE ] </code>

<code>                </code><code>echo</code> <code>"$PIDFILE does not exist, process is not running."</code> 

<code>                </code><code>PID=$(</code><code>cat</code> <code>$PIDFILE) </code>

<code>                </code><code>echo</code> <code>"Stopping ..."</code> 

<code>                </code><code>$CLIEXEC -p $PORT </code><code>shutdown</code> 

<code>                </code><code>while</code> <code>[ -x </code><code>/proc/</code><code>${PID} ] </code>

<code>                </code><code>do</code> 

<code>                    </code><code>echo</code> <code>"Waiting for Redis to shutdown ..."</code> 

<code>                    </code><code>sleep</code> <code>1 </code>

<code>                </code><code>done</code> 

<code>                </code><code>echo</code> <code>"Redis stopped."</code> 

<code>    </code><code>restart) </code>

<code>        </code><code>$0 stop &amp;&amp; $0 start </code>

<code>    </code><code>*) </code>

<code>        </code><code>echo</code> <code>"Usage: $0 {start|stop|restart}"</code> <code>&gt;&amp;2 </code>

<code>esac</code> 

<code>END </code>

<code>#增加可执行权限 </code>

<code>chmod</code> <code>u+x ${redis_start} </code>

<code>${redis_start} start </code>

<code>    </code><code>echo</code> <code>"redis start ......  OK"</code> 

<code>    </code><code>echo</code> <code>"redis start ...... Failure"</code> 

<code>fi</code>

执行脚本自动安装

<code>sh auto_install_redis.sh</code>

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

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

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

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

2、启动Tomcat服务

3、启动Nginx服务

Nginx简单配置:

vim /etc/nginx/nginx.conf

<code>upstream myServer {  </code>

<code>    </code><code>server 192.168.122.12:8080 weight=1 max_fails=2 fail_timeout=30s;  </code>

<code>    </code><code>server 192.168.122.13:8080 weight=1 max_fails=2 fail_timeout=30s;  </code>

<code>server {  </code>

<code>    </code><code>listen 80;  </code>

<code>    </code><code>server_name a.test01.com;  </code>

<code>    </code><code>location / {  </code>

<code>        </code><code>proxy_ignore_client_abort on;  </code>

<code>        </code><code>proxy_redirect off;  </code>

<code>        </code><code>proxy_set_header Host $host;  </code>

<code>        </code><code>proxy_set_header X-Real-IP $remote_addr;  </code>

<code>        </code><code>proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  </code>

<code>        </code><code>proxy_pass http:</code><code>//tomcat_server</code><code>;  </code>

<code>        </code><code>client_max_body_size    10m;  </code>

<code>        </code><code>client_body_buffer_size 128k;  </code>

<code>        </code><code>proxy_connect_timeout   300;  </code>

<code>        </code><code>proxy_send_timeout      300;  </code>

<code>        </code><code>proxy_read_timeout      300;  </code>

<code>        </code><code>proxy_buffer_size       4k;  </code>

<code>        </code><code>proxy_buffers           4 32k;  </code>

<code>        </code><code>proxy_busy_buffers_size 64k;  </code>

<code>        </code><code>proxy_temp_file_write_size 64k;  </code>

<code>    </code><code>}  </code>

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

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

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

<code>&lt;session-config&gt; </code>

<code>    </code><code>&lt;session-timeout&gt;300&lt;</code><code>/session-timeout</code><code>&gt; </code>

<code>&lt;</code><code>/session-config</code><code>&gt;</code>

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

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

<code>127.0.0.1:6379&gt; ttl 7B088CABA49FAADF8BF1F23801104958 </code>

<code>(integer) 291   </code><code>#此处为秒数,如果客户端刷新一下网页,此值就会又人300开始;</code>

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

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