一.实验原理

 

  <T1> <T2>
    . \ / .

    . / \ .
  <M1> <M2>

 

  nignx+tomcat+memcached可实现交叉缓存,即Tomcat-1 (T1) session 存储在 memcached-2 (T2)上。只有当 M2 不可用时,T1 才将 session 储在 memcached-1 上(M1 T1 failoverNode)。使用这种配置的好处是,当 T1 M1 同时崩溃时也不会丢失 session 会话,避免单点故障。


二.实验过程


  系统环境:rhel6 x32 selinux and iptables disabled
        主机角色:主机1:172.25.46.1             nginx

                         node1: 172.25.46.2      tomcat  memcached

                         node2: 172.25.46.3          tomcat  memcached
    软件下载:http://www.nginx.org

                         http://tomcat.apache.org

                          http://code.google.com/p/memcached-session-manager/

                           http://www.oracle.com/technetwork/java/javase/archive-139210.html

 

    以下步骤在 node1 node2 上实施


     jdk安装

    # sh jdk-6u20-linux-i586.bin

     

     运行后,生成目录jdk1.6.0_20

      # mv  jdk1.6.0_20  /usr/local/lnmp

      # ln  -s  jdk1.6.0_20/  java

  

  配置环境变量

     # vim /etc/profile

      export JAVA_HOME=/usr/local/lnmp/java

      exportJAVAPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib

      export PATH=$PATH:$JAVA_HOME/bin

     # source /etc/profile


     tomcat安装

    # ls

    apache-tomcat-7.0.37.tar.gz

    #    cd /usr/local/lnmp/

    #    tar zxf  /root/apache-tomcat-7.0.37.tar.gz

    #    ln -s apache-tomcat-7.0.37 tomcat

    #    cd tomcat


 启动tomcat

     #    bin/startup.sh 

     #    netstat -antlp

            tcp       0      0 :::8080                     :::*                        LISTEN      5650/java


    session 的序列化方案官方推荐的有 4 种:

    1. java serialization

    2. msm-kryo-serializer

    3. msm-javolution-serializer

    4. msm-xstream-serializer
    其中性能最好的序列化方案是 Kryo,
此实验我们采用 kryo 方式。

 把如下软件包放置到/usr/local/lnmp/tomcat/lib目录中

   # pwd

       /usr/local/lnmp/tomcat/lib

   # ls

      kryo-1.03.jarkryo-serializers-0.8.jar

      memcached-2.5.jar

      memcached-session-manager-1.5.1.jar

      memcached-session-manager-tc7-1.5.1.jar

      minlog-1.2.jarmsm-kryo-serializer-1.5.1.jarreflectasm-0.9.jar


    编辑文件进行交叉缓存

    # cd ../conf

 # vim context.xml

   ...........

   19 <Context>

   ..........

   34 <ManagerclassName="de.javakaffee.web.msm.MemcachedBackupSessionManager"

   35 memcachedNodes="n1:172.25.46.2:11211,n2:172.25.46.3:11211"     

   36 failoverNodes="n1"        

   37 requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"                            38transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.

    KryoTranscoderFactory"       

   39 />

   40

   41 </Context>


 memcached 安装

   # yum install memcached -y

   # /etc/init.d/memcached start



    以下步骤在主机1上实施

 

 nginx 安装

    # yum install -y pcre-devel openssl-devel

    # tar zxf nginx-1.0.6.tar.gz

    # tar zxf nginx-sticky-module-1.0.tar.gz -C nginx-1.0.6

    # useradd -s /sbin/nologin nginxcd nginx-1.0.6

    # ./configure --user=nginx --group=nginx --with-http_ssl_module --with-http_stub_status_module -addmodule=nginx-sticky-module-1.0/

    # make && make install


 注: nginx-sticky-module 为 nginx 的第三方模块,使 nginx 支持 sticky 模式,所谓 sticky 模式就是指同一个用户的访问请求都被发送到同一个 tomcat 实例上处理。


 # vim /usr/local/lnmp/nginx/conf/nginx.conf

      user nginx nginx;
      worker_processes 4;


      events {
      use epoll;
      worker_connections 1024;
      }

 
      http {
      upstream www.example.com {
     sticky;
     server 172.25.46.2:8080;
     server 172.25.46.3:8080;
     }


     include mime.types;
     default_type application/octet-stream;
     sendfile on;
     tcp_nopush on;
     keepalive_timeout 65;
     gzip on;


 server {
    listen 80;
    server_name www.example.com;

    location / {
    root html;
    index index.html index.htm;
    }


   error_page 500 502 503 504 /50x.html;
   location = /50x.html {
   root html;
   }

 
  location ~ \.jsp$ {                     #所有jsp页面交给 tomcat 处理,动静分离
  proxy_pass http://www.example.com;
  }
  }}

 

  测试页面

 # cd /usr/local/lnmp/tomcat/webapps/ROOT

    # vim test.jsp

   <%@ page contentType="text/html;charset=GBK" %>

   <%@ page import="java.util.*"%>

   <html><head><title>ClusterApp Test</title></head>

   <body>

   Server Info:

   <%

   out.println(request.getLocalAddr() + ": " + request.getLocalPort()+"<br>");%>

   <%

   out.println("<br> ID " +session.getId()+"<br>");

   String dataName =request.getParameter("dataName");

   if (dataName != null &&dataName.length() > 0) {

   String dataValue =request.getParameter("dataValue");

   session.setAttribute(dataName, dataValue);

   }

   out.print("<b>Sessionlist</b>");

   Enumeration e =session.getAttributeNames();

   while (e.hasMoreElements()) {

   String name = (String)e.nextElement();

   String value =session.getAttribute(name).toString();

   out.println( name + " = " +value+"<br>");

   System.out.println( name + " = "+ value);

   }

   %>


 注:这是一个测试页面,它从客户端获取用户,并在node1和node2中的日志中显示用户或telnet,来测试交叉缓存是否成功。


 访问 http://www.example.com/test.jsp,此时node1和node2的tomcat与mmecached均开启。

 不同的主机访问时会调度到不同的 tomcat 实例上处理来自同一主机的请求会交给同一个 tomcat 实例处理,此时你 down 掉当前正在响应的 tomcat 实例,nginx 会自动把用户的请求调度到另一个 tomcat 实例上,同时 session 也没有丢掉。


 node1访问http://www.example.com/test.jsp,提交用户后如图:

 wKiom1dkq3zw_FXhAAApgNKip9k937.png-wh_50

 

 

 node1查看日志,不显示用户信息,说明没有缓存到本机


   # pwd

     /usr/local/lnmp/tomcat/logs/

 # tail -f catalina.out             

      atorg.apache.tomcat.util.digester.Digester.startElement(Digester.java:1276)

      ...32 more

     June 18, 2016 9:34:03 AMorg.apache.catalina.startup.ContextConfig processContextConfig

     June 18, 2016 9:34:03 AMorg.apache.catalina.core.StandardContext startInternal

     SEVERE: Context [/docs] startup failed dueto previous errors


     node2查看日志,显示用户信息,说明缓存到本机

 

    # pwd

      /usr/local/lnmp/tomcat/logs/

 # tail -f catalina.out      

      June 18, 2016 9:37:34 AMorg.apache.catalina.core.StandardService stopInternal

       INFO: Destroying ProtocolHandler["ajp-bio-8009"]

       user1=999


    改变环境,down掉node2的tomcat和memcached,node2访问http://www.example.com/test.jsp,若用户信息缓存到node1,则说明交叉缓存成功。


    node2关闭tomcat和memcached

    # pwd

      /usr/local/lnmp/tomcat/

    # bin/shutdown.sh

    # /etc/init.d/memcached stop


   node2访问http://www.example.com/test.jsp,提交用户信息后如图:

 wKiom1dksgvTCGbjAAApXcTOidg550.png-wh_50

 node2查看日志,无用户信息,说明未缓存到本机

    # pwd

  /usr/local/lnmp/tomcat

    # tail -f logs/catalina.out

   ...........

   June 18, 2016 10:01:32 PMorg.apache.coyote.AbstractProtocol destroy

   June 18, 2016 10:01:32 PMorg.apache.coyote.AbstractProtocol destroy

   

   node1查看日志,有用户信息,说明缓存到本机

   # pwd

     /usr/local/lnmp/tomcat

   # tail -f logs/catalina.out

     June 18, 2016 10:16:34 AMorg.apache.catalina.core.StandardService stopInternal

     INFO: Destroying ProtocolHandler["ajp-bio-8009"]

     user2=123


   可以再次改变实验环境,开启node2的tomcat和memcached,down掉node1的tomcat和memcached,实验结果与上例类似,原理相同。


   问题集锦:

  (1)实验时,context.xml文件中的failoverNodes要写本机。否则当对方的tomcat和memcacheddown掉后,数据会丢失。

   (2)本实验中,要把域名www.example.com同时在三台主机中进行解析,否则无法通过域名访问测试页面,无法进行交叉缓存。

 j_0080.gif