一.实验原理
<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://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,提交用户后如图:
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,提交用户信息后如图:
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同时在三台主机中进行解析,否则无法通过域名访问测试页面,无法进行交叉缓存。
转载于:https://blog.51cto.com/chengyanli/1790529