`

征服 Apache + Tomcat (转)

阅读更多

原文转自http://snowolf.iteye.com/blog/743611

 

Apache Tomcat 原本就是一家,更是一家亲!Apache与Tomcat整合,无非是将Apache作为前端根据请求路径、端口、代理分发给多个Tomcat,以到达转发负载均衡 的目的!同时,通过Apache和Tomcat相互作用,进行粘性会话会话拷贝 构建集群 !这一切的最终结果就是“云服务 ”!不要说Session 不重要,当下火爆的团购 ,如果离开Session 还能快活多久?如何保证Session同步 ,仍然是不能回避的问题!

这里要说的是基于HTTP和AJP跳转方式的负载均衡实现,关于JK,由于效率问题一直成为诟病,这里就不折腾它的复杂配置了!

至于说Apache+Tomcat+SSL,并不是难题!只要完成了Apache+SSL然后配置相应的负载均衡、反向代理等等就可以达到目的,相关Apache+SSL参考征服 Apache + SSL

Ubuntu Server 10.04版本,Apache选用2.2.14,Tomcat选用6.0.24。

相关内容:
征服 Apache + SSL
征服 Apache + SVN
征服 Apache + Tomcat


步骤:

  1. 安装Apache基本模块
  2. 后台监控
  3. 负载均衡简单测试
  4. 配置Tomcat相关模块(AJP)
  5. 保持Session唯一,粘性会话
  6. Tomcat集群,Session复制



1.安装Apache相关模块
负载均衡需要的主要是代理模块!
经过几次Apache配置尝试,在Ubuntu下配置Apache实在是太容易了。加载什么模块、取消什么模块两个命令搞定。

Shell代码
  1. #启用模块  
  2. sudo a2enmod <model>  
  3. #禁用模块  
  4. sudo a2dismod <model>  
#启用模块
sudo a2enmod <model>
#禁用模块
sudo a2dismod <model>



这里,我们需要让Apache提供代理服务,其中又包含基于http、ftp、ajp等等协议的代理功能,同时还需要负载均衡模块。我们可以通过命令逐个加载:

Shell代码
  1. #代理核心模块  
  2. sudo a2enmod proxy  
  3. #代理AJP模块  
  4. sudo a2enmod proxy_ajp  
  5. #代理负载均衡模块  
  6. sudo a2enmod proxy_balancer  
  7. #代理HTTP模块  
  8. sudo a2enmod proxy_http  
  9. #代理FTP模块  
  10. sudo a2enmod proxy_ftp  
#代理核心模块
sudo a2enmod proxy
#代理AJP模块
sudo a2enmod proxy_ajp
#代理负载均衡模块
sudo a2enmod proxy_balancer
#代理HTTP模块
sudo a2enmod proxy_http
#代理FTP模块
sudo a2enmod proxy_ftp



完成上述操作后,系统会提示重启Apache!
先不着急重启,现学现卖,了解下Apache的目录结构。在Ubuntu下配置Apache主要是在/etc/apache2 目录下:

分述:

  • apache2.conf 核心配置文件,一般不需要修改!
  • conf.d 目录,里面包含了一些字符集设置,文档等设置!
  • dav_svn.authzdav_svn.passwd 是前面做SVN时,相关权限、密码文件。
  • envvars 定义了运行时的用户身份——www-data。
  • httpd.conf 是Apache留给我们自己折腾的配置文件,默认为空。apache2.conf 会加载这个文件。
  • ports.conf 端口默认配置。apache2.conf 会加载这个文件。
  • magic 为mod_mime_magic模块服务。
  • mods-enabledmods-available mods-enabled 会被apache2.conf 加载,里面包含*.load和*.conf文件。*.load文件中是加载相应的模块(位于/usr/lib/apache2/modules/ 中),而*.conf中是对应的基本配置。但这些文件其实都是链接到mods-available 中相应的文件上。当我们通过a2enmod 操作时,实际上正是操作了这些软链接。
  • sites-availablesites-enabledmods-enabledmods-available 的关系类似,只是其中包含的是站点内容。


罗嗦了一堆,下面配置负载均衡部分。
执行修改:

Shell代码
  1. sudo vi /etc/apache2/mods-available/proxy.conf  
sudo vi /etc/apache2/mods-available/proxy.conf



上图红框中的内容是原始内容,白框中的内容是我新加的部分。
注意红框中的配置:

Conf代码
  1. <Proxy *>  
  2.         AddDefaultCharset off  
  3.         Order deny,allow  
  4.         #Deny from all  
  5.         Allow from localhost ip6-localhost    
  6. </Proxy>  
        <Proxy *>
                AddDefaultCharset off
                Order deny,allow
                #Deny from all
                Allow from localhost ip6-localhost  
        </Proxy>


在默认配置中,Deny from all 处于可用状态。当我们配置其他代理节点时,将导致杜绝访问! 使用Allow from localhost ip6-localhost 限制仅允许本机访问!
再说,白框中的内容:

Conf代码
  1. <Proxy balancer://zlex>  
  2.         BalancerMember http://localhost:8080 /  
  3.         BalancerMember http://192.168 . 49.1 : 8080 /  
  4. </Proxy>  
        <Proxy balancer://zlex>
                BalancerMember http://localhost:8080/
                BalancerMember http://192.168.49.1:8080/
        </Proxy>


这里,我配置了一个负载均衡节点balancer://zlex ,其中包含了两个服务http://localhost:8080/http://192.168.49.1:8080/ ,一个是虚拟机上的Tomcat、一个是真机上的Tomcat。这里使用的Http的转发方式,当然,使用AJP未尝不可,稍后详述!
这里的节点次序会有一个先后关系,Apache会将请求按照FIFO的方式调度顺次分配到各个节点上!如果其中有一个节点挂掉,将跳过该节点顺次寻找可用节点。
再说代理和反向代理:

Conf代码
  1. ProxyPass /zlex balancer://zlex  
  2. ProxyPassReverse /zlex balancer://zlex  
        ProxyPass /zlex balancer://zlex
        ProxyPassReverse /zlex balancer://zlex


这里配置,如果要访问/zlex 路径时,将跳转到balancer://zlex 上,也就是享受负载均衡!

2.后台监控
我们如何知道某个节点负载多少,响应时间多久,服务是否正常呢?Apache提供了负载均衡监控平台:http://localhost/balancer-manager 。但是,这个服务默认是不存在。
除了用于负载均衡配置、监控的balancer-manager 还有http://localhost/server-statushttp://localhost/server-info
我们需要添加info模块:

Shell代码
  1. #系统信息模块  
  2. sudo a2enmod info  
#系统信息模块
sudo a2enmod info


同时,为了能够使用balancer-manager ,我们需要配置:

Conf代码
  1. <Location /balancer-manager>  
  2.         SetHandler balancer-manager  
  3.         Order Deny,Allow  
  4.         #Deny from all  
  5.         Allow from localhost ip6-localhost  
  6. </Location>  
<Location /balancer-manager>
        SetHandler balancer-manager
        Order Deny,Allow
        #Deny from all
        Allow from localhost ip6-localhost
</Location>


把这段代码放到哪?由于它同属系统信息配置,我把它放到了info.conf 中,说白了就是照猫画虎:

Shell代码
  1. sudo vi /etc/apache2/mods-available/info.conf  
sudo vi /etc/apache2/mods-available/info.conf



注意,这段代码放到了<IfModule mod_info.c></IfModule> 之间!
现在,我们重启Apache:

Shell代码
  1. sudo /etc/init.d/apache2 restart  
sudo /etc/init.d/apache2 restart


来看看管理界面http://localhost/balancer-manager


我们再来看看服务器基本信息http://localhost/server-info


上述两个服务需要加载info模块,而服务器状态(server-status)不需要http://localhost/server-status


3.负载均衡简单测试
疯狂访问http://localhost/zlex ,直到手酸眼烦!
我这里故意使用不同了Tomcat界面,来验证自己的配置是否生效。更疯狂的是,我甚至把节点指向了百度、搜狐,来测试负载均衡的效果。如果你细致观察,Apache是将请求顺次分配到各个节点上的。
如果其中一个节点发生问题(例如,强行关闭一个Tomcat,或配置一个错误节点)Apache将会经过几次尝试后,绕过这个问题节点,寻找可以成功访问的节点。如果这个节点恢复正常使用,Apache将在该Tomcat恢复正常工作后大约1分钟内将该节点标识为可用!
现在,再看看现在的后台(http://localhost/balancer-manager )啥样子:

如果我们控制一个节点的状态是否可用,该怎么做:

涉及到负载量,session同步等等,我们最后讨论!

4.配置Tomcat相关模块(AJP)
基于Http协议分发并不复杂,但AJP效果更好!一次诡异事件中,内网访问正常,外网访问多次失败,最后通过AJP方式完美解决了!
在Tomcat中配置AJP也很简单,修改server.xml 开启AJP模块:

Shell代码
  1. sudo vi /etc/tomcat6/server.xml   
sudo vi /etc/tomcat6/server.xml 


开启AJP配置:

Xml代码
  1. < Connector    port = "8009"   protocol = "AJP/1.3"    
  2.                 URIEncoding = "UTF-8"   
  3.                 redirectPort = "8443"   />   
<Connector  port="8009" protocol="AJP/1.3" 
                URIEncoding="UTF-8"
                redirectPort="8443" />


注意使用的端口port="8009" ,字符集URIEncoding="UTF-8" ,这是输入框、请求字符集乱码的入口!
接下里就可以通过AJP方式进行节点分发了。修改/etc/apache2/mods-available/proxy.conf

Shell代码
  1. sudo vi /etc/apache2/mods-available/proxy.conf    
sudo vi /etc/apache2/mods-available/proxy.conf  


http 改为ajp ,将8080 改为8009

Conf代码
  1. <Proxy balancer://zlex>  
  2.         BalancerMember ajp://localhost:8009 /  
  3.         BalancerMember ajp://192.168 . 49.1 : 8009 /  
  4. </Proxy>  
        <Proxy balancer://zlex>
                BalancerMember ajp://localhost:8009/
                BalancerMember ajp://192.168.49.1:8009/
        </Proxy>


重启Apache:

Shell代码
  1. sudo /etc/init.d/apache2 restart   
sudo /etc/init.d/apache2 restart 


再看看管理界面http://localhost/balancer-manager

至此,我们完成了基本负载均衡的基本配置!

/etc/apache2/mods-available/proxy.conf 还有一些属性,比如noFailOver 是否打开失败转移,On |Off ,默认为Off,添加在ProxyPass 后面,如:

Conf代码
  1. ProxyPass /zlex balancer://zlex  stickySession=JSESSIONID noFailOver=On  
        ProxyPass /zlex balancer://zlex  stickySession=JSESSIONID noFailOver=On


如果这样配置,当提供给你服务的服务器发生异常,那么你将一直看着它返回给你503,直到系统恢复正常!

5.Session唯一,粘性会话
Apache已经可以轻松将内容处理的工作分配给各个Tomcat了!
当然,这还不够,Session还是个问题!
WHY?

我们来做一系列修改,来检测Session到底出现了什么问题!
先来改造Tomcat,修改server.xml

Shell代码
  1. sudo vi /etc/tomcat6/server.xml   
sudo vi /etc/tomcat6/server.xml 


修改<Engine /> 节点,增加jvmRoute 属性:

Xml代码
  1. < Engine    
  2.              name = "Catalina"    
  3.              defaultHost = "localhost"    
  4.              jvmRoute = "tomcat1" >   
 <Engine 
              name="Catalina" 
              defaultHost="localhost" 
              jvmRoute="tomcat1">


另一个Tomcat设置改为

Xml代码
  1. < Engine    
  2.              name = "Catalina"    
  3.              defaultHost = "localhost"    
  4.              jvmRoute = "tomcat2" >   
 <Engine 
              name="Catalina" 
              defaultHost="localhost" 
              jvmRoute="tomcat2">


通过jvmRoute ,指定了Tomcat唯一标识!
然后修改/etc/apache2/mods-available/proxy.conf

Shell代码
  1. sudo vi /etc/apache2/mods-available/proxy.conf  
sudo vi /etc/apache2/mods-available/proxy.conf


如下:

Java代码
  1. <Proxy balancer: //zlex>   
  2.         BalancerMember ajp://localhost:8009/zlex     route=tomcat1    
  3.         BalancerMember ajp://192.168.49.1:8009/zlex        route=tomcat2    
  4. </Proxy>  
  5.   
  6. ProxyPass /zlex balancer://zlex   
  7. ProxyPassReverse /zlex balancer://zlex   
        <Proxy balancer://zlex>
                BalancerMember ajp://localhost:8009/zlex     route=tomcat1 
                BalancerMember ajp://192.168.49.1:8009/zlex        route=tomcat2 
        </Proxy>

        ProxyPass /zlex balancer://zlex
        ProxyPassReverse /zlex balancer://zlex



这里需要通过修改route 属性,将Apache与Tomcat关联起来!
注意,Tomcat中定义的jvmRoute 需要与Apache定义的route 相对应!
我们来看一下http://localhost/balancer-manager 发生了什么变化:

我们注意到route字段有了新的标识,当然,我们也可以通过这个配置界面修改这些信息,但当前修改不会真的修改/etc/apache2/mods-available/proxy.conf文件,Apache重启后将丢失。

为了更细致的对比进过复杂均衡的结果,这里增加了zlex应用!主要是监控Session的变化!
只看核心代码:

Jsp代码
  1. <b>当前SessionID:</b>  
  2. <br />  
  3. <%  
  4.         String sessionID = session.getId();  
  5.         out.println(sessionID);  
  6.         System.err.println("sessionID = "  + sessionID);  
  7.   
  8.         // 如果有新的 Session 属性设置  
  9.         String dataName = request.getParameter("dataName" );  
  10.         if (dataName != null && !dataName.isEmpty()) {  
  11.                 String dataValue = request.getParameter("dataValue" );  
  12.                 session.setAttribute(dataName, dataValue);  
  13.         }  
  14. %>  
  15. <br />  
  16. <br />  
  17. <b>Session属性列表:</b>  
  18.   
  19. <br />  
  20. <%  
  21.         Enumeration<String> e = (Enumeration<String>) session  
  22.                         .getAttributeNames();  
  23.         while (e.hasMoreElements()) {  
  24.                 String name = e.nextElement();  
  25.                 String value = (String) session.getAttribute(name);  
  26.                 out.println(name + " = "  + value +  "<br>" );  
  27.                 System.err.println(name + " = "  + value);  
  28.         }  
  29. %>  
  30. <form method="POST" >  
  31. <ul style="list-style-type: none;" >  
  32.         <li><label for="dataName" >键:</label><input size= "20"  id= "dataName"   
  33.                 name="dataName" ></li>  
  34.         <li><label for="dataValue" >值:</label><input size= "20"   
  35.                 id="dataValue"  name= "dataValue" ></li>  
  36.         <li><input type="submit"  value= "提交"  /></li>  
  37. </ul>  
  38. </form>  
<b>当前SessionID:</b>
<br />
<%
        String sessionID = session.getId();
        out.println(sessionID);
        System.err.println("sessionID = " + sessionID);

        // 如果有新的 Session 属性设置
        String dataName = request.getParameter("dataName");
        if (dataName != null && !dataName.isEmpty()) {
                String dataValue = request.getParameter("dataValue");
                session.setAttribute(dataName, dataValue);
        }
%>
<br />
<br />
<b>Session属性列表:</b>

<br />
<%
        Enumeration<String> e = (Enumeration<String>) session
                        .getAttributeNames();
        while (e.hasMoreElements()) {
                String name = e.nextElement();
                String value = (String) session.getAttribute(name);
                out.println(name + " = " + value + "<br>");
                System.err.println(name + " = " + value);
        }
%>
<form method="POST">
<ul style="list-style-type: none;">
        <li><label for="dataName">键:</label><input size="20" id="dataName"
                name="dataName"></li>
        <li><label for="dataValue">值:</label><input size="20"
                id="dataValue" name="dataValue"></li>
        <li><input type="submit" value="提交" /></li>
</ul>
</form>


将其做成一个名为zlex的web应用,分别部署到两个Tomcat上!
然后重启Apache:

Shell代码
  1. sudo /etc/init.d/apache2 restart  
sudo /etc/init.d/apache2 restart


不断刷新http://localhost/zlex ,看看真正的恶魔:
第1次:
第2次:
第3次:
第4次:
仔细观察,每次请求都按照负载均衡配置的节点次序依次请求到不同的Tomcat上。尤其是当我们通过jvmRouteroute 做了绑定之后,信息更加准确。但是,仔细观察,每次请求的SessionID都是不一样! 对于纯Web应用,尤其是依靠SessionID区分唯一用户的应用,这将是一场噩梦——解决了服务器压力均衡问题,却带来了SessionID不唯一问题!这就需要SessionID绑定,或者说叫做“会话复制”。
如果这时候你在页面上提交表单,将键值对保持在session中,在页面刷新后,将无法获得该信息,因为Seesion丢失了!
接着修改/etc/apache2/mods-available/proxy.conf ,让SeesionID保持唯一:

Shell代码
  1. sudo vi /etc/apache2/mods-available/proxy.conf  
sudo vi /etc/apache2/mods-available/proxy.conf


增加stickySession 属性:

Conf代码
  1. ProxyPass /zlex balancer://zlex  stickySession=JSESSIONID  
        ProxyPass /zlex balancer://zlex  stickySession=JSESSIONID


stickySession 粘性会话,根据这一属性,浏览器将通过cookie绑定SeesionID。如果这个时候再次访问http://localhost/zlex ,你会发现,页面不会来回跳转了!
sticky是什么?

引用
sticky模式
利用负载均衡器的sticky模式的方式把所有同一session的请求都发送到相同的Tomcat节点。这样不同用户的请求就被平均分配到集群 中各个tomcat节点上,实现负载均衡的能力。这样做的缺点是没有灾难恢复的能力。一旦一个节点发生故障,这个节点上所有的session信息全部丢 失;
同一用户同一session只和一个webServer交互,一旦这个webserver发生故障,本次session将丢失,用户不能继续使用 !


提交一个Session设定看看http://localhost/zlex

观察后台日志:

再看看返回页面,这相当于一次页面刷新,如果正常粘性会话,我们将获得当前SessionID对应的一切信息:

这说明粘性会话生效了!
我们得到了形如

引用
50DAF14C6CDF8ACFBDC1095A5EE8E2CF.tomcat1

的SessionID。这样,我们就能知道当前访问的是哪台服务器了!
如果,换一个浏览器打开该页面http://localhost/zlex ,将会获得一个新的SessionID,并且,根据Apache中配置的负载均衡节点列表依次访问下一个节点!
如果这时候负载均衡节点列表中某一节点发生异常,那么Apache将按照惯例,跳转该节点,并在该节点恢复正常后约1分钟内重新将其纳入可用节点!

修改刚才的jsp页面,看看Http头中都有些什么:

Jsp代码
  1. <b>Cookie信息:</b>  
  2. <br />  
  3. ${header["cookie" ]}  
  4. <br />  
  5. <b>Host信息:</b>  
  6. <br />  
  7. ${header["host" ]}  
  8. <br />  
<b>Cookie信息:</b>
<br />
${header["cookie"]}
<br />
<b>Host信息:</b>
<br />
${header["host"]}
<br />



sticky模式 的根本在于浏览器支持cookie,如果浏览器不支持cookie,则需要修改server.xml文件中的<Context />节点,将cookie 置为false ,关闭cookie功能,让jsessionid显式传递!

6.Tomcat集群,Session复制
经过两天反复研究,两只互不相认的Tomcat终于在网络上“资源共享”了——Session复制成功!
关于Tomcat集群以及Session复制 ,网上已经有很多很多,但是否真的能用?!为了确认这一问题,周末还跑到书店翻了翻《Apache Tomcat 高级编程》,参考Clustering/Session Replication HOW-TO (有点小错误),经过两天苦战,克服种种小问题,终于拿下!

引用
Session复制,主要是指集群环境下,多台应用服务器之间同步Session,确保Session保持一致,且Session中的内容保持一致,对外透明——看起来就像是一台应用服务器!
如果其中一台服务器发生故障,根据负载均衡的原理,Apache会遍历寻找可用节点,分发请求。与此同时,当前用户Session不能发生数据丢失,其余各节点服务器应保证用户Session数据同步。



为了搭建Tomcat集群,我将两个Tomcat分别部署到两台虚拟机上,确保网段一致。(这一步很关键,我最初将Tomcat1(192.168.49.132) 部署在虚拟机上,将Tomcat2(192.168.49.128) 部署在本机上,结果,网络总有问题,耽误了很多时间。

由于变换了IP,我需要修改Apache的/etc/apache2/mods-available/proxy.conf 文件:

Shell代码
  1. sudo vi /etc/apache2/mods-available/proxy.conf   
sudo vi /etc/apache2/mods-available/proxy.conf 



修改负载均衡节点如下:

Conf代码
  1. <Proxy balancer://zlex>  
  2.         BalancerMember ajp://192.168 . 49.128 : 8009 /zlex        route=tomcat1  
  3.         BalancerMember ajp://192.168 . 49.132 : 8009 /zlex        route=tomcat2  
  4. </Proxy>  
        <Proxy balancer://zlex>
                BalancerMember ajp://192.168.49.128:8009/zlex        route=tomcat1
                BalancerMember ajp://192.168.49.132:8009/zlex        route=tomcat2
        </Proxy>



对于windows系统,不需要考虑网络问题,广播地址(这里用到224.0.0.0240.0.0.0 )默认开放,对于linux则需要通过命令开放地址。
Ubuntu上开放广播地址(eth0网卡):

Shell代码
  1. sudo route add -net  224.0 . 0.0  netmask  240.0 . 0.0  dev eth0  
sudo route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0


然后通过-v 参数查看当前开放的广播地址:

Shell代码
  1. route -v  
route -v




注意,重启后,该路由设置将丢失!

在Ubuntu下,可以考虑修改/etc/networks 文件!


如果有必要,Windows上开放广播地址(192.168.49.128本机地址):

Cmd代码
  1. route add  224.0 . 0.0  mask  240.0 . 0.0   192.168 . 49.128   
route add 224.0.0.0 mask 240.0.0.0 192.168.49.128


然后通过print 参数查看当前开放的广播地址:

Shell代码
  1. route print  
route print




然后,修改tomcat的server.xml文件:

Shell代码
  1. sudo vi /etc/tomcat6/server.xml   
sudo vi /etc/tomcat6/server.xml 


<Engine /> 节点中加入如下内容:

Xml代码
  1.    < Cluster   className = "org.apache.catalina.ha.tcp.SimpleTcpCluster"   
  2.          channelSendOptions = "8" >   
  3.   
  4.   < Manager   className = "org.apache.catalina.ha.session.DeltaManager"   
  5.            expireSessionsOnShutdown = "false"   
  6.            notifyListenersOnReplication = "true" />   
  7.   
  8.   < Channel   className = "org.apache.catalina.tribes.group.GroupChannel" >   
  9.     < Membership   className = "org.apache.catalina.tribes.membership.McastService"   
  10.                 address = "224.0.0.0"   
  11.                 port = "45564"   
  12.                 frequency = "500"   
  13.                 dropTime = "3000" />   
  14.     < Receiver   className = "org.apache.catalina.tribes.transport.nio.NioReceiver"   
  15.               address = "192.168.49.1"   
  16.               port = "4000"   
  17.               autoBind = "100"   
  18.               selectorTimeout = "5000"   
  19.               maxThreads = "6" />   
  20.   
  21.     < Sender   className = "org.apache.catalina.tribes.transport.ReplicationTransmitter" >   
  22.       < Transport   className = "org.apache.catalina.tribes.transport.nio.PooledParallelSender" />   
  23.     </ Sender >   
  24.     < Interceptor   className = "org.apache.catalina.tribes.group.interceptors.TcpFailureDetector" />   
  25.     < Interceptor   className = "org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor" />   
  26.   </ Channel >   
  27.   
  28.   < Valve   className = "org.apache.catalina.ha.tcp.ReplicationValve"   
  29.          filter = ".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;" />   
  30.   < Valve   className = "org.apache.catalina.ha.session.JvmRouteBinderValve" />   
  31.   
  32.   < ClusterListener   className = "org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener" />   
  33.   < ClusterListener   className = "org.apache.catalina.ha.session.ClusterSessionListener" />   
  34. </ Cluster >    
          <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="224.0.0.0"
                        port="45564"
                        frequency="500"
                        dropTime="3000"/>
            <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
                      address="192.168.49.1"
                      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"
 

  


  
分享到:
评论
1 楼 devroller2 2011-11-30  

相关推荐

    征服 Apache + Tomcat

    NULL 博文链接:https://snowolf.iteye.com/blog/743611

    征服Ajax Web 2.0

    3. **Tomcat 5以上**: Apache Tomcat是一个开源的Servlet容器,用于部署Java Web应用。 4. **Eclipse 3.0**: 集成开发环境,支持Java和JavaScript开发,便于构建和调试Ajax应用。 **四、学习资源** 本资源可能包含...

    JavaEE程序员必读图书大推荐参照.pdf

    8. 《Tomcat 权威指南》:做 Java Web 的一般都必须学习这个,为 Apache 的开源项目。 9. 《Head First Servlets & Jsp》:Servlet 和 Jsp 是 JavaEE 程序员必须要掌握好的。 10. 《Head First HTML与 CSS.XHTML 》...

    技嘉Z97X UD3H F9 增加NVME启动功能

    亲测可用

    《基于YOLOv8的音响设备识别系统》(包含源码、完整数据集、可视化界面、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。

    毕业设计物联网实战项目基于mqttd-centos7-v2.3.11.zip 配置的emqtt服务器,配套金大万翔物联网管理平台.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕设单片机实战项目基于ESP8266的家庭版简易开关.zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕设单片机实战项目基于ESP8266制作的一个局域网关灯神器,还有一个OLED,用于显示实时时间和最近三天的天气信息。.zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    毕业设计物联网实战项目基于树莓派wifi的物联网项目.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    IDE的护眼的主题的套件

    IDE护眼主题套件

    【新能源汽车】基于Matlab/Simulink的增程式电动车动力系统仿真模型设计与优化:功率跟随控制及能量流管理

    内容概要:文章详细介绍了基于Matlab/Simulink构建的增程式电动车仿真模型。该模型由电池、电机、发动机、整车动力学、控制策略和驾驶员模块六大组件构成,重点在于各模块间的能量流动逻辑。文中特别强调了功率跟随控制策略,通过PID闭环控制使发动机功率与电池需求动态匹配,优化了燃油经济性和SOC控制精度。此外,模型采用开放式架构,所有参数通过m脚本集中管理,便于修改和扩展。文章展示了模型在典型工况下的性能表现,并突出了其在科研和工程应用中的灵活性和实用性。; 适合人群:对新能源汽车技术感兴趣的工程师、研究人员以及高校相关专业师生。; 使用场景及目标:①用于研究增程式电动车的能量管理策略;②作为教学案例帮助学生理解复杂系统的建模方法;③为实际工程项目提供可复用的仿真平台。; 阅读建议:读者应重点关注模型的架构设计和关键控制算法实现,同时结合提供的代码片段进行实践操作,以便更好地掌握增程式电动车的工作原理及其优化方法。

    51a30-main.zip

    51a30-main.zip

    【Java数据库技术】索引类型与事务特性详解:提升SQL查询性能与数据一致性管理

    内容概要:本文详细介绍了多种类型的数据库索引及其应用场景,包括普通索引、唯一性索引、单个索引、复合索引、聚簇索引、非聚簇索引、主索引、外键索引、全文索引和空间索引。每种索引都有其独特的定义、要点和适用场景,并附有具体的SQL代码示例。此外,文章还对比了InnoDB和MyISAM两种存储引擎的特点,解释了脏读、不可重复读、可重复读和幻读的概念,并讨论了SQL优化的方法以及数据库事务的ACID特性。 适合人群:具备一定数据库基础知识的开发者、数据库管理员以及参与数据库设计和优化的技术人员。 使用场景及目标:①帮助开发者选择合适的索引类型以提高查询效率;②理解不同存储引擎的特点,选择最适合应用场景的存储引擎;③掌握事务隔离级别的概念,避免数据不一致问题;④学习SQL优化技巧,提升数据库性能;⑤理解ACID特性,确保数据库操作的一致性和可靠性。 阅读建议:本文内容较为全面且深入,建议读者结合实际项目需求,重点理解不同类型索引的应用场景,掌握SQL优化的基本原则,并熟悉事务处理的最佳实践。

    【MATLAB优化算法】基于MATLAB的优化算法实现与应用:涵盖梯度下降、线性规划、非线性规划及智能优化算法

    内容概要:本文详细介绍了MATLAB中优化算法的实现方法,涵盖确定性算法(如梯度下降法)和随机性算法(如遗传算法、粒子群优化)。文章首先讲解了梯度下降法和MATLAB优化工具箱的应用,展示了如何使用fmincon解决约束优化问题。接着,文章深入探讨了线性规划、非线性规划和多目标优化的理论和实践,提供了具体的MATLAB代码示例。此外,文中还介绍了遗传算法、粒子群优化和模拟退火算法的原理及应用,并通过实例展示了这些算法在实际问题中的使用。最后,文章讨论了优化算法在工程、金融和机器学习领域的高级应用,以及调试和优化的常见策略。 适合人群:具备一定编程基础,对优化算法感兴趣的工程师、研究人员和学生。 使用场景及目标:①理解优化算法的基础理论和实现方法;②掌握MATLAB优化工具箱的使用,解决线性、非线性、多目标优化问题;③学习遗传算法、粒子群优化和模拟退火算法的具体应用;④提高优化算法的性能和可靠性,解决实际工程、金融和机器学习问题。 阅读建议:本文内容丰富,涉及多种优化算法及其MATLAB实现,建议读者先掌握基本的优化理论和MATLAB编程基础,再逐步深入学习各类算法的具体应用。在学习过程中,结合提供的代码示例进行实践,并尝试调整参数以优化算法性能。

    python for appium ui automate test, it is something to update.

    this is for myself learn coding, change a pc debug.

    p111基于django的企业员工管理系统.zip

    项目资源包含:可运行源码+sql文件 适用人群:学习不同技术领域的小白或进阶学习者;可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 项目具有较高的学习借鉴价值,也可拿来修改、二次开发。 有任何使用上的问题,欢迎随时与博主沟通,博主看到后会第一时间及时解答。 开发语言:Python 框架:django Python版本:python3.8 数据库:mysql 5.7 数据库工具:Navicat 开发软件:PyCharm 浏览器:谷歌浏览器

    毕设单片机实战项目基于esp8266的太空人时钟小电视.zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    电力电子MMC型STATCOM/SVG载波移相调制与电压均衡控制技术详解:从理论到实战调试经验分享

    内容概要:本文深入探讨了MMC型STATCOM/SVG的核心技术和调试技巧,重点讲解了载波移相调制(CPS-PWM)和电压均衡控制两大关键技术。载波移相调制通过为每个子模块设置不同的载波相位差,有效降低谐波含量并优化开关频率。电压均衡则分为桥臂内、桥臂间和相间三个层次,分别采用动态排序、比例控制和零序电压注入等方法,确保系统稳定运行。文章还分享了多个实战经验,如低压调试、红外热像仪检测以及避免参数设置不当引发的问题。; 适合人群:从事电力电子领域,特别是参与STATCOM/SVG项目的设计、开发和调试的技术人员。; 使用场景及目标:①理解MMC型STATCOM/SVG的工作原理和技术细节;②掌握载波移相调制的具体实现方法;③学习电压均衡控制的各种策略及其应用场景;④获取实际调试过程中常见问题的解决方案。; 阅读建议:本文涉及大量技术细节和实战经验,建议读者结合实际项目进行阅读,重点关注载波移相调制和电压均衡控制的具体实现,并参考提供的代码片段进行实践。

    liangmmm_finalll.scdoc

    liangmmm_finalll.scdoc

    区块链开发中Solidity语言的关键特性与应用解析

    内容概要:本文详细介绍了Solidity语言的核心概念和语法特性,涵盖结构体、函数修改器、事件、类型系统、数组、映射、操作符、合约可见性、构造函数、抽象合约、接口、继承、控制结构、异常处理和keccak256哈希函数等内容。通过这些知识点的讲解,帮助开发者理解如何构建高效、安全的智能合约。; 适合人群:对区块链开发感兴趣,尤其是希望深入了解以太坊智能合约开发的初学者及有一定编程基础的研发人员。; 使用场景及目标:①掌握Solidity语言的基本语法和高级特性,如结构体、函数修改器、事件等;②理解合约的可见性、继承、接口等面向对象编程特性;③学会使用keccak256等安全机制保障智能合约的安全性;④能够运用控制结构和异常处理编写健壮的合约逻辑。; 阅读建议:建议读者从基础语法开始逐步深入,结合实际案例进行练习。尤其要注意合约的安全性和性能优化,避免常见的漏洞和错误。在学习过程中,应多参考官方文档和其他优质资料,不断巩固和拓展知识体系。

Global site tag (gtag.js) - Google Analytics