我正在本地计算机上的Tomcat 7上设置群集/复制,以评估它是否与我的环境/代码库一起使用。
我在不同端口上运行的兄弟目录中有两个相同的tomcat服务器。我有httpd监听另外两个端口并连接到两个tomcat实例作为VirtualHosts。我可以在配置的端口上访问和交互两个环境;一切都按预期工作。
tomcat服务器在server.xml中启用了这样的群集:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4001"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
我将distributable标记添加到web.xml的最开头:
<web-app 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"
version="3.0">
<distributable />
(lots more...)
</web-app>
当服务器启动时,他们会记录
Sep 16, 2013 1:44:23 PM org.apache.catalina.ha.tcp.SimpleTcpCluster startInternal
INFO: Cluster is about to start
Sep 16, 2013 1:44:23 PM org.apache.catalina.tribes.transport.ReceiverBase getBind
FINE: Starting replication listener on address:10.0.0.100
Sep 16, 2013 1:44:23 PM org.apache.catalina.tribes.transport.ReceiverBase bind
INFO: Receiver Server Socket bound to:/10.0.0.100:4001
Sep 16, 2013 1:44:23 PM org.apache.catalina.tribes.membership.McastServiceImpl setupSocket
INFO: Setting cluster mcast soTimeout to 500
Sep 16, 2013 1:44:23 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:4
Sep 16, 2013 1:44:24 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Done sleeping, membership established, start level:4
Sep 16, 2013 1:44:24 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Sleeping for 1000 milliseconds to establish cluster membership, start level:8
Sep 16, 2013 1:44:25 PM org.apache.catalina.tribes.membership.McastServiceImpl waitForMembers
INFO: Done sleeping, membership established, start level:8
当第二台服务器启动时,第一台服务器会记录
Sep 16, 2013 2:17:30 PM org.apache.catalina.tribes.group.interceptors.TcpFailureDetector messageReceived
FINE: Received a failure detector packet:ClusterData[src=org.apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4000,{10, 0, 0, 100},4000, alive=112208, securePort=-1, UDP Port=-1, id={118 6 107 -67 88 98 72 95 -73 41 4 -108 58 -5 -127 -41 }, payload={}, command={}, domain={}, ]; id={25 110 120 -2 -25 6 78 -97 -84 -34 2 -11 49 -62 -8 -56 }; sent=2013-09-16 14:17:30.139]
Sep 16, 2013 2:17:30 PM org.apache.catalina.tribes.transport.nio.NioReplicationTask remoteEof
FINE: Channel closed on the remote end, disconnecting
Sep 16, 2013 2:17:30 PM org.apache.catalina.tribes.membership.McastServiceImpl memberDataReceived
FINE: Mcast add member org.apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=1010, securePort=-1, UDP Port=-1, id={82 -45 -109 -56 -110 -5 78 -10 -103 61 -40 -59 -36 -79 104 120 }, payload={}, command={}, domain={}, ]
Sep 16, 2013 2:17:30 PM org.apache.catalina.ha.tcp.SimpleTcpCluster memberAdded
INFO: Replication member added:org.apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=1011, securePort=-1, UDP Port=-1, id={82 -45 -109 -56 -110 -5 78 -10 -103 61 -40 -59 -36 -79 104 120 }, payload={}, command={}, domain={}, ]
当一个关闭时,另一个记录
Sep 16, 2013 2:28:05 PM org.apache.catalina.tribes.membership.McastServiceImpl memberDataReceived
FINE: Member has shutdown:org.apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=422279, securePort=-1, UDP Port=-1, id={54 43 17 -9 13 -11 72 -63 -107 -78 -8 65 -21 -77 115 88 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]
Sep 16, 2013 2:28:05 PM org.apache.catalina.tribes.group.interceptors.TcpFailureDetector memberDisappeared
INFO: Verification complete. Member disappeared[org.apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=422279, securePort=-1, UDP Port=-1, id={54 43 17 -9 13 -11 72 -63 -107 -78 -8 65 -21 -77 115 88 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]]
Sep 16, 2013 2:28:05 PM org.apache.catalina.ha.tcp.SimpleTcpCluster memberDisappeared
INFO: Received member disappeared:org.apache.catalina.tribes.membership.MemberImpl[tcp://{10, 0, 0, 100}:4001,{10, 0, 0, 100},4001, alive=422279, securePort=-1, UDP Port=-1, id={54 43 17 -9 13 -11 72 -63 -107 -78 -8 65 -21 -77 115 88 }, payload={}, command={66 65 66 89 45 65 76 69 88 ...(9)}, domain={}, ]
所以我知道他们彼此了解。
最后,当我在jconsole中使用Cluster / Operations MBean尝试将属性“foo”设置为“bar”时,jconsole报告“方法成功调用”,并且服务器记录
Sep 16, 2013 2:30:18 PM org.apache.catalina.ha.tcp.SimpleTcpCluster setProperty
WARNING: Dynamic setProperty(foo,value) has been disabled, please use explicit properties for the element you are trying to identify
我并不太担心这个错误;主要用于演示setProperty创建日志语句。
据我所知,我的应用中没有复制会话信息。
tomcat管理器仅列出在其监控的服务器上启动的会话,而不是群集中的其他会话。
我的印象是每当应用程序调用HttpSession.setAttribute时,该属性应该被复制到其他群集节点,我希望会记录一些这样的记录。我的应用程序包括以下行:
public static void saveBillingInfo(IPageContext pageContext, BillingInfo billingInfo)
{
pageContext.getSession().setAttribute("billingInfo", billingInfo);
//etc...
}
其中BillingInfo是一个Serializable类,只包含一个字段,一个关于结算信息的HashMap信息。
当此行或任何其他行处理时,不会写入任何日志语句,并且我没有看到任何证据表明会话信息实际上正在被共享。
欢迎任何建议或进一步的问题。
答案 0 :(得分:29)
我们有同样的问题。虽然没有在任何地方记录,但为我解决的是简单地移动&lt; Manager&gt;从server.xml标记到全局context.xml(将其从&lt; Server&gt; ...&lt; Cluster&gt; ...组中引出并进入&lt; Context&gt;组)。一旦我们这样做,一切都“神奇地”开始起作用。这仅适用于Tomcat 7 ... Tomcat 6与您在上面描述的设置(以及文档描述)完美配合。
<Context>
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true" />
</Context>
现在只需删除&lt; Manager&gt;来自server.xml中的群集组的标记,您已完成。
答案 1 :(得分:1)
只需添加:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="6"/>
,并在您的context.xml中:
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true" />
它适用于我,我使用的是Tomcat 7和Tomcat 8
答案 2 :(得分:0)
我们的解决方案是将<distributable/>
标记添加到WEB-INF/web.xml
元素下的<web-app>
文件中。不知道为什么这对我们有用而不是OP。
顺便说一句,Jason的解决方案也适用于我们。
答案 3 :(得分:0)
根据Tomcat文档,你需要做这两个中的一个(不是两个):
在web.xml <distributable/>
中指定启用群集并使用server.xml中指定的默认<Manager>
或...
在context.xml
<Manager>
醇>
答案 4 :(得分:0)
如果要为特定部署的应用程序启用群集,可以使用以下示例
server.xml中
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Resource auth="Container" driverClassName="oracle.jdbc.OracleDriver" factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory" minPoolSize="4" maxPoolSize="50" name="jdbc/myoracle/myconect" password="sdfhsfghsgfsfg" type="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean" uniqueResourceName="uniresource" url="jdbc:oracle:thin:@10.10.10.10.:1521:abc" user="user"/>
</Context>
答案 5 :(得分:-1)
以上建议均无效。对于那些正在关注Ramki教程的人,您遇到的问题是在第一个tomcat实例中有完整列表,而在其他实例中有空列表。与视频教程不同,您唯一要做的就是将index.jsp中的scriptlet更改为:
String bookName = request.getParameter("bookName");
List<String> listOfBooks = (ArrayList<String>) request.getSession().getAttribute("Books");
if(listOfBooks == null) {
listOfBooks = new ArrayList<String>();
}
if(bookName != null) {
listOfBooks.add(bookName);
}
request.getSession().setAttribute("Books", listOfBooks);
for(String book: listOfBooks) {
out.println("<li>" + book + "</li><br />");
}
这意味着不要仅在listOfBooks为空时而是在每次时都设置Books属性。这将通知所有正在运行的tomcat实例列表内容已更改,它们将重新扫描列表,并在所有实例中显示完整列表,而不仅仅是在正在运行的实例上。