1. 程式人生 > >Tomcat7 session同步集群搭建

Tomcat7 session同步集群搭建

centos7.2 tomcat7 session 同步集群搭建

Tomcat session同步集群搭建

一、如何保持session會話

為了使web能適應大規模的訪問,需要實現應用的集群部署。集群最有效的方案就是負載均衡,而實現負載均衡用戶每一個請求都有可能被分配到不固定的服務器上,這樣我們首先要解決session的統一來保證無論用戶的請求被轉發到哪個服務器上都能保證用戶的正常使用,即需要實現session的共享機制。


因為我這邊提供web服務的是兩臺Tomcat服務器,也會有session共享的議題存在,經過與開發人員的交談中了解到,他們應用的session是由JVM產生的,所以為了讓一臺tomcat服務器出現故障時,另外一臺可以繼續承接服務,並保持原先會話,即在故障服務器上處於登入狀態的用戶,不需要再次登入。


二、在集群系統下實現session統一的有如下三種方案:

1、請求精確定位產生session的web服務器:sticky session,即當前用戶的請求都集中定位到一臺服務器中,這臺服務器保存了用戶的session登錄信息,如果宕機,

則等同於單點部署,會丟失,會話也不會復制。

#註:上述情況適用於在web端做好session共享,負載均衡層做好sticky session,則就可以實現精準定位又實現解除故障的情況。


2、session復制共享:session replication,如tomcat自帶session共享,主要是指集群環境下,多臺應用服務器之間同步session,使session保持一致,對外透明。

如果其中一臺服務器發生故障,根據負載均衡的原理,調度器會遍歷尋找可用節點,分發請求,由於session已同步,故能保證用戶的session信息不會丟失,實現會話復制。

但必須在同一種中間件之間完成(如:tomcat-tomcat之間).

session復制帶來的性能損失會快速增加.特別是當session中保存了較大的對象,而且對象變化較快時, 性能下降更加顯著,會消耗系統性能。這種特性使得web應用的水平擴展受到了限制。

Session內容通過廣播同步給成員,會造成網絡流量瓶頸,即便是內網瓶頸,在大並發下表現也並不好。

#註:上述2適用於並發量小的集群需求


3.基於 memcache/redis緩存的 session 共享

即使用cacheDB存取session信息,應用服務器接受新請求將session信息保存在cache DB中,當應用服務器發生故障時,調度器會遍歷尋找可用節點,分發請求,當應用服務器發現session不在本機內存時,則去cache DB中查找,如果找到則復制到本機,這樣實現session共享和高可用。


二、本文主要講第二種集群方式,配置基於tomcat7環境,通過tomcat集群自帶的session復制,session信息將會被自動復制到各個節點。

涉及環境:

主機 操作系統 IP地址 主要軟件

Nginx centos7.2 172.16.22.2 nginx-1.10.1


tomcat01 centos7.2 172.16.22.3 jdk-8u102-linux-x64.tar.gz、apache-tomcat-7.0.72.tar.gz


tomcat02 centos7.2 172.16.22.4 jdk-8u102-linux-x64.tar.gz、apache-tomcat-7.0.72.tar.gz


三、安裝軟件工作

1.安裝Nginx

a.首先安裝nginx前需要安裝一些依賴庫 openssl-devel 、zlib-devel 、pcre-devel

[root@~]# yum install -y openssl-devel 、zlib-devel 、pcre-devel

因為程序默認是使用 nobody 身份運行的,我們為了便於查看可以創建nginx 用戶來運行,首先添加nginx組和用戶,可不創建家目錄,並且不允許登陸系統

[root@~]# groupadd nginx

[root@~]# useradd -M -s /sbin/nologin -g nginx nginx

b.解壓nginx-1.10.1.tar.gz,並編譯

[root@~]# tar xf nginx-1.10.1.tar.gz

[root@~]# cd nginx-1.10.1

# ./configure \

--prefix=/data0/nginx \

--pid-path=/data0/nginx/logs/nginx.pid \

--lock-path=/var/lock/nginx.lock \

--user=nginx \

--group=nginx \

--with-http_ssl_module \

--with-http_flv_module \

--with-http_stub_status_module \

--with-http_gzip_static_module \

--http-client-body-temp-path=/var/tmp/nginx/client/ \

--http-proxy-temp-path=/var/tmp/nginx/proxy/ \

--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \

--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \

--http-scgi-temp-path=/var/tmp/nginx/scgi \

--with-pcre

結果如下:

Configuration summary

+ using system PCRE library

+ using system OpenSSL library

+ md5: using OpenSSL library

+ sha1: using OpenSSL library

+ using system zlib library


nginx path prefix: "/data0/nginx"

nginx binary file: "/data0/nginx/sbin/nginx"

nginx modules path: "/data0/nginx/modules"

nginx configuration prefix: "/data0/nginx/conf"

nginx configuration file: "/data0/nginx/conf/nginx.conf"

nginx pid file: "/data0/nginx/nginx.pid"

nginx error log file: "/data0/nginx/logs/error.log"

nginx http access log file: "/data0/nginx/logs/access.log"

nginx http client request body temporary files: "/var/tmp/nginx/client/"

nginx http proxy temporary files: "/var/tmp/nginx/proxy/"

nginx http fastcgi temporary files: "/var/tmp/nginx/fcgi/"

nginx http uwsgi temporary files: "/var/tmp/nginx/uwsgi"

nginx http scgi temporary files: "/var/tmp/nginx/scgi"

c.上述配置完,就進行編譯安裝

[root@~]# make && make install

[root@~]# mkdir /var/tmp/nginx/client/ -pv


等編譯安裝完成後在 /data0 下就會出現 nginx 這個目錄了,進入這個目錄後發現目錄非常簡單。

它的配置文件存放在 conf 目錄中,網頁文件存放在 html 中,日誌文件存放在 logs 中,

sbin 目錄下只有一個可執行程序 "nginx"


d.進入/data0/nginx/conf,配置nginx.conf

配置nginx.conf文件

[[email protected] ] vim nginx.conf

user nginx;

#user root;

worker_processes auto;

error_log /data0/nginx/logs/error.log crit;

pid /data0/nginx/logs/nginx.pid;

worker_rlimit_nofile 100000;

events {

worker_connections 2048;

multi_accept on;

use epoll;

}

http {

include /data0/nginx/conf/mime.types;

default_type application/octet-stream;

server_tokens off;

sendfile on;

tcp_nopush on;

tcp_nodelay on;

keepalive_timeout 10;

client_header_timeout 10;

client_body_timeout 10;

reset_timedout_connection on;

send_timeout 10;

limit_conn_zone $binary_remote_addr zone=addr:5m;

limit_conn addr 100;

gzip_disable "msie6";

gzip_proxied any;

gzip_min_length 1000;

gzip_comp_level 6;

gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

open_file_cache max=100000 inactive=20s;

open_file_cache_valid 30s;

open_file_cache_min_uses 2;

open_file_cache_errors on;

#load balance

upstream tomcat {

server 172.16.22.3:8080;

server 172.16.22.4:8080;

}

#load balance

server {

listen 80;

server_name localhost;

charset utf-8;

location ~ /uploads/.*\.(gif|jpg|jpeg|png|pdf|doc|xls|docx|xlsx|apk|htm|html|mp4|flv)$ {

expires 24h;

root /data0/nginx/res/home/;

access_log off;

proxy_store on;

proxy_store_access user:rw group:rw all:rw;

proxy_temp_path /data0/nginx/res/home/;

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;

client_max_body_size 20m;

client_body_buffer_size 1280k;

proxy_connect_timeout 900;

proxy_send_timeout 900;

proxy_read_timeout 900;

proxy_buffer_size 40k;

proxy_buffers 40 320k;

proxy_busy_buffers_size 640k;

proxy_temp_file_write_size 640k;

if ( !-e $request_filename)

{

proxy_pass http://127.0.0.1:80;

}

}


location / {

client_max_body_size 20m;

proxy_pass http://localhost:8080/;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


# allow 113.28.26.107

# deny all;

}

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

e.檢測配置文檔是否準確無誤

[root@~] # /data0/nginx/sbin/nginx -t

nginx: the configuration file /data0/work/nginx/conf/nginx.conf syntax is ok

nginx: configuration file /data0/work/nginx/conf/nginx.conf test is successful

#註:如果有問題,通過提示內容進行解決即可


f.啟動nginx服務

[root@~] # /data0/nginx/sbin/nginx


g.但是記得關閉防火牆或將端口加入防火墻規則

因為在CentOS 7 以後不再用iptables作為防火牆,直接使用firewall

[root@~]# systemctl stop firewalld.service && systemctl disable firewalld.service

或者

[root@~]# firewall-cmd --permanet --add-port=80/tcp

[root@~]# firewall-cmd --reload


h.打開瀏覽器訪問http://172.16.22.2或者在本機使用[root@~] curl http://localhost:80訪問,如果能打開nginx默認網頁出現Welcome to nginx字樣,則nginx安裝成功


2.安裝配置java 與tomcat

a.在安裝tomcat前需要安裝Java

解壓並且進入安裝包

[root@~]# tar -zxvf jdk-8u101-linux-x64.tar.gz

[root@~]# mkdir /usr/local/java

[root@~]mv jdk1.8.0_101/ /usr/local/java/


b.配置環境變量

[root@~]# vim /etc/profile

在最後一行添加上下列信息

# java

export JAVA_HOME=/usr/local/java/jdk1.8.0_101

export JRE_HOME=/usr/local/java/jdk1.8.0_101/jre

export CLASSPATH=.:$JRE_HOME/lib/dt.jar:$JRE_HOME/lib/tools.jar

export PATH=$JRE_HOME/bin:$JRE_HOME/bin:$PATH


c.讓配置生效查看版本

[root@~]# source /etc/profile

[root@~]# java -version

java version "1.8.0_101"

Java(TM) SE Runtime Environment (build 1.8.0_101-b13)

Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)


d.首先tomcat是一個免安裝軟件直接進行解壓即可,查看tomcat版本及JVM配置環境信息

[root@~]# tar -xf apache-tomcat-7.0.72.tar.gz

[root@~]# sh /data0/tomcat01/bin/version.sh

Using CATALINA_BASE: /data0/tomcat01

Using CATALINA_HOME: /data0/tomcat01

Using CATALINA_TMPDIR: /data0/tomcat01/temp

Using JRE_HOME: /usr/local/java/jdk1.8.0_101/jre

Using CLASSPATH: /data0/tomcat01/bin/bootstrap.jar:/data0/tomcat01/bin/tomcat-juli.jar

Server version: Apache Tomcat/7.0.72

Server built: Sep 14 2016 12:12:26 UTC

Server number: 7.0.72.0

OS Name: Linux

OS Version: 3.10.0-327.el7.x86_64

Architecture: amd64

JVM Version: 1.8.0_101-b13

JVM Vendor: Oracle Corporation


e.啟動tomcat服務

[root@~]# sh /data0/tomcat01/bin/startup.sh


f.查看是否開放了tomcat端口 8080 8009 8005,服務是否正常

[root@~]# netstat -nltp

Active Internet connections (only servers)

Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name

tcp 0 0 0.0.0.0:8009 0.0.0.0:* LISTEN 9844/java

tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 9844/java

tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 32434/nginx: master

tcp 0 0 127.0.0.1:8005 0.0.0.0:* LISTEN 9844/java


3.呈現訪問測試session頁面的準備工作

在上述步驟完畢後,便修改tomcat配置文件

a.註:設置默認主機,並增加jvmRoute

[root@~]# vim /data0/tomcat01/conf/server.xml

找到第102行

102 <!-- You should set jvmRoute to support load-balancing via AJP ie :

103 <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">

104 -->

在下面添加下列內容,該jvmRoute改為Tomcat01

如: <Engine name="Catalina" defaultHost="localhost" jvmRoute="Tomcat01">

目的是為了在使用負載均衡層訪問頁面時,了解承接服務的是哪一臺tomcat服務器

#註:tomcat02也是這麽做,只是jvmRoute不同,只要把Tomcat01更換成Tomcat02即可


b.在發布文檔目錄內添加測試文件

[root@~]# vim /data0/tomcat01/webapps/ROOT/jsp/index.jsp

<[email protected] language="java" import="java.util.*" pageEncoding="UTF-8"%>

<html>

<head>

<title>tomcat01</title>

</head>

<body>

<h1><font color="red">Session serviced by tomcat </font></h1>

<table aligh="center" border="1">

<tr>

<td>Session ID </td>

<td><%=session.getId() %></td>

<% session.setAttribute("abc","adc");%>

</tr>

<tr>

<td>Created on</td>

<td><%=session.getCreationTime() %></td>

</tr>

</table>

</body>

<html>


#註:另外Tomcat02節點與tomcat01節點配置基本類似,另外為了區分由哪個節點提供訪問,測試頁標題也不同。其他的配置都相同


c.重啟tomcat服務,分別進行測試訪問index.jsp

訪問Tomcat01測試頁面

技術分享


訪問Tomcat02測試頁面

技術分享

可以看到訪問結果中頁面呈現的session ID 不同,到這,可以說準備工作就基本完成,下面我們來配置tomcat的負載均衡,通過session復制實現會話保持。


4.配置tomcat集群環境:

配置會話共享集群,分別在tomcat01和tomcat02完成下面的操作

a.配置server.xml文件

[root@~]# vim /data0/tomcat01/conf/server.xml

找到110行左右

110 <!--

111 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

112 -->

在下面添加下列內容:

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"

channelSendOptions="8" >


<Manager className="org.apache.catalina.ha.session.DeltaManager"

expireSessionsOnShutdown="false"

notifyListenersOnReplication="true"/>

<Channel className="org.apache.catalina.tribes.group.GroupChannel">

<Membership className="org.apache.catalina.tribes.membership.McastService"

address="228.0.0.4"

port="45564"

frequency="500"

dropTime="3000"/>

<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"

address="auto"

port="4000"

autoBind="100"

selectorTimeout="5000"

maxThreads="6"/>

<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">

<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>

</Sender>

<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>

<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>

</Channel>

<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"

filter=".*\.gif|.*\.js|.*\.jpeg|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt"/>

<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"

tempDir="/tmp/war-temp/"

deployDir="/tmp/war-deploy/"

watchDir="/tmp/war-listen/"

watchEnabled="false"/>


<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>

<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>

</Cluster>

#上述添加集群的內容來自於官網配置文檔,請參考:http://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html


b.配置應用代碼目錄下的web.xml文件

修改應用的web.xml文件,加入標簽<distributable/>,這是tomcat集群實現session復制的的關鍵,如果沒有添加,Tomcat集群可以說就無法實現。設置很簡單如下所示:

[root@~]# vim /data0/tomcat01/webapps/ROOT/WEB-INF/web.xml

<welcome-file>index.shtml</welcome-file>

<welcome-file>index.jspx</welcome-file>

</welcome-file-list>

<distributable/> --添加的

</web-app>


#註:直接加在</web-app>之前就可以了。


c.兩臺Tomcat均按上述步驟修改了配置文檔後,我們重啟下兩臺Tomcat服務器,並通過瀏覽器訪問jsp測試頁面

我們重啟下兩臺Tomcat服務器Tomcat服務

tomcat02重啟Tomcat服務

[root@~]#sh /data0/tomcat02/bin/shutdown.sh

[root@~]#sh /data0/tomcat02/bin/startup.sh


再對tomcat01重啟Tomcat服務

[root@~]#sh /data0/tomcat01/bin/shutdown.sh

[root@~]#sh /data0/tomcat01/bin/startup.sh


查看先啟動那臺機器上的catalina.out日誌

[[email protected] ~]# tail -f /data0/work/tomcat02/logs/catalina.out

May 11, 2017 11:46:29 AM org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded

INFO: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{172, 16, 22, 3}:4000,{172, 16, 22, 3},4000, alive=1011, securePort=-1, UDP Port=-1, id={-66 109 3 57 13 98 70 60 -86 23 -103 16 91 -52 -91 -49 }, payload={}, command={}, domain={}, ]

從上面的SimpleTcpCluster memberAdded來看tomcat01和tomcat02成了集群成員了。


然後訪問負載均衡層的測試頁面

技術分享

刷新,再看測試頁面

技術分享

大家可以從圖中看到,不管你怎麽刷新SessionID都不會變,只有承載的服務器在變化而已,從而說明我們的Tomcat的DeltaManager集群配置完成,實現了會話共享。

本文出自 “10793382” 博客,請務必保留此出處http://10803382.blog.51cto.com/10793382/1924812

Tomcat7 session同步集群搭建