拓扑图

IP网络规划

nginx 172.17.10.150
tomcatA 172.17.10.168
tomcatB 172.17.10.169

访问原理

用户访问nginx客户端,nginx通过反向代理功能,把.jsp和.do后缀的请求发送到后端的tomcat集群,后端的tomcat集群会话session复制,从而实现会话保持功能。

nginx配置文件


user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
error_log  /var/log/nginx/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  65535;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log     /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush     on;
    tcp_nodelay    on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip  on;
    upstream tomcat-cluster {
#   ip_hash
    server 172.17.10.168:8080  weight=1;
    server 172.17.10.169:8080  weight=1;
    }


    server {
        listen     80;
        server_name  xiaomi.mage.com;
        root /data/xiaomi;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        
#       if ($http_user_agent ~ "WOW64") {
#       rewrite ^(.*)$ /404.html break;
#       }


        location ~* \.(jsp|do)$ {
        proxy_pass http://tomcat-cluster;
        }
        location / {
        index  index.jsp index.php index.html index.htm;
        }
        location /status{
            stub_status on;
            auth_basic "status AH";
            auth_basic_user_file ./htpasswd;
        }
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
       #    root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
       #    root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }

这样实现分离的话会出现一个问题,访问172.17.10.150/index.jsp页面如下 由于是实验环境,我们可以在nginx配置文件中server段中添加一个location,把.css和.png也代理到后端的tomcat集群,这样就能找到.css和.png文件了。(这样配置只是为了试验,如果本机有其他web服务里有以.png或者.css结尾的文件就找不到了)

location ~* \.(css|png)$ {
        proxy_pass http://tomcat-cluster;
        }

或者可以nginx代理端和tomcat处在一个物理机上,把root指向tomcat的工作目录也可以

root  /usr/locat/tomcat/webapps/BOOT----------->tomcat默认的.jsp文件在这个目录下

后端集群实现session会话

方法一 基于集群的session复制实现(适用于小型集群)

tomcat配置文件server.xml
<Engine name="Catalina" defaultHost="localhost">

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->

      <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="45565" frequency="500" dropTime="3000"/>
        <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="172.17.10.168" 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="/"/>
        <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

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

        </Cluster>


server.xml配置详解

Cluster配置:

Cluster(集群,族) 节点,如果你要配置tomcat集群,则需要使用此节点. className 表示tomcat集群时,之间相互传递信息使用那个类来实现信息 之间的传递. channelSendOptions可以设置为2、4、8、10,每个数字代表一种方式 2 = Channel.SEND_OPTIONS_USE_ACK(确认发送) 4 = Channel.SEND_OPTIONS_SYNCHRONIZED_ACK(同步发送) 8 = Channel.SEND_OPTIONS_ASYNCHRONOUS(异步发送) 在异步模式下,可以通过加上确认发送(Acknowledge)来提高可靠性,此时channelSendOptions设为10

Manager介绍

Manger对象用于实现HTTP会话管理的功能,Tomcat中有5种Manger的实现: (1).StandardManager Tomcat6的默认会话管理器,用于非集群环境中对单个处于运行状态的Tomcat实例会话 进行管理。当Tomcat关闭时,这些会话相关的数据会被写入磁盘上的一个名叫 SESSION.ser的文件,并在Tomcat下次启动时读取此文件。 (2).PersistentManager 当一个会话长时间处于空闲状态时会被写入到swap会话对象,这对于内存资源比较吃紧 的应用环境来说比较有用。 (3).DeltaManager(目前这个更适用) 用于Tomcat集群的会话管理器,它通过将改变了会话数据同步给集群中的其它节点实现 会话复制。这种实现会将所有会话的改变同步给集群中的每一个节点,也是在集群环境中 用得最多的一种实现方式。 (4).BackupManager 用于Tomcat集群的会话管理器,与DeltaManager不同的是,某节点会话的改变只会同 步给集群中的另一个而非所有节点。

Manager配置

className-指定实现org.apache.catalina.ha.ClusterManager接口的类,信息之间的管 理 expireSessionsOnShutdown-设置为true时,一个节点关闭,将导致集群下的所有 Session失效 notifyListenersOnReplication-集群下节点间的Session复制、删除操作,是否通知 session listeners

<Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
Channel介绍和配置

Channel是Tomcat节点之间进行通讯的工具。Channel包括4个组件: Membership 集群的可用节点列表 Receiver 接收器,负责接收消息 Sender 发送器,负责发送消息 Interceptor Cluster的拦截器

<Channel className="org.apache.catalina.tribes.group.GroupChannel">
Membership:维护集群的可用节点列表,它可以检查到新增的节点,也可以检查到没有心跳的节点

className-指定Membership使用的类 address-组播地址 port-组播端口 frequency-发送心跳(向组播地址发送UDP数据包)的时间间隔(单位:ms)。默认值为500 dropTime-Membership在dropTime(单位:ms)内未收到某一节点的心跳,则将该节点从可用节点列表删除。默认值为3000 注: 组播(Multicast):一个发送者和多个接收者之间实现一对多的网络连接。 一个发送者同时给多个接收者传输相同的数据,只需复制一份相同的数据包。 它提高了数据传送效率,减少了骨干网络出现拥塞的可能性 相同组播地址、端口的Tomcat节点,可以组成集群下的子集群

<Membership className="org.apache.catalina.tribes.membership.McastService" 
address="228.0.0.4" 
port="45564"
frequency="500" 
dropTime="3000"/>
Receiver : 接收器,负责接收消息

接收器分为两种:BioReceiver(阻塞式)、NioReceiver(非阻塞式) className-指定Receiver使用的类 address-接收消息的地址 port-接收消息的端口 autoBind-端口的变化区间 如果port为4000,autoBind为100,接收器将在4000-4099间取一个端口,进行监听 selectorTimeout-NioReceiver内轮询的超时时间 maxThreads-线程池的最大线程数

<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" 
address="172.17.10.168" 
port="4000" 
autoBind="100" 
selectorTimeout="5000" 
maxThreads="6"/>  
(这里这个接收地址默认auto绑定的是本机的127地址,可以修改为本机桥接地址,便于通信)
Sender : 发送器,负责发送消息

Sender内嵌了Transport组件,Transport真正负责发送消息

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

Transport:定义传输方式 Transport分为两种:bio.PooledMultiSender(阻塞式)、nio.PooledParallelSender(非阻塞式)

<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
Interceptor : Cluster的拦截器

TcpFailureDetector-网络、系统比较繁忙时,Membership可能无法及时更新可用节点列表,此时TcpFailureDetector可以拦截到某个节点关闭的信息,并尝试通过TCP连接到此节点,以确保此节点真正关闭,从而更新集群可以用节点列表

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

MessageDispatch15Interceptor-查看Cluster组件发送消息的方式是否设置为 Channel.SEND_OPTIONS_ASYNCHRONOUS(Cluster标签下的channelSendOptions为8时)。 设置为Channel.SEND_OPTIONS_ASYNCHRONOUS时, MessageDispatch15Interceptor先将等待发送的消息进行排队,然后将排好队的消息转给Sender

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

ClusterListener : 监听器,监听Cluster组件接收的消息 使用DeltaManager时,Cluster接收的信息通过ClusterSessionListener传递给DeltaManager -->

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

配置文件web.xml

<welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
<distributable/>   (在文件结尾处</web-app>上方加上这个参数就行)
</web-app>

测试页面

<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<font color="blue">TomcatA 
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("abc","abc"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
如图

如果测试不通过的话,就复制tomcat配置文件conf目录下的web.xml文件到你的测试目录下的WEB-INF(需要手动创建)

这样基于tomcat集群的session复制的配置就完成了~

方法二 tomcat结合memcached实现seesion共享 (适用于比较大的集群)

环境准备

Tomcat Session Server (memcached) https://github.com/magro/memcached-session-manager 支持的session server类型: memcached: redis:

相关包

memcached-session-manager-2.1.1.jar memcached-session-manager-tc7-2.1.1.jar(注意:要根据tomcat版本下载相应的) spymemcached-2.11.1.jar msm-javolution-serializer-2.1.1.jar javolution-5.4.3.1.jar

剩下的内容下次博客再来详细介绍,溜了溜了~