Apache+tomcat+memcache负载均衡的入门配置

Apache+tomcat+memcache负载均衡的入门配置
目录
一、准备工作 1
二、配置Apache 1
1、打开相关的模块。 1
2、配置tomcat集群。 2
三、配置tomcat 2
1、配置server的关闭。 2
2、配置Connector 2
3、配置Engine 3
4、配置Session的复制 3


这份文档只是一个初步的配置负载均衡的文档,没有涉及过多的性能优化的东西。
所以也就不多言了,直接切入主题。
一、准备工作
安装JDK并配置环境变量。这里要求至少1.5以上版本。
安装apache2.2。我的安装目录为:D:\Apache2.2
安装tomcat6。为了端口不起冲突,建议直接解压。我这里只使用了两台tomcat作为集群服务器。其路径分别为D:\apache-tomcat-6.0.20_v1、D:\apache-tomcat-6.0.20_v2

二、配置Apache
这里说明一下,我在网上找到的一些资料都在介绍mod_JK的方式配置负载均衡。但是从apache2.X版本之后其自身已经集成了mod_jk可以直接使用mod_proxy的方式进行负载均衡的配置,所以下面介绍的也即是这种方式。
在D:\Apache2.2\conf目录下找到httpd.conf文件,并进行修改。修改步骤:
1、打开相关的模块。
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
在配置文件里找到上述模块,将前边的“#”去掉.
2、配置tomcat集群。
在该配置文件的最后加上:
ProxyRequests Off
ProxyPass / balancer://cluster/
<proxy balancer://cluster>
BalancerMember ajp://localhost:8009 loadfactor=1 route=jvm1
BalancerMember ajp://localhost:9009 loadfactor=1 route=jvm2
</proxy>
注意红色部分,因为这里我只使用了一台物理机器作为集群的配置,所以就直接使用了localhost指向本地的集群服务器,你也可以使用127.0.0.1。如果这里你使用多台机器一起配合的话,只需要将localhost修改为其他机器的IP地址就行。
另外需要注意的就是上面配置的端口,为什么要这么配置?将在后边结合tomcat一起做一个详细的说明。

三、配置tomcat
在D:\apache-tomcat-*\conf找到server.xml,然后着手修改。
1、配置server的关闭。
因为我是在同一台机器上配置两台tomcat,所以为了使tomcat关闭不出现端口被占用的情况,需要修改关闭端口。
<Server port="8005" shutdown="SHUTDOWN">
修改为:
<Server port="XXXX" shutdown="SHUTDOWN">
注意,我这里用了两台tomcat,所以第一个tomcat我就选择了默认的端口8005,第二个tomcat我将此端口修改为了9005。总之,如果你有多台tomcat服务器群,都需要将它们的端口修改为互不冲突的端口号。
2、配置Connector
这里又两个地方需要修改,第一个就是tomcat监听的http端口,另一个就是tomcat监听的AJP端口:
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
注意,蓝色部分是tomcat的http端口,因为我在同一台机器上配置了两个tomcat,为了使它们的http端口不冲突,我将第一个tomcat使用默认的端口即8080,第二个tomcat的http端口我修改为了8081。同样的道理,如果你还有其他的tomcat,记得将它们的http端口修改为互不冲突的端口号即可。
另一个需要修改的端口,红色部分的端口,这里是apache和tomcat链接的关键,前台apache就是通过AJP协议与tomcat进行通信的,以完成负载均衡的作用。现在回过头去看看apache的httpd.conf配置,
<proxy balancer://cluster>
BalancerMember ajp://localhost:8009 loadfactor=1 route=jvm1
BalancerMember ajp://localhost:9009 loadfactor=1 route=jvm2
</proxy>
那么,另一个tomcat的AJP端口你知道要配置成什么了吗?对了,就是9009。
3、配置Engine
<Engine name="Catalina" defaultHost="localhost">,这个是原来的配置,现在将这个配置修改为:<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">,然后另一个tomcat修改为<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm2">。

现在再回过头去看看apache的配置:
<proxy balancer://cluster>
BalancerMember ajp://localhost:8009 loadfactor=1 route=jvm1
BalancerMember ajp://localhost:9009 loadfactor=1 route=jvm2
</proxy>
这里再说明一点,loadfactor相当于一种加权策略,loadfactor的值越大,对应的tomcat服务器分到的请求就越多。像上面的这种设置就说明两台tomcat将平均负载。

4、配置Session的复制
Tomcat里的 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>这个配置默认是被注释掉的,如果想要开启取消注释就OK,这也是tomcat默认的会话同步和复制配置。一般的情况下,使用默认配置就可以。
关于session的复制我还没来得及验证过,有需要的同学可以自己去网上找一下相关资料。

新建一个项目测试就OK了 惊醒测试


测试结果jvm1

Jvm2

5、安装memcache客户端

1  Memcached 介绍
  Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。
Memcached需要有缓存服务端,采用java编程的话还需要memcached.jar,这就是java中实现memcached服务的插件。
2 使用Memcached目的
  研究这个东东主要是为了解决在项目中,由于信息过多,当用户查询数据时(目前当天查询的都是前一天的数据),由于数据量过大,并且大并发情况下数据库频繁读写造成速度慢的问题。所以就想通过使用Memcached解决这一问题。
3  memcached原理及工作机制
Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。
它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。
4 准备过程
  在开发前,要准备有:
  memcached-1.2.6-win32-bin.zip     windows下服务器
  memcached-1.2.6-win32-src.zip     windows 下服务器源码(是C语言哦,亲)
  memcached-1.2.6.tar.gz            linux 下服务器
  java_memcached-release_2.5.1.jar   java 客户端 JAR包
5 服务器安装过程
  首先解压memcached-1.2.6-win32-bin.zip到某一盘下,然后使用命令、或者直接双击,运行。相当于就已经安装好memcached服务器了。并且启动了服务。它的默认端口是:11211(不建议修改)
  打开控制面板-管理工具-服务:

此时可以访问一下服务器:打开-运行-cmd-telnet 127.0.0.1 11211
输入命令stats

这里显示了很多状态信息,下边详细解释每个状态项:
1.  pid: memcached服务进程的进程ID
2.  uptime: memcached服务从启动到当前所经过的时间,单位是秒。
3.  time: memcached服务器所在主机当前系统的时间,单位是秒。
4.  version: memcached组件的版本。这里是我当前使用的1.2.6。
5.  pointer_size:服务器所在主机操作系统的指针大小,一般为32或64.
6.  curr_items:表示当前缓存中存放的所有缓存对象的数量。不包括目前已经从缓存中删除的对象。
7.  total_items:表示从memcached服务启动到当前时间,系统存储过的所有对象的数量,包括目前已经从缓存中删除的对象。
8.  bytes:表示系统存储缓存对象所使用的存储空间,单位为字节。
9.  curr_connections:表示当前系统打开的连接数。
10. total_connections:表示从memcached服务启动到当前时间,系统打开过的连接的总数。
11. connection_structures:表示从memcached服务启动到当前时间,被服务器分配的连接结构的数量,这个解释是协议文档给的,具体什么意思,我目前还没搞明白。
12. cmd_get:累积获取数据的数量,这里是3,因为我测试过3次,第一次因为没有序列化对象,所以获取数据失败,是null,后边有2次是我用不同对象测试了2次。
13. cmd_set:累积保存数据的树立数量,这里是2.虽然我存储了3次,但是第一次因为没有序列化,所以没有保存到缓存,也就没有记录。
14. get_hits:表示获取数据成功的次数。
15. get_misses:表示获取数据失败的次数。
16. evictions:为了给新的数据项目释放空间,从缓存移除的缓存对象的数目。比如超过缓存大小时根据LRU算法移除的对象,以及过期的对象。
17. bytes_read:memcached服务器从网络读取的总的字节数。
18. bytes_written:memcached服务器发送到网络的总的字节数。
19. limit_maxbytes:memcached服务缓存允许使用的最大字节数。这里为67108864字节,也就是是64M.与我们启动memcached服务设置的大小一致。
20. threads:被请求的工作线程的总数量。这个解释是协议文档给的,具体什么意思,我目前还没搞明白。
6 客户端开发过程(分为2种)
第1种:不使用spring(直接在static 里面初始化连接。)
1 加载java_memcached-release_2.5.1.jar包
2 编写MemcachedUtil 分布式缓存工具类
3 创建需要缓存的对象(必须要序列化对象)
  对于普通的POJO而言,如果要进行存储的话,那么比如让其实现java.io.Serializable接口,因为memcached是一个分布式的缓存服务器,多台服务器间进行数据共享需要将对象序列化的,所以必须实现该接口,否则会报错的。缓存中获取的对象是存入对象的一个副本,对获取对象的修改并不能真正的修改缓存中的数据,而应该使用其提供的replace等方法来进行修改。
4 使用缓存(如果在缓存有效期内,则数据就从缓存中查询,如果不在缓存有效期内,意思就是过期了,则就从数据库中查询)
5 缓存过期时间的设置
过期时间有两种格式:
1. 相对时间:多长时间,给出过期的时间长度
2. 绝对时间:到期时间,给出过期的最后期限
相对时间时,返回的值是:服务器当前时间之后的exptime - process_started秒
绝对时间时,返回的值是:服务器当前时间之后的(exptime -服务器当前时间) -process_started秒。
可以看到,如果Client和Server时间不一致,使用绝对时间很容易导致缓存过期。
所以使用相对时间是比较安全的做法。
服务端的处理
时间处理源代码【memcached.c】如下:
#define REALTIME_MAXDELTA60*60*24*30                     //定义30天的秒数
static rel_time_t realtime(const time_texptime) {
       if(exptime == 0) return 0;
       if(exptime > REALTIME_MAXDELTA){                       //超过30天,是绝对时间
              if(exptime <=process_started)                         //小于进程启动日期
                      return(rel_time_t)1;                                  //
              return(rel_time_t)(exptime - process_started);   // 返回进程启动之后的时间差
       }else{                                                                   //不超过30天,是相对时间
              return(rel_time_t)(exptime +current_time);       // exptime + (tvsec -process_started)
       }
}
OK,结束!
第2种方法:(使用spring配置,方便之后扩展)
1 同样加载JAR包java_memcached-release_2.5.1.jar
2 封装memcached缓存。建立接口IMemcachedClient
实现类MemcachedClientImpl.java
3 在spring的核心配置文件applicationContext.xml中配置
4 创建需要缓存的对象。
5 使用memcached的缓存
OK,结束!



6 apache+多个tomcat+memcached共享session会话(windows)

c)再修改Tomcat的context.xml
[html] view plaincopyprint?
1. <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"  
2.  
3. memcachedNodes="n1:localhost:11211"  
4.  
5. requestUriIgnorePattern=".*/.(png|gif|jpg|css|js)$"  
6.  
7. sessionBackupAsync="false"  
8.  
9. sessionBackupTimeout="100" 
10.  
11. transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"  
12.  
13. copyCollectionsForSerialization="false"/> 

需要用到的jar包:
memcached-2.6.jar这个jar包测试的时候有问题,需要改成spymemcached-2.8.4.jar包才能正常使用,或者会报下面一下错误 (https://code.google.com/p/spymemcached/downloads/detail?name=spymemcached-2.8.4.jar)
javolution-5.4.3.1.jar
memcached-session-manager-1.5.1.jar
memcached-session-manager-tc7-1.5.1.jar
msm-javolution-serializer-1.5.1.jar
msm-kryo-serializer-1.5.1.jar
msm-xstream-serializer-1.5.1.jar
以上jar包在http://code.google.com/p/memcached-session-manager/downloads/list中都可以找到。

d)安装memcached服务器,参见
http://blog.csdn.net/shuzui1985/article/details/7907889
3、编写测试代码
index.jsp
[html] view plaincopyprint?
1. <%@ page contentType="text/html; charset=GBK" %> 
2. <%@ page import="java.util.*" %> 
3. <html><head><title>Cluster Test</title></head>   
4. <body> 
5. <% 
6.   //HttpSession session = request.getSession(true); 
7.   System.out.println(session.getId()); 
8.   out.println("<br> SESSION ID:" + session.getId()+"<br>");   
9.    
10.   if(session.getAttribute("jhy") != null){ 
11.     out.println("<br> SESSION attribute:" + session.getAttribute("jhy")+"<br>"); 
12.     String str = "+"; 
13.     session.setAttribute("jhy",session.getAttribute("jhy")+str); 
14.   }else{ 
15.     session.setAttribute("jhy","test"); 
16.     out.println("<br> SESSION attribute set!" +"<br>"); 
17.   } 
18. %> 
19. </body> 
20. </html> 

4、测试。Balance是他的项目名称。改成你自己的   访问localhost:你知道的项目名称/index.jsp

第一次访问,返回显示session中属性为空,进行属性设置,同时n1表示session在memcached服务器上的节点,b为tomcat服务器节点。
紧接着关闭b服务器,就是默认的第二个自定义服务器myTomcat6.

继续访问如下图,sessionID前段没有发生变化,只是变成了来自tomat服务器a,但是从session属性中读出了初始设置test

再访问http://localhost/balance,如下图,已经开始累计了。


再开启b服务器,再访问http://localhost/balance,


好了,以上的测试结果表明,session已经实现了集群共享,当其中一个服务器宕机了以后,可以实现故障转移。



猜你喜欢

转载自denghuan.iteye.com/blog/1968574