通過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>&& </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>] && </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>] && . </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 ] && </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 ] && </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 ></code><code>/dev/null</code> <code>2>&1 </code>
<code>case</code> <code>"$1"</code> <code>in</code>
<code>start) </code>
<code>rh_status_q && </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 【在<Context>中間添加 <</code><code>/Context</code><code>>】 </code>
<code><Valve className=</code><code>"com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve"</code> <code>/> </code>
<code><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>/></code>
注釋:上面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
<code>Server Info: </code>
<code>SessionID:<%=session.getId()%> </code>
<code><br> </code>
<code>SessionIP:<%=request.getServerName()%> </code>
<code>SessionPort:<%=request.getServerPort()%> </code>
<code><% </code>
<code>out.println(</code><code>"127"</code><code>); </code><code>//</code><code>标記後端節點 </code>
<code>%></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>>> ${redis_6379} << </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>>> ${redis_start} << </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 && $0 start </code>
<code> </code><code>*) </code>
<code> </code><code>echo</code> <code>"Usage: $0 {start|stop|restart}"</code> <code>>&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><session-config> </code>
<code> </code><code><session-timeout>300<</code><code>/session-timeout</code><code>> </code>
<code><</code><code>/session-config</code><code>></code>
此處預設為60,分鐘為機關;但是經過redis的包時就變成了60秒,此處是個問題;是以這裡修改成300變成秒了;注意上面的注釋,由于setMaxInactiveInterval在這裡沒有配置,是以優先級以session-timeout;
通過redis-c檢視到失效時間:
<code>127.0.0.1:6379> ttl 7B088CABA49FAADF8BF1F23801104958 </code>
<code>(integer) 291 </code><code>#此處為秒數,如果用戶端重新整理一下網頁,此值就會又人300開始;</code>
總結:其實此處用到的jar存在着很多問題,不建議在正式的生産環境使用;
本文轉自 dengaosky 51CTO部落格,原文連結:http://blog.51cto.com/dengaosky/2053456,如需轉載請自行聯系原作者