天天看點

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,如需轉載請自行聯系原作者