??xml version="1.0" encoding="utf-8" standalone="yes"?>
删除服务: sc delete "Jboss for Adobe LiveCycle"
在创建服务的时? 开始老是不成? 后来发现是在参数 "binPath=" 后面?"displayName="后面,都是要有一个空格的...... ..好奇怪呀. .
JMS做ؓJ2EE的高U部分一直蒙着一层神U的面纱Q作为JMS的定制者SUN只规定了JMS规范Q象很多其他SUN产品一栯多家厂商提供了具 体的实现。但是作为tomcat和RESINQ今q初宣布全部支持J2EE规范Q。这些面向低端但却被q泛应用的服务器本nq不对JMS提供支持。庆q的 是openjms和activeMQ两家开源Y件提供了插g式的支持?
在应用了一些开发框架如spring的项目里如果要用到JMSQ虽然SPRING提供了部分对JMS的支持但l过我一D|间的应用? 玎ͼOO的封装在某些地方反而成为开发过E中的障。在实现诸如监听之类的代码段里人非常的懊恼Q即使用callback(回调)有些东西仍然不能够很 好的被取到?
下面׃些TOMCAT上面JMS的支持既实现做一下整理?
1.很自然的你需要下载JMS实现,?opnerJMS或者activeMQ .下蝲地址www.jmsopen.com 或www.activeMQ.com
2.服务器下载以后的具体配置在以上两个网站上都有很详l的说明Q就不再列D了?
3.和WEB服务器的整合Q首先要配置应用的web.xmlq个文g配置如下Q?
|
这一D代码放到web.xml里。注意到activemq.xml文gQ是jms服务器的具体配置Q?
|
此时Q在启动你的TOMCAT的时候会看到JMS服务器已l绑C上面?/p>
估计最高在Uh数是3万,q发人数最?00人。开发的|站是否能否承受q个压力Q如何确保网站的负荷没有问题Q经q研I决定如下:
Q?Q?采用负蝲q和集技术,初步机构采用Apache+Tomcat的机技术?br />
Q?Q?采用压力试工具Q测试压力。工hLoadrunner?br />
g环境搭徏Q?br />
Z能够q行压力试Q需要搭Z个环境。刚开始时Q测试在公司局域网内进行,但很快发C一个问题,即一个脚本的压力试l果每次都不一Pq且差别很大。原来是受公司网l的影响Q于是决定搭Z个完全隔ȝ局域网试。搭建后的局域网配置如下Q?br />
Q?Q?|络速度Q?00M
Q?Q?三台服务器:
负蝲服务?Q操作系lwindows2003Q?br />
Tomcat服务器:操作pȝwindows2000 Professional
数据库服务器Q操作系lwindows2000 Professional
三台机器的cpu 2.4 G, 内存 1G?br />
软g环境搭徏Q?br />
软g的版本如下:
Apache 版本Q?.054Q?br />
Tomcat5.0.30,
mysql Q?.1.14.
JDK1.5
压力试工具QLoadrunner7.8?
负蝲qҎ如下Q?br />
一台机器(操作pȝ2003Q安装apacheQ作载服务器Qƈ安装tomcat作ؓ一个workerQ一个单独安装tomcatQ作为第二个workerQ剩下的一台单独作为数据库服务器?br />
Apache和tomcat的负载^衡采用JK1.2.14Q没有采?.0Q主要是2.0不再l护了)?br />
集群ҎQ?br />
采用Tomcat本n的集方案。在server.xml配置?br />
压力试问题Q?br />
压力试后,发现了一些问题,C一列出来:
Q?Q?采用Tocmat集群后,速度变得很慢。因为集后Q要q行session复制Q导致速度较慢。Tomcatd的复Ӟ目前不支持application复制。复制的作用Q主要用来容错的Q即一台机器有故障后,apache可以把请求自动{发到另外一个机器。在定w和速度的考虑上,我们最l选择速度Q去掉了Tomcat集群?br />
Q?Q?操作pȝ最大ƈ发用L限制Q?br />
Z采用|站的压力,我们开始的时候,仅测试Tomcat的最大负载数。Tomcat服务器安装的操作pȝ是windows2000 Professional。当我们用压力测试工Pq发试Ӟ发现只要过15个ƈ发用P会经常出现无法连接服务器的情c经q研IӞ发现是操作系l的问题Qwindows2000 Professional 支持的ƈ发访问用h限,默认的好像是15个。于是我们把操作pȝ全部采用windows2003 server版本?br />
Q?Q?数据库连接池的问题:
试数据库连接性能Ӟ发现数据库连接速度很慢。每增加一些用Pq接性能差了很多。我们采用的数据库连接池是DBCPQ默认的初始化ؓ50个,应该不会很慢吧。查询数据库的连接数Q发现初始化Q只初始化一个连接。ƈ发增加一个用hQ程序就会重新创Z个连接,Dq接很慢。原因就在这里了。如何解军_Q偶在JDK1.4下的Tomcat5.0.30下执行数据库q接压力试Q发现速度很快Q程序创建数据库q接的速度也是很快的。看来JDK1.5的JDBC驱动E序有问题。于是我们修?JDK的版本ؓ1.4.
Q?Q?C3P0和DBCP
C3P0是Hibernate3.0默认的自带数据库q接池,DBCP是Apache开发的数据库连接池。我们对q两U连接池q行压力试ҎQ发现在q发300个用户以下时QDBCP比C3P0q_旉?U左叟뀂但在ƈ?00个用hQ两者差不多?br />
速度上虽然DBCP比C3P0快些Q但是有BUGQ当DBCP建立的数据库q接Q因为某U原因断掉后QDBCP不会再重新创徏新的q接Q导致必重新启动Tomcat才能解决问题。DBCP的BUG使我们决定采用C3P0作ؓ数据库连接池?br />
调整后的ҎQ?br />
操作pȝWindows2003 server版本
JDK1.4
Tomcat 5.0.30
数据库连接池C3P0
仅采用负载^衡,不采用集?br />
软g的配|:
Apache配置Q主要配|httpd.conf和新增加的文件workers.properties
Httpd.confQ?br />
#一个连接的最大请求数?br />
MaxKeepAliveRequests 10000
#NT环境Q只能配|这个参数来提供性能
#每个q程的线E数Q最?920。NT只启动父子两个进E,不能讄启动多个q程
ThreadsPerChild 1900
每个子进E能够处理的最大请求数
MaxRequestsPerChild 10000
# 加蝲mod_jk
#
LoadModule jk_module modules/mod_jk.so
#
# 配置mod_jk
#
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel info
#h分发Q对jsp文gQ?do{动态请求交由tomcat处理
DocumentRoot \"C:/Apache/htdocs\"
JkMount /*.jsp loadbalancer
JkMount /*.do loadbalancer
JkMount /servlet/* loadbalancer
#xLLookupQ如果ؓonQ很影响性能Q可以有10多秒钟的延迟?br />
HostnameLookups Off
#~存配置
LoadModule cache_module modules/mod_cache.so
LoadModule disk_cache_module modules/mod_disk_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so
CacheForceCompletion 100
CacheDefaultExpire 3600
CacheMaxExpire 86400
CacheLastModifiedFactor 0.1
CacheEnable disk /
CacheRoot c:/cacheroot
CacheSize 327680
CacheDirLength 4
CacheDirLevels 5
CacheGcInterval 4
CacheEnable mem /
MCacheSize 8192
MCacheMaxObjectCount 10000
MCacheMinObjectSize 1
MCacheMaxObjectSize 51200
worker. Properties文g
#
# workers.properties Q可以参?br />
http://jakarta.apache.org/tomcat/connectors-doc/config/workers.html
# In Unix, we use forward slashes:
ps=
# list the workers by name
worker.list=tomcat1, tomcat2, loadbalancer
# ------------------------
# First tomcat server
# ------------------------
worker.tomcat1.port=8009
worker.tomcat1.host=localhost
worker.tomcat1.type=ajp13
# Specify the size of the open connection cache.
#worker.tomcat1.cachesize
#
# Specifies the load balance factor when used with
# a load balancing worker.
# Note:
# ----> lbfactor must be > 0
# ----> Low lbfactor means less work done by the worker.
worker.tomcat1.lbfactor=900
# ------------------------
# Second tomcat server
# ------------------------
worker.tomcat1.port=8009
worker.tomcat1.host=202.88.8.101
worker.tomcat1.type=ajp13
# Specify the size of the open connection cache.
#worker.tomcat1.cachesize
#
# Specifies the load balance factor when used with
# a load balancing worker.
# Note:
# ----> lbfactor must be > 0
# ----> Low lbfactor means less work done by the worker.
worker.tomcat1.lbfactor=2000
# ------------------------
# Load Balancer worker
# ------------------------
#
# The loadbalancer (type lb) worker performs weighted round-robin
# load balancing with sticky sessions.
# Note:
# ----> If a worker dies, the load balancer will check its state
# once in a while. Until then all work is redirected to peer
# worker.
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tomcat1,tomcat2
#
# END workers.properties
#
Tomcat1配置:
enableLookups=\"false\" redirectPort=\"8443\" acceptCount=\"100\"
debug=\"0\" connectionTimeout=\"20000\"
disableUploadTimeout=\"true\" />
启动内存配置,开发configure tomcatE序卛_配置Q?br />
Initial memory pool: 200 M
Maxinum memory pool:300M
Tomcat2配置Q?br />
配置和tomcat1差不多,需要改动的地方如下Q?br />
启动内存配置,开发configure tomcatE序卛_配置Q?br />
Initial memory pool: 512 M
Maxinum memory pool:768M
Mysql配置Q?br />
ServercdQDedicated MySQL Server Machine
Database usage:Transational Database Only
q发q接数量QOnline Transaction Processing(OLTP)
字符集:UTF8
数据库连接池的配|:
我们采用的是spring 框架Q配|如下:
其他的没有额外配|?br />
LoadRunner 常见问题Q?br />
Q?Qsofeware caused connctionQ这U情况,一般是脚本有问题,或者loadrunner有问题。解x法:重新启动机器Q或者重新录制脚本,估计是loadrunner的bug?br />
Q?Qcannot connect to server:无法q接到服务器。这U情冉|服务器的配置有问题,服务器无法承受过多的q发q接了。需要优化服务器的配|,
如操作系l采用windows 2003 serverQ?br />
优化tomcat配置QmaxThreads=\"500\" minSpareThreads=\"400\" maxSpareThreads=\"450\"。但是tomcat 最多支?00个ƈ发访?br />
优化apache配置Q?br />
ThreadsPerChild 1900
MaxRequestsPerChild 10000
其他的错误如Q?br />
Action.c(10): Error -27791: Server has shut down the connection prematurely
HTTP Status-Code=503 (Service Temporarily Unavailable)
一般都是由于服务器配置不够好引LQ按照问题(2Q处理,如果仍旧不行Q需要优化硬件和调整E序了?br />
Apache问题Q?br />
Q?Q?File does not exist: C:/Apache/htdocs/favicon.icoQ?br />
q个问题是apacheQhtdocs目录没有favicon.ico文g引v的,该文件是|站的图标,仅在firefox,myIE{浏览器出现?br />
Q?Q?囄无法昄Q?br />
配置apache后,却无法显C图片?br />
解决ҎQ把E序的图片,按照E序l构copy到apache的htdocs目录下?br />
Q?Q?无法处理hQ?br />
没有问题。原因是没有?do命o转发ltomcat处理。解x法如下:
在apache配置文g中配|如下内容:
DocumentRoot \"C:/Apache/htdocs\"
JkMount /*.jsp loadbalancer
JkMount /*.do loadbalancer
ȝQ?br />
|站的压力测试,涉及的知识面挺广的,不仅要熟悉压力测?q要善于发现问题Q要知道如何解决。最重要的一点,要有良好的测试方法。刚开始测试时Q可以从最单的试脚本入手Q不需要太复杂的脚本,q样便于发现问题。如我们刚开始时Q就从一个简单的下蝲登陆界面的脚本入手,试一个tomcat的压力负载。一个简单的获取登陆的脚本,帮助我们优化了tomcat的配|;后来再测试数据库q接Q也是一个简单的数据库连接脚本,帮助我们优化了数据库q接池;然后利用q些单的脚本Q测试apache的负载^衡,优化了apache配置。最后运行复杂的脚本Q模拟多U角色的用户在不同时间下的处理,以测试网站压力负载?/p>
集群允许一个应用同时运行在多个q发的服务器。负载分布在不同的服务器Q即使有个别服务器崩溃,应用E序q可以通过别的服务器节点访问。集是企业U应用的关键技术,可以通过单地增加节点来提升性能?/p>
JBoss支持集群Q启动一个JBoss集群的最单的方式?使用run -c all命o在局域网内启动多个JBoss实例。这些服务器实例Q都使用all配置集,自动地构Z个集?/p>
一个集是׃pd节点l成。在一个JBoss集群中,一个节Ҏ一个JBoss服务器实例,要构Z个集,必须几个JBoss服务器实例组合在一赗在一个局域网可能有多个集,Z区分他们Q每个集必L唯一的名U?/p>
下图构徏一个网l,包含三个集群。节点可以在M时候添加到集群或者从集群?/p>
一个JBoss服务器实例可以同时在多个集群Q但是不推荐q样做,因ؓ会增加管理复杂性?/p>
JBoss服务器实例通过deploy/cluster-service.xml 文g中的ClusterPartition MBean指定属于哪一个集。所有有同样的ClusterPartition MBean配置的节点属性同一个集。因此,如果惛_同一个局域网构徏两个集群Q只需要创Z个不同的ClusterPartition配置卛_。如果某一个节点启动时Q集还不存在,会创个集,同时当属于一个集的所有节点移除时Q集也会被U除?/p>
下面的示例是JBoss发布包的~省定义Q通过使用此缺省集设|启动服务器Q将可以构徏一个缺省集名UCؓDefaultPartition的集?/tt>
q里省略了详l的JGroups协议配置QJGoups处理底层的节点之间的点对炚w信Q稍后将讨论其具体配|?tt>ClusterPartition MBean可配|的属性包括:
PartitionName ~省值是DefaultPartitionQ可选属性,用来指定集群的名U?/tt>
NodeAddress 讄节点的IP地址?/p>
DeadlockDetection ~省gؓfalseQ设|JGroups是否Z每个h都运行消息死锁检算法?/p>
StateTransferTimeout ~省值是30000Q设|集之间的状态复制的时倹{?/p>
PartitionConfig 指定JGourp配置选项?/p>
一个集包含的所有节点,必须有同L PartitionName ?ParitionConfig 元素。改变某些节点的q两个元素将D集群分离Q通过改变ParitionConfig 是更Ҏ一些?/p>
可以通过集群中的M一个节点的JMX控制台查看当前集信息(比如Q?a href="http://hostname:8080/jmx-console">http://hostname:8080/jmx-consoleQ,然后点击 jboss:service=DefaultPartition MBeanQ将可以看到当前集群的所有节点的IP地址列表?/p>
A cluster (partition) contains a set of nodes that work toward a same goal. Some clustering features require to sub-partition the cluster to achieve a better scalability. For example, let's imagine that we have a 10-node cluster and we want to replicate in memory the state of stateful session beans on all 10 different nodes to provide for fault-tolerant behaviour. It would mean that each node has to store a backup of the 9 other nodes. This would not scale at all (each node would need to carry the whole state cluster load). It is probably much better to have some kind of sub-partitions inside a cluster and have beans state exchanged only between nodes that are part of the same sub-partition. The future JBoss clustering implementation will support sub-partitions and it will allow the cluster administrator to determine the optimal size of a sub-partition. The sub-partition topology computation will be done dynamically by the cluster.
对于应用E序开发h员来Ԍ可能更关心集的架构QJBoss支持两种cd的集架构,一U是客户端的拦截器架构,比如代理和存根,q有一U是负蝲q器?/p>
JBoss应用服务器提供的大多数远E服务,包括JNDI,EJB,RMI{都要求客户端获取一个存根对象。存根对象由服务器生成,实现服务接口。客L在本地调用存根对象,q些调用自动q行|络路由Q激zL务器理的服务对象。在一个集环境中Q服务器生成的存根对象也是一个拦截器实现Q知道如何在集群包含的节点中路由h。存根对象知道如何查扑适的服务器节点,~码调用参数Q解码调用结果,q返回结果给客户端?/p>
存根拦截器包含集的相关信息Q比如,所有可用的服务器节点的IP地址Q负载^衡算法,以及当某个目标节点不可用时如何处理请求。每个请求中Q服务器节点用集群的最q的改变信息更新存根拦截器。比如,一个节点从集群中移除,当每个存Ҏ截器q接CQ何一个激zȝ节点Ӟ都将更新最新的配置信息。所有基于存根的操作对于客户来讲都是透明的,客户端拦截器集群架构如下图所C:
别的JBoss服务Q特别是HTTP WEB服务Q不要求客户端下载Q何东ѝ客L接通过某个通信协议发送请求ƈ接受响应Q比如HTTP协议。这U情况下Q一个负载^衡器用来处理所有的hq将q些hz֏l集中的节炏V负载^衡器通常是集的一部分Q它知道集群配置和恢复策略,客户端只需要知道负载^衡器。负载^衡器架构如下图所C:
负蝲q器架构的一个潜在的问题是负载^衡器是所有请求的唯一入口Q必M证高的可用性?/p>
客户拦截器架构和负蝲q器架构都使用负蝲q{略定由哪一个服务器节点发送一个新的请求。下面描qJBoss AS的负载^衡策略?/p>
JBoss 3.0.x 中有如下两个负蝲q选项可用Q?/p>
Round-Robin (org.jboss.ha.framework.interfaces.RoundRobin)Q每ơ调用被z֏l一个新的节点,W一个节Ҏ随机选择的?/p>
First Available (org.jboss.ha.framework.interfaces.FirstAvailable):Q第一个可用的节点选ؓ主节点,服务于随后每一个调用,主节点的选择是随机的。当集群中的节点发生变化Ӟ因ؓ节点启动或者停止)Q除非当前主节点依然可用Q将重新选择一个可用的节点作ؓ主节炏V每个客L拦截器或负蝲q器独立选择自己的主节点?/p>
JBoss 3.2+ 中增加了一个新的负载^衡选项 "First AvailableIdenticalAllProxies" (org.jboss.ha.framework.interfaces.FirstAvailableIdenticalAllProxies)Q此选项?"First Available" {略有类似的{略Q唯一的区别是选择的主节点被所有的客户端拦截器׃n?/p>
JBoss 3.2 以后的版本中Q?定义?Proxy Family"术语。is defined. A Proxy Family is a set of stub interceptors that all make invocations against the same replicated target. For EJBs for example, all stubs targeting the same EJB in a given cluster belong to the same proxy family. All interceptors of a given family share the same list of target nodes. Each interceptor also has the ability to share arbitrary information with other interceptors of the same family. A use case for the proxy family is give in Section 1.3.1, “Stateless Session Bean in EJB 2.x”.
在一个集中布v应用E序最Ҏ的方式是使用farming服务Q就是将一个应用程序压~文ӞEAR,WAR或SAR)热布|到M个节点的 all/farm/ 目录Q应用程序会自动地复制到集群中的其他节点。如果稍后有新的节点加入Q新节点启动时也会自动从集群中复制应用程序ƈ布v到本地。在集群q行的过E中Q如果从M节点的farm目录U除应用E序Q这个应用程序将首先从本地卸载,然后再从集群的其他节点中卸蝲。应该手动从当前没有q接到集的服务器节点中删除应用E序?/p>
当前存在一个BugQFarm布v服务只能在热布v压羃文g的方式中才能生效。如果你首先放一个应用程序在farm目录Q然后启动服务器Q这个应用程序将不会被检ƈ布v到集中?/p>
在farm目录中只能用压~文Ӟ而不能用展开的目录?/p>
Farming 服务在JBoss AS发布版的all配置集中是缺省启用的Q不需要手动设|。配|文件保存在deploy/deploy.last目录Q如果需要在集群配置中启用farming服务Q创建farm-service.xml文g如下Qƈ拯到JBoss布v目录$JBOSS_HOME/server/your_own_config/deployQ确保在配置中已l启用集服务?/tt>
FarmMemberService MBean 可用的属性如下:
PartitionName 指定集群名字Q缺省gؓ DefaultPartition.
URLs 指定布v器监控布|文件的目录Q如果不存在QMBean创建?"." 表示配置目录Q比?$JBOSS_HOME/server/all/Q?/tt>
ScanPeriod 指定文g夹的扫描周期Q缺省gؓ5000?/p>
Farming 服务?tt>URLDeploymentScanner的扩展,用来扫描deploy目录Q因此在FarmMemberService MBean中可以?tt>URLDeploymentScanner MBean 中定义的所有属性?/tt>
集群环境中,分布式状态管理是集群必须提供的一个关键服务。比如一个有状态的会话Bean应用E序Q会话状态必d所有节点的Bean实例中保持同步,因此不管哪个节点服务hQ客L应该得到同样的会话状态。实体Bean应用E序中,Bean实例必须在集中q行~存以减L据库负蝲。目前JBoss AS中的状态复制和分布式缓存由两种方式提供Q?HASessionState MBean ?JBoss Cache 框架?/p>
HASessionState MBean ZEJB2.X有状态会话Bean和JBoss3.x?.x的HTTP负蝲q器提供会话复制和分布式缓存服务。MBean相关定义?all/deploy/cluster-service.xml 文g中?/p>
JBoss Cache 是一个分布式~存框架Q可以用在Q何应用程序服务器环境Q也可以独立使用Q已l逐渐替换 HASessionState 服务。JBoss AS 整合JBoss Cache 为HTTP会话Q?EJB 3.0 会话和实体Bean,Hibernate持久对象提供~存服务。这些缓存服务都在独立的MBean中定义?/p>
HTTP会话复制用来在你的WEB客户端和集群的节点之间复制状态,那么当某一个节点崩溃时Q集中的其他节点可以恢复。要实现q个目的Q必L行两个步骤:
会话状态复?/p>
h负蝲q
如果使用all配置集启动JBossQ缺省会启用会话状态复制功能,只需要布|你的应用程序,会话状态就已经可以在集中q行复制?/p>
但是负蝲q需要额外的软g支持Q作Z个常用的场景Q我们将描述如何讄Apache和mod_jk。这个功能也可以通过专门的硬件或者其他Y件来实现?/p>
一个负载^衡器跟踪HTTPhQ根据和h兌的会话,军_z֏h到合适的节点。这被称作用sticky-sessions的负载^衡器Q一 旦在某个节点创徏了会话,随后的请求将由同一个节点进行处理。用一个支持sticky-sessions的负载^衡器可以不用复制会话Q没有会话状态复 制的花销Q每个请求将是被同一个节点处理。但是一旦这个节点崩溃,保存在这个节点的所有客户会话都丢失,客户必须dq另一个节点,重新启动一个新的会 话。在某些情况Q不复制HTTP会话是可以接受的Q因为比较关键的状态都保存在数据库中,但是也有些情况下Q丢׃话状态是无法接受的,q种情况下,会话 状态复制的花销是必L受的?/p>
Apache 是一个可以通过插入模块扩展功能的WEB服务器,mod_jkQ最新的mod_jk2Q模块的主要功能是允许从Apache分发hC? Servlet容器Q还可以支持在多个Servlet容器中负载^衡HTTP调用Q遵循sticky-sessionsQ?/p>
?tt>http://httpd.apache.org/ 下蝲Apache,安装是非常直白的Q不需要特别的配置Q推荐?.0.x版本Q这里假定Apache安装目录为APACHE_HOME?/tt>
然后?a >www.apache.org/dist/jakarta/tomcat-connectors/jk/binaries/. 下蝲mod_jk模块Q徏议用mod_jk 1.2.x版本。重命名下蝲的文件ؓmod_jk.soQ拷贝到APACHE_HOME/modules/目录下?/p>
更改APACHE_HOME/conf/httpd.conf 文gQ在文gNd一行:
创徏文gAPACHE_HOME/conf/mod-jk.conf:
java 代码
- # Load mod_jk module
- # Specify the filename of the mod_jk lib
- LoadModule jk_module modules/mod_jk.so
- # Where to find workers.properties
- JkWorkersFile conf/workers.properties
- # Where to put jk logs
- JkLogFile logs/mod_jk.log
- # Set the jk log level [debug/error/info]
- JkLogLevel info
- # Select the log format
- JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
- # JkOptions indicates to send SSK KEY SIZE
- JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
- # JkRequestLogFormat
- JkRequestLogFormat "%w %V %T"
- # Mount your applications
- JkMount /application/* loadbalancer
- # You can use external file for mount points.
- # It will be checked for updates each 60 seconds.
- # The format of the file is: /url=worker
- # /examples/*=loadbalancer
- JkMountFile conf/uriworkermap.properties
- # Add shared memory.
- # This directive is present with 1.2.10 and
- # later versions of mod_jk, and is needed for
- # for load balancing to work properly
- JkShmFile logs/jk.shm
- # Add jkstatus for managing runtime data
- JkMount status
- Order deny,allow
- Deny from all
- Allow from 127.0.0.1
其中有两个设|是非常重要的:
LoadModule 指o必须引用下蝲的mod_jk库,路径中必d括modules前缀?/p>
JkMount 指o通知Apache哪些URL应该被派发给mod_jk模块Q也是z֏lServlet容器Q。上面的配置中,所有基?application/* 的请求都会派发给mod_jk负蝲q器。如果用mod_jk作ؓ一个专门的负蝲q器,可以所有的h(/*)z֏lmod_jk?/tt>
除了使用 JkMount 指oQ也可以使用JkMountFile 指o指定一个配|文Ӟ包含多个URL映射配置。你只需要在APACHE_HOME/conf 目录下创Z?tt>uriworkermap.properties 文g。文件格式ؓ/url=worker_name,CZ文g如下Q?/tt>
java 代码
- # Simple worker configuration file
- # Mount the Servlet context to the ajp13 worker
- /jmx-console=loadbalancer
- /jmx-console/*=loadbalancer
- /web-console=loadbalancer
- /web-console/*=loadbalancer
如上CZ配|?mod_jk z֏h /jmx-console ?tt>/web-console lTomcat?/p>
接着需要创建conf/workers.properties文gQ这个文件用来指定名个不同的Servlet容器的位|以及调用如何在q些容器之间q行q。针对一个两个节点的讄Q示例文件如下:
java 代码
- # Define list of workers that will be used
- # for mapping requests
- worker.list=loadbalancer,status
- # Define Node1
- # modify the host as your host IP or DNS name.
- worker.node1.port=8009
- worker.node1.host=node1.mydomain.com
- worker.node1.type=ajp13
- worker.node1.lbfactor=1
- worker.node1.cachesize=10
- # Define Node2
- # modify the host as your host IP or DNS name.
- worker.node2.port=8009
- worker.node2.host= node2.mydomain.com
- worker.node2.type=ajp13
- worker.node2.lbfactor=1
- worker.node2.cachesize=10
- # Load-balancing behaviour
- worker.loadbalancer.type=lb
- worker.loadbalancer.balance_workers=node1,node2
- worker.loadbalancer.sticky_session=1
- #worker.list=loadbalancer
- # Status worker for managing load balancer
- worker.status.type=status
上述文g配置mod_jk执行Round-Robin的基于sticky-sessions的负载^衡策略,两个节点都监?009端口?/p>
works.properties文g中,每个节点使用worker.XXX 命名规范q行定义Q这?XXX 可以是Q何名字,用来命名Servlet容器。对于每个工作者,必须指定在目标Servlet容器中配|的AJP13q接器的IP地址和端口号?/p>
lbfactor 属性用来表C载^衡权重,军_节点之间的优先QD大,该节点将接受多的请求。这个选项可以用来分配不同的节点不同的负蝲?/p>
cachesize 属性定义关联的Servlet容器的线E池大小Q确定这个值没有超qServlet容器在AJP13q接器中的配|。可以参?a >jakarta.apache.org/tomcat/connectors-doc/config/workers.html
conf/workers.properties 最后定义负载^衡工作者,唯一需要改变的?tt>worker.loadbalancer.balanced_workers 讄Q必d出刚才定义的所有工作者?/p>
sticky_session 属性指定集针对HTTP会话的处理方式,如果指定worker.loadbalancer.sticky_session=0Q每个请求将在两个节点中q行负蝲q。但是当一个用户在某个节点创徏一个会话时Q比较好的方式是随后的请求都导向q个节点Q这被称?/tt>"sticky session"Q由于客hL使用会话创徏的节Ҏ务所有随后的h。否则用L会话数据必须在两个节点进行同步,要启?sticky session"Q必设|?worker.loadbalancer.sticky_session gؓ1?/p>
A non-loadbalanced setup with a single node required the worker.list=node1 entry before mod_jk would function correctly.注意
最后必配|集中所有节点的JBoss Tomcat实例?/p>
在每个节点中Q我们必L据workers.properties文g中的worker名称来命名节炏V比如,在JBoss 实例node1中,需要编?tt>JBOSS_HOME/server/all/deploy/jbossweb-tomcat50.sar/server.xml 文gQ定?元素d一个jvmRoute属性:
然后Q对于集中的每一个节点,我们必须通知它添加一个jvmRoute值到会话cookies中,以便mod_jk可以路由随后的请求。编?JBOSS_HOME/server/all/deploy/jbossweb-tomcat50.sar/META-INF/jboss-service.xml 文gQ定义UseJK的元素,讄gؓtrueQ?/p>
到此为止Q我们已l成功设|Apache_mod_jk使用sticky-session方式的负载^衡?/p>
更多信息可以参?tt>http://wiki.jboss.org/wiki/Wiki.jsp?page=UsingMod_jk1.2WithJBoss?/tt>
目前为止Q已l成功配|了sticky-session方式的负载^衡,但是q种方式q不是一个完善的解决ҎQ因Z个节点崩溃,所有的会话数据都会丢失。更可选的解决方式是在集群的节点之间复制会话状态,q样客户讉KM个节炚w会获得同L会话状态?/p>
jboss.cache:service=TomcatClusteringCache MBean 使用 JBoss Cache提供HTTP会话状态复制服务,q个MBean定义?tt>deploy/tc5-cluster.sar/META-INF/jboss-service.xml 文g中?/p>
JBoss AS 4.0.4 CR2以前的版本,HTTP会话~存配置文g?tt>deploy/tc5-cluster-service.xml文g中?/tt>
下面是一个典型的deploy/tc5-cluster.sar/META-INF/jboss-service.xml 文g
详细的配|请参见JBossCache~存配置部分Q下面讨论几个比较关键的配置Q?/p>
TransactionManagerLookupClass 讄事务理器工厂,~省gؓorg.jboss.cache.BatchModeTransactionManagerLookupQ这个类通知~存不要参与JTA事务Q自q理事务?/tt>
IsolationLevel 讄更新分布式缓存的隔离U别Q可选值包括:SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED, ?NONE?/tt> q里的隔ȝ别和数据库的隔离U别有同L含义Q对于大多数WEB应用E序来讲通常讄?tt>REPEATABLE_READ?/p>
CacheMode 控制~存如何被复制。可选值包括:REPL_SYNC ?tt>REPL_ASYNCQ确定改变是应该同步q是异步复制。用同步复Ӟ保在请求完成之前传播改变,同步复制相对来说会慢一些?/tt>
ClusterName 指定集群名称。缺省的集群名称是由当前的JBoss分区名称加上"Tomcat-"前缀。所有的节点应该使用相同的集名U?/p>
UseMarshalling ?strong>InactiveOnStartup 属性必L相同的|如果使用FIELDU别的会话复Ӟq两个值必Mؓtrue?/p>
ClusterConfig 配置底层的JGoups 堆栈。最重要的配|元素是q播地址和端口号mcast_addr ?tt>mcast_portQ详l配|请参见JGroups配置?/tt>
LockAcquisitionTimeout 讄获取锁的最大超时|~省gؓ15000?/p>
UseReplQueue 使用异步复制时是否启动复刉列,q允许多个更Ch行从而提升性能。复刉列属性由 ReplQueueInterval ?tt>ReplQueueMaxElements 属性配|?/p>
ReplQueueInterval 配置JBoss~存处理复制队列的时间间隔?/p>
ReplQueueMaxElements: 配置复制队列可以保存的最多的元素数目?/p>
要在你的WEB应用E序中启用集,必须在web.xml文g中声明distributable。示例如下:
可以在jboss-web.xml文g中进一步配|会话复ӞCZ如下Q?br />
xml 代码
- <jboss-web>
- <replication-config>
- <replication-trigger>SET_AND_NON_PRIMITIVE_GETreplication-trigger>
- <replication-granularity>SESSIONreplication-granularity>
- <replication-field-batch-mode>truereplication-field-batch-mode>
- replication-config>
- jboss-web>
replication-trigger 元素定什么情况触发一ơ会话复Ӟ有四个选项Q?/p>
SET: 使用此选项Q一个会话只有在讄属性时才被认ؓ需要复制。如果你的应用L需要改变会话的属性,q个选项是性能最优的。如果一个对象只是被索和修改Q但是不需要改写会话,q个对象的改变ƈ不会造成会话复制?/p>
SET_AND_GET: 使用此选项QQ何属性的获取和设|都被认为需要复制。如果一个对象被索和修改Q但是不需要改定会话,q个对象的改变将会被复制。这个选项有显著的性能问题?/p>
SET_AND_NON_PRIMITIVE_GET: 此选项cM?SET_AND_GETQ唯一的例外是只有非原始类型的索操作被认ؓ需要复制。比如,HTTP会话h可以从属性中索一个非原始cd的对象实例ƈ更改Q如果我们没有指定此选项Q更改将不会被复制。这是缺省设|?/p>
ACCESS: 使用此选项Q只要会话被讉K都被认ؓ需要复制。由于每个HTTPh都会造成会话被访问,所以每个请求都会导致会话复制。用此选项Q会话时间戳在集群中同步。注意用此选项会有显著的性能问题?/p>
replication-granularity 元素控制复制_度Q支持的选项包括Q?/p>
SESSION: Z会话的复Ӟ只要会话发生改变Q整个会话对象都会被序列化?/p>
ATTRIBUTE: Z属性的复制Q复制只在属性被认ؓ是脏的时候发生,比如lastAccessTime.。对于持有大量数据的会话Q这个选项可以提升性能?/p>
FIELD: Z字段的复Ӟ复制只在会话属性包含的对象的字D发生变化时发生?/p>
replication-field-batch-mode 表示是否需要在每个HTTPhq行扚w更新Q缺省gؓtrue?/p>
如果你的会话通常比较,SESSION选项比较适合Q如果会话比较大Q而且某些部分不是l常被访问,ATTRIBUTE 选项比较适合Q如果会话属性包含大数据量的对象而且只有字段l常更改QFIELD 选项比较适合?/p>
FIELD-level replication only replicates modified data fields inside objects stored in the session. It could potentially drastically reduce the data traffic between clustered nodes, and hence improve the performance of the whole cluster. To use FIELD-level replication, you have to first prepare your Java class to indicate which fields are to be replicated. This is done via JDK 1.4 style annotations embedded in JavaDocs:
To annotate your POJO, we provide two annotations: @@org.jboss.web.tomcat.tc5.session.AopMarker and @@org.jboss.web.tomcat.tc5.session.InstanceAopMarker. When you annotate your class with AopMarker, you indicate that instances of this class will be used in FIELD-level replication. For exmaple,
/*
* My usual comments here first.
* @@org.jboss.web.tomcat.tc5.session.AopMarker
*/
public class Address
{
...
}
If you annotate it with InstanceAopMarker instead, then all of its sub-class will be automatically annotated as well. For example,
/*
*
* @@org.jboss.web.tomcat.tc5.session.InstanceOfAopMarker
*/
public class Person
{
...
}
then when you have a sub-class like
public class Student extends Person
{
...
}
there will be no need to annotate Student. It will be annotated automatically because it is a sub-class of Person.
However, since we only support JDK 1.4 style annotation (provided by JBoss Aop) now, you will need to perform a pre-processing step. You need to use the JBoss AOP pre-compiler annotationc and post-compiler aopc to process the above source code before and after they are compiled by the Java compiler. Here is an example on how to invoke those commands from command line.
$ annotationc [classpath] [source files or directories]
$ javac -cp [classpath] [source files or directories]
$ aopc [classpath] [class files or directories]
Please see the JBoss AOP documentation for the usage of the pre- and post-compiler. The JBoss AOP project also provides easy to use ANT tasks to help integrate those steps into your application build process. In the next AS release, JDK 5.0 annotation support will be provided for greater transparency. But for now, it is important that you perform the pre- and post-compilation steps for your source code.
Or, you can see a complete example on how to build, deploy, and validate a FIELD-level replicated web application from this page: http://wiki.jboss.org/wiki/Wiki.jsp?page=Http_session_field_level_example. The example bundles the pre- and post-compile tools so you do not need to download JBoss AOP separately.
When you deploy the web application into JBoss AS, make sure that the following configurations are correct:
In the server's deploy/tc5-cluster.sar/META-INF/jboss-service.xml file, the inactiveOnStartup and useMarshalling attributes must both be true.
In the application's jboss-web.xml file, the replication-granularity attribute must be FIELD.
Finally, let's see an example on how to use FIELD-level replication on those data classes. Notice that there is no need to call session.setAttribute() after you make changes to the data object, and all changes to the fields are automatically replicated across the cluster.
<pre class="programlistin