首先,我们明确目标,做tomcat集群的目的是为了提供更高的负载能力,把访问均摊到不同的服务器上。
直观地来说,就是访问test.localhost.com时,nignx会随机将访问请求分发到tomcat1,tomcat2,为了保持session同步,使用memcached去管理session。
为此我们准备的配置清单是: windows x 1 nginx x 1 memcached x 1 tomcat x 2 mysql x 1
部署的架构图如下:
首先,我准备了一个java web项目、tomcat 6、jdk6。
step1 配置tomcat
先将项目部署到tomcat,因为要用到两个tomcat,当然地要把其中一个tomcat的端口修改一下。
step2 配置nginx
下载安装nginx,。
在host里准备一个测试域名。打开c:\windows\system32\drivers\etc\host, 添加域名映射
127.0.0.1 test.local.com
打开nginx的根目录,在conf里添加test.conf,内容大概如下。
upstream test.local.com { server 127.0.0.1:8080 weight=1; server 127.0.0.1:8083 weight=1; } server { listen 80; server_name test.local.com; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } root /data/projects/ycp/bill; # - rewrite: if( path ~ "^/assets/(.*)" ) goto "/public/assets/$1" # location ~ ^/static/assets/(.*)$ # { #alias /data/projects/payment/web/public/assets/$1; # access_log off; # #expires 3d; # } location / { index index.html index.htm index.jsp; } location ~ .* { # proxy_pass_header server; proxy_set_header host $http_host; # proxy_redirect off; proxy_set_header x-real-ip $remote_addr; proxy_set_header x-scheme $scheme; proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for; add_header pragma "no-cache"; proxy_pass http://test.local.com; } rewrite ^/admin/?$ /admin/login redirect; # for rewrite rewrite ^/(channel|admin|mobile|api|web)/(.*)$ /public/index.php/$2 last; #redirect to mobile wap #rewrite ^$ /m redirect; #rewrite ^/$ /mobile/user redirect; }
然后将test.conf引入到nginx.conf里面
include ycp-test.conf;
此时,我们可以启动nginx和tomcat,访问,试试效果。
step3 配置和调试memcached
上一步,我们配好了nginx集群,但是tomcat的session还没有集到一起。接下来我们会用memcached管理session。
下载安装memcached。
ps:
解压放某个盘下面,比如在c:\memcached
在cmd下输入 "c:\memcached\memcached.exe -d install" 安装。
再输入:"c:\memcached\memcached.exe -d start" 启动。note: 以后memcached将作为windows的一个服务每次开机时自动启动。
如图:
启动时可添加其他参数
-p 监听的端口
-l 连接的ip地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位mb。默认64mb
-m 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key value flags默认是48
-h 显示帮助
另外,我们可以用telnet操作memcached
windows如果本来没有telnet命令的话,可以在控制面板-程序和功能-启动或关闭windows功能里面勾选telnet客户端
telnet 127.0.0.1 11211 stats
可得到描述memcached服务器运行情况的参数。如下图:
ps:网上给出的一些参数解释
- pid: memcached服务进程的进程id
- uptime: memcached服务从启动到当前所经过的时间,单位是秒。
- time: memcached服务器所在主机当前系统的时间,单位是秒。
- version: memcached组件的版本。这里是我当前使用的1.2.6。
- pointer_size:服务器所在主机操作系统的指针大小,一般为32或64.
- curr_items:表示当前缓存中存放的所有缓存对象的数量。不包括目前已经从缓存中删除的对象。
- total_items:表示从memcached服务启动到当前时间,系统存储过的所有对象的数量,包括目前已经从缓存中删除的对象。
- bytes:表示系统存储缓存对象所使用的存储空间,单位为字节。
- curr_connections:表示当前系统打开的连接数。
- total_connections:表示从memcached服务启动到当前时间,系统打开过的连接的总数。
- connection_structures:表示从memcached服务启动到当前时间,被服务器分配的连接结构的数量,这个解释是协议文档给的,具体什么意思,我目前还没搞明白。
- cmd_get:累积获取数据的数量,这里是3,因为我测试过3次,第一次因为没有序列化对象,所以获取数据失败,是null,后边有2次是我用不同对象测试了2次。
- cmd_set:累积保存数据的树立数量,这里是2.虽然我存储了3次,但是第一次因为没有序列化,所以没有保存到缓存,也就没有记录。
- get_hits:表示获取数据成功的次数。
- get_misses:表示获取数据失败的次数。
- evictions:为了给新的数据项目释放空间,从缓存移除的缓存对象的数目。比如超过缓存大小时根据lru算法移除的对象,以及过期的对象。
- bytes_read:memcached服务器从网络读取的总的字节数。
- bytes_written:memcached服务器发送到网络的总的字节数。
- limit_maxbytes:memcached服务缓存允许使用的最大字节数。这里为67108864字节,也就是是64m.与我们启动memcached服务设置的大小一致。
- threads:被请求的工作线程的总数量。
我们还可以用java操作memcached
首先下载相关的jar包
然后编写客户端ocsutil.java
package net.bill.commons.util; import org.springframework.stereotype.component; import com.danga.memcached.memcachedclient; import com.danga.memcached.sockiopool; @component public classocsutil{ private static ocsutil session; publicstatic ocsutil getsession(){ if (session == null) { synchronized(ocsutil.class){ if(session==null){ session=new ocsutil(); } } } return session; } /** * memcached客户端 */ private memcachedclient memcache = null; publicocsutil(){ if (memcache == null) { memcache =new memcachedclient(); string [] addr ={"127.0.0.1:11211"}; integer [] weights = {3}; sockiopool pool = sockiopool.getinstance(); pool.setservers(addr); pool.setweights(weights); pool.setinitconn(5); pool.setminconn(5); pool.setmaxconn(200); pool.setmaxidle(1000*30*30); pool.setmaintsleep(30); pool.setnagle(false); pool.setsocketto(30); pool.setsocketconnectto(0); pool.initialize(); } } publicvoidsetattribute(string key, object value){ memcache.set(key, value, 1000); } public object getattribute(string key){ return memcache.get(key); } publicvoidremoveattribute(string key){ memcache.delete(key); } }
再编写测试代码basetest.java和ocstest.java
package net.test.modules; import org.junit.before; import org.junit.runner.runwith; import org.springframework.beans.beansexception; import org.springframework.context.applicationcontext; import org.springframework.context.applicationcontextaware; import org.springframework.test.context.contextconfiguration; import org.springframework.test.context.junit4.springjunit4classrunner; @runwith(springjunit4classrunner.class) @contextconfiguration(locations="/applicationcontext.xml") public classbasetestimplementsapplicationcontextaware{ public applicationcontext ctxt; publicvoidsetapplicationcontext(applicationcontext arg0)throws beansexception { this.ctxt = arg0; } @before publicvoidsetup()throws exception { } }
package net.test.modules; import net.bill.commons.util.ocsutil; import net.bill.modules.pojo.user; import org.junit.test; import org.springframework.beans.factory.annotation.autowired; public class ocstest extends basetest { @autowired ocsutil session; /** * 通过spring注入获得客户端 */ @test public void test1() { session.setattribute("user", new user("13355558888")); system.out.println(session.getattribute("user")); } /** * 通过静态方法获得客户端(单例) */ @test public void test2() { ocsutil session = ocsutil.getsession(); system.out.println(session.getattribute("user")); } }
要注意的是,user类必须实现serializable接口,进行序列化。因为memcached的value类型是string。
接下来我要用memcached替换tomcat的session
在这之前,可以先看一下(google的),或中文翻译的。
session的序列化方案官方推荐的有4种:
- kryo-serializer
- javolution-serializer
- xstream-serializer
- flexjson-serializer
我使用的是最简单的一种,就是 java serialization。这个只要java中存入session的对象实现serializable就可以了。 然后下载以下jar包,并放在tomcat\lib\里
- memcached-session-manager-1.8.3.jar
- memcached-session-manager-tc6-1.8.3.jar
- spymemcached-2.11.1.jar
在tomcat\conf\context.xml,里加上以下配置:
<managerclassname="de.javakaffee.web.msm.memcachedbackupsessionmanager"memcachednodes="n1:127.0.0.1:11211"username="root"password=""sticky="false"sessionbackupasync="false"lockingmode="uripattern:/path1|/path2"requesturiignorepattern=".*\.(ico|png|gif|jpg|css|js)$" />
启动tomcat,可以看见日志输出以下信息:
信息: -------- - memcachedsessionservice finished initialization: -sticky:false - operation timeout:1000 - node ids: [n1] - failover node ids: [] - storage key prefix: null --------
step4 整体测试
现在可以测一下是否成功。
- 启动tomcat1
- 访问test.local.com,并登录
- 启动tomcat2,关闭tomcat1
- 查看登录信息是否还在
测试通过的话,就基本上没问题了。