关于Session
使用Apache搭建Sticky模式的Tomcat集群
http://ajita.iteye.com/blog/1848665
Apache配置tomcat负载和session粘连(stickysession)
http://wwwcomy.iteye.com/blog/1909211
以下是Apache 2.2集群方法
Apache和Tomcat 配置负载均衡(mod-proxy方式)
http://blog.csdn.net/wangjunjun2008/article/details/38268483
Apache + Tomcat集群配置详解 (1)
http://zyycaesar.iteye.com/blog/294089
Apache + Tomcat集群配置详解 (2)
http://zyycaesar.iteye.com/blog/295227
Tomcat 集群
http://publib.boulder.ibm.com/wasce/V2.1/zh_CN/configuring-tomcat-native-clusters.html
Apache 2.4 + Tomcat7集群配置
Apache2.4 proxy model文档
http://httpd.apache.org/docs/current/mod/mod_proxy.html
Apache 2.4 + Tomcat7集群配置
http://blog.csdn.net/shaozengwei/article/details/40861447
win7 : Apache-2.4.4 + tomcat-7.0.41 集群的配置
http://blog.csdn.net/u011296170/article/details/9266495
先总结的
坑坑洼洼
1.找不到包, 尤其版本相对应的问题. 见
http://www.cnblogs.com/lengfo/p/4260363.html
2.权限问题, Redis没有使用root权限启动, 会出现无法访问Redis问题.
3.apache的session问题,用Redis的session的时候, 不需要stickysession=jsessionid, 否则可能出现死循环(只出现很卡, 让后电脑几乎动不了).
做了一些修改
1. 准备工作
首先下载Tomcat7 和Apache2.4
然后安装Apache,安装完成后在IE中输入localhost访问,如果出现It Works则表示Apache安装好了,然后解压缩到Tomcat1和Tomcat2两个目录中。
分别启动Tomcat1和Tomcat2看是否可以正常启动。
准备测试工程
同时准备一个应用, 分别存放到两个tomcat的webapps下面, 源码如下
集群服务器里面的应用,
其实两个工程的源码应该是一模一样, 我只是为了测试到底有没有集训, 所以特意在index.jsp的第一行标注是哪个服务器的代码
Tomcat1的test工程源码
在webapps下面添加test目录,添加index.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
第<label style='color:red;'><b>1</b></label>个集群服务器的Tomcat
<hr/>
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>Session 列表</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);
}
%>
<form action="index.jsp" method="POST">
名称:<input type=text size=20 name="dataName">
<br>
值:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>
创建WEB-INF目录,创建web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<distributable />
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Tomcat2的test工程源码
在webapps下面添加test目录,添加index.jsp
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
第<label style='color:red;'><b>2</b></label>个集群服务器的Tomcat
<hr/>
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>Session 列表</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);
}
%>
<form action="index.jsp" method="POST">
名称:<input type=text size=20 name="dataName">
<br>
值:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>
创建WEB-INF目录,创建web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<distributable />
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
2. 配置Apache2.4
①打开conf/httpd.conf文件,加载以下模块。 在LoadModule的地方, 增加一下代码
#---------------------start------------------------
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so
LoadModule rewrite_module modules/mod_rewrite.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 slotmem_shm_module modules/mod_slotmem_shm.so
LoadModule speling_module modules/mod_speling.so
#LoadModule ssl_module modules/mod_ssl.so
#----------------------end---------------------
② 如果你想看到小猫页面,
<IfModule dir_module>
DirectoryIndex index.html index.jsp
</IfModule>
在上面的index.html下面添加index.jsp就可以了
③去掉Include conf/extra/httpd-vhosts.conf的注释标记#。
改成:
增加Include conf/httpd-vhosts.conf, 因为配置文件不存在, 所以增加, 并增加到httpd.conf同一个级别的文件夹.
④在文件末尾加反向代理
纵向集群
ProxyRequests Off
<proxy balancer://cluster>
BalancerMember ajp://127.0.0.1:8009 loadfactor=1 route=jvm1
BalancerMember ajp://127.0.0.1:9009 loadfactor=1 route=jvm2
</proxy>
横向集群
ProxyRequests Off
<proxy balancer://cluster>
BalancerMember ajp://192.168.0.11:8009 loadfactor=1 route=jvm11
BalancerMember ajp://192.168.0.12:8009 loadfactor=1 route=jvm22
</proxy>
⑤修改conf/extra/httpd-vhosts.conf文件。
没有这个文件呀, 难道直接一个空文件,然后追加?
注释掉所有的dummy-host,添加以下内容
<VirtualHost *:80>
ServerAdmin [email protected]
ServerName localhost
ServerAlias localhost
ProxyPass / balancer://cluster/ stickysession=jsessionid nofailover=On #使用Redis的session的时候, 不需要stickysession=jsessionid, 否则可能出现死循环
ProxyPassReverse / balancer://cluster/
ErrorLog "logs/lbtest-error.log"
CustomLog "logs/lbtest-access.log" common
</VirtualHost>
说明
ProxyRequests Off 表示启用反向代理,必须开启;
ProxyPass为代理转发的Url,即将所有访问/的请求转发到群集balancer://cluster
BalancerMember为群集的成员,即群集服务器1或2,负载均衡服务器会根据均衡规则来将请求转发给BalancerMember
loadfactor=1 即为均衡规则的权重
stickysession=jsessionid -- 用于处理session发送问题
2.配置Tomcat
两个方向集群共同修改
server.xml, 第1个改为jvm1, 第二个改为jvm2
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm${n}">
取消注释
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
或者改为
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
</Cluster>
纵向集群
tomcat1保持配置不变, 第二个tomcat2的server.xml里面涉及到的端口, 第一个数字改为9, 比如:9080,9443......
横向集群
端口一律不变
配置完成之后,启动两个Tomcat测试一下Tomcat是否可以正常启动
如果可以正常启动,则进行下面步骤
最后启动Apache2.4,在页面中输入
到此, 直接启动的时候, 好像已经集群好了.
测试
http://192.168.2.100/test/(apache服务器地址),
不断刷新, 不断看到调用不同的服务器. , 会看到seession输出类似7F401A91D1BB932EB482B9819A13233D.jvm1, 注意, 点的后面是服务器标识.
纵向集群:session一直改变!!,要使用session共享来解决问题.
横向集群:session保持不变,VM和docker都测试成功.
注意:如果纵向只要Redis的session共享方式, 横向不使用的话, 那么纵向和横向个子的session不变, 但是从两个方向切换的时候, 就会改变. 所以, 一旦使用session共享, 那么横向和纵向都需要配置.
session共享
这是因为没有做Session处理, 它包含两种方式:
I: Session Sticky,把同一个用户的Session一直发送到同一个逻辑单元处理,指定负载的分发组件(如Apache),把请求中包含特定属性的请求发到同一个连接,如指定jsessionid一致的请求到同一个请求,或者在负载组件中给每个响应增加一个头部属性,指定下次的分发目的地. 配置见:
http://ajita.iteye.com/blog/1848665,
测试成功
II: 通过数据库来实现tomcat集群, 例子1:
http://mushme.iteye.com/blog/1147960, 例子2:
http://tangmingjie2009.iteye.com/blog/1772169, 不测试
II: mod_jk方式 apache + tomcat + mod_jk 集群部署及Session共享和遇到的问题
http://bbs.vpigirl.com/forum.php?mod=viewthread&tid=562, 不测试
IV: Redis的Session共享, 所有的后端处理逻辑单元共享Session或者Session更新时通知其它逻辑单元(1. 各自维护Session,当请求处理结束后,通知其它组件单元更新Session,包括异步和同步模式; 2. 统一维护Session,如把Session放在memcached或者共享文件系统中,可以在容器级别或者应用级别做这个事情; 3.利用cache server),
使用 Redis 来存储 Apache Tomcat 7 的 Session
http://www.open-open.com/lib/view/1378430065687
tomcat7和redis的sessoin共享问题处理,tomcat7sessoin
http://www.bkjia.com/ASPjc/930346.html
获得集群的包:
http://www.cnblogs.com/lengfo/p/4260363.html,配置见后面,附件是我自己打包得到的.
安装Redis, 网上找教程,
注意: 安装Redis后, 要使用root权限启动.
su root
redis-server /etc/redis/redis.conf
两个tomcat都需要配置context.xml
<Context>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="localhost" <!-- 这里是redis服务器IP -->
port="6379"
database="0"
maxInactiveInterval="60" />
</Context>
-------------------
配置纵向的时候没问题, 但是配置横向(两个虚拟机, 非docker方式)的时候碰到问题:
1.
Could not get a resource from the pool
原来是服务器没有开放Redis的6379端口, 晕死了............
获得包的代码
=====================================================================
build.gradle文件, 注意版本, 得到包后, 其实
只需要几个包:commons-pool2-2.2.jar,jedis-2.5.2.jar,tomcat-juli-7.0.61.jar,tomcat-redis-session-manager-master-2.0.0.jar.
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'signing'
group = 'com.orangefunction'
version = '2.0.0'
repositories {
mavenCentral()
}
compileJava {
sourceCompatibility = 1.7
targetCompatibility = 1.7
}
dependencies {
compile group: 'org.apache.tomcat', name: 'tomcat-catalina', version: '7.0.61'
compile group: 'redis.clients', name: 'jedis', version: '2.5.2'
compile group: 'org.apache.commons', name: 'commons-pool2', version: '2.2'
//compile group: 'commons-codec', name: 'commons-codec', version: '1.9'
testCompile group: 'junit', name: 'junit', version: '4.+'
testCompile 'org.hamcrest:hamcrest-core:1.3'
testCompile 'org.hamcrest:hamcrest-library:1.3'
testCompile 'org.mockito:mockito-all:1.9.5'
testCompile group: 'org.apache.tomcat', name: 'tomcat-coyote', version: '7.0.61'
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from 'build/docs/javadoc'
}
task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}
artifacts {
archives jar
archives javadocJar
archives sourcesJar
}
//signing {
// sign configurations.archives
//}
task copyJars(type: Copy) {
from configurations.runtime
into 'dist'
}
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
//repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
// authentication(userName: sonatypeUsername, password: sonatypePassword)
//}
//repository(url: "https://oss.sonatype.org/content/repositories/snapshots") {
// authentication(userName: sonatypeUsername, password: sonatypePassword)
//}
pom.project {
name 'tomcat-redis-session-manager'
packaging 'jar'
description 'Tomcat Redis Session Manager is a Tomcat extension to store sessions in Redis'
url 'https://github.com/jcoleman/tomcat-redis-session-manager'
issueManagement {
url 'https://github.com:jcoleman/tomcat-redis-session-manager/issues'
system 'GitHub Issues'
}
scm {
url 'https://github.com:jcoleman/tomcat-redis-session-manager'
connection 'scm:git:git://github.com/jcoleman/tomcat-redis-session-manager.git'
developerConnection 'scm:git:[email protected]:jcoleman/tomcat-redis-session-manager.git'
}
licenses {
license {
name 'MIT'
url 'http://opensource.org/licenses/MIT'
distribution 'repo'
}
}
developers {
developer {
id 'jcoleman'
name 'James Coleman'
email '[email protected]'
url 'https://github.com/jcoleman'
}
}
}
}
}
}
构建命令:
gradle build -x test copyJars
得到所有包, 放到tomcat/lib下面, 注意版本.