概述
一个
集群
系统是一群松散结合的服务器组,形成一个虚拟的服务器,为客户端用户提供统一的服务。对于这个客户端来说,通常在访问
集群
系统时不会意识到它的服务是由具体的哪一台服务器提供。
集群
系统一般应具高
可用性
、
可伸缩性
、
负载均衡
、故障恢复和可维护性等特殊性能。越来越多的关键任务和大型应用正运行在
J2EE
平台上,象银行之类的应用要求很高的可用性
(HA)
,大型系统比如大型网站则要求更好的伸缩性。
J2EE
集群是最常用的技术,用来提供高可用性和伸缩性的容错服务,单机部署和多机集群化部署差别很大,网上的资料大多语焉不详,即使文档图文并茂,也是到了关键处就部署成功,其实后面还要做些工作才行,且多以单机部署多个
server
来模拟集群化部署,其实和真正多机部署还是有比较大的差别。本文仅以
weblogic
应用服务器为例说明集群化部署。
集群层次说明
Web
级集群,
是
J2EE
集群中最重要和基础的功能。
web
层集群技术包括:
Web
负载均衡和
HTTPSession
失效转移。
web
负载均衡,基本的是在浏览器和
web
服务器之间放置负载均衡器。
应用级集群,是
ejb
集群,
EJB
是
J2EE
应用平台的核心,
EJB
是用于开发和部署具多层结构的、分布式的、面向对象的
Java
应用系统跨平台的构件体系结构。
主要是业务应用,部署在
EJB
容器上。
数据库级集群,是
oracle
数据库设置多个数据库实例,全部映射到数据库。
Weblogic集群概念
Ø
Domain
:由配置为
Administrator Server
的
WebLogic Server
实例管理的逻辑单元,这个单元是有所有相关资源的集合。
Ø
Server
:
一个相对独立的,为实现某些特定功能而结合在一起的单元。按功能可分为
domain server
和
managed server
。一个
Domain
可以包含一个或多个
WebLogic Server
实例,甚至是
Server
集群。一个
Domain
中有一个且只能有一个
Server
担任管理
Server
的功能,其它的
Server
具体实现一个特定的逻辑功能。
Ø
Domain Server
:在一个集群中,有且仅有一个
domain server
,即管理
server
,该
server
只负责管理多个
Managed server
(被管理
server
),即
domain server
仅仅是行政领导,考勤之类的活动,如某个
managed Sever
的状态,是未知(
unKnown
),还是运行(
run
),还是停止(
shutdown
),远程启动等等,不负责具体业务。因此部署时
domain server
上不要部署具体任务,毕竟人家是当官的吗。
Ø
Managed Server
:真正的实干家,部署具体的应用。
应用及业务逻辑组件被分发在多个受管服务器(
Managed Server
)。
Weblogic集群要求
Ø
集群中的所有
Server
必须位于同一网段,并且必须是
IP
广播
(UDP)
可到达的
Ø
集群中的所有
Server
必须使用相同的版本
,
包括
Service Pack
Ø
集群中的
Server
必须使用永久的静态
IP
地址。动态
IP
地址分配不能用于集群环境。如果服务器位于防火墙后面,而客户机位于防火墙外面,那么服务器必须有公共的静态
IP
地址,只有这样,客户端才能访问服务器
Ø
使用
weblogic
的支持集群的
licence
项目实战
项目概况
我们的项目是
struts―ejb―hibernate―spring
,因为
hibernate
和
spring
都必须进行初始化且初始化都依赖于
servlet
,在系统启动时就初始化数据,并且我们在
web
层和
ejb
层分别部署为
web
集群和
ejb
集群,而
hibernate
和
spring
都部署在应用服务器上。为此,我们打了两个部署包,一个是
cnlife.war, cnlife_app.ear
,其中
cnlife.war
包部署在
web
集群上,
cnlife
_app.ear
部署在
ejb
集群上,
cnlife_app.ear
包括两个包,其中一个是
cnlifeejb.jar
(
ejb
包),
另外一个是
backgroudinit.war
,
backgroudinit.war
用来初始化
spring
,
hibernate
的初始化数据。
cnlife.war (
部署在
Web Server)
_backgroudinit.war
|
cnlife_app.ear-|
(部署在
Application Server
)
|_cnlifeejb.jar
Ejb
是
stateless Session bean
,使用
ejb
的目的就是应用服务器集群,部署示意图如下:
Web级集群
Web集群中使用内存复制策略
weblogic.xml 如下
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application
8.1//EN" "[url]http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd[/url]">
<weblogic-web-app>
<session-descriptor>
<session-param> <param-name>PersistentStoreType</param-name>
<param-value>replicated</param-value> </session-param>
</session-descriptor>
</weblogic-web-app>
使用JNDI连接EJB集群
Web集群使用JNDI连接EJB集群时,首先在初始化context时,使用如下方式
public static final String PROVIDER_URL = "t3://10.10.21.13,10.10.21.14:8001";
其中10.10.21.13,10.10.21.14是集群中EJB集群中的Management Server地址。
Managed server使用不同端口号,“t3://node1:7001,node2:7002,node3:7003”
Weblogic Proxy
Web集群使用JNDI连接EJB集群时Web级集群负载均衡器,可以使用硬件(如交换机),
专门的负载均衡器(如aparche的负载均衡器),我们使用weblogic的软件均衡器,
该均衡器除了负载均衡外,还有失效处理机制。
Weblogic.xml
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//
DTD Web Application 8.1//EN" "http://www.bea.com/servers/wls810/dtd/
weblogic810-web-jar.dtd">
<weblogic-web-app>
<context-root>/</context-root>
</weblogic-web-app>
Web.xml
!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//
DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>HttpClusterServlet</servlet-name>
<servlet-class>
weblogic.servlet.proxy.HttpClusterServlet
</servlet-class>
<init-param>
<param-name>WebLogicCluster</param-name>
<param-value>
10.10.21
.13:8001|10.10.21.14:8001
</param-value>
</init-param>
<init-param>
<param-name>DebugConfigInfo</param-name>
<param-value>ON</param-value>
</init-param>
<init-param>
<param-name>verbose</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>HttpClusterServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>HttpClusterServlet</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>HttpClusterServlet</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>HttpClusterServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
其中“
10.10.21
.13:8001|10.10.21.14: 8001 ” 表示用作web集群中的机器地址及端口,用竖线分开。
EJB级集群
设置集群地址
设置集群地址,其中的ip地址为managed server的地址和端口号,
多个managed server使用“,”隔开。
Hibernate配置文件设置数据源
使用
weblogic
连接池配置
hibernate
配置文件:
(
片断
)
,其中
mypool
是数据源的
JNDI
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="hibernate.connection.datasource">mypool</property>
<property name="hibernate.connection.provider_class">org.hibernate.connection.
DatasourceConnectionProvider</property>
<property name="hibernate.session_factory_name">hibernate.session_factory</property>
<property name="hibernate.jndi.class">weblogic.jndi.WLInitialContextFactory</property>
<property name="hibernate.jndi.url">t3://localhost:7001/</property>
<property name="hibernate.jdbc.fetch_size">50</property>
<property name="hibernate.jdbc.batch_size">25</property>
<property name="show_sql">true</property>
WebLogic EJB JNDI注意事项
JNDI
表示必须使用“
.
”隔开,在单机上使用“
/
”也可以,但在集群中不要使用“
/
”
<weblogic-enterprise-bean>
<ejb-name>DestroyAccountEJB</ejb-name>
<jndi-name>account.DestroyAccountEJB</jndi-name>
</weblogic-enterprise-bean>
J2EE集群项目部署
Weblogic集群配置domain
在linux(windows)的部署cluster,然后把配置的相关东西copy到cluster的其他liunx(windows)机器上,
copy内容是user_project(含user_project)下面的所有内容。
Weblogic集群启动
启动时,为了启动后管理服务器能够监控其他被管理服务器,首先启动domain server
启动domain server
./startWebLogic.sh �CDweblogic.management.discover=true �CDweblogic.management.
discover.interval=10 �CDweblogic.management.discover.retries=20
启动 managed server
./startManagedWebLogic.sh m1 [url]http://10.10.21.13:7001[/url]
其中m1是集群中某个managed server 名称,
[url]http://10.10.21.13:7001[/url]是集群中管理服务器(domain server)的地址及端口,
注意启动这个命令必须在managed server所在的机器。
Weblogic部署应用
部署时必须部署到cluster,不能包括domain server,设置Cluster address :
10.10.21.13:8001,10.10.21.14:8001,在配置ejb集群中,设置集群地址,
其中的ip地址为managed server的地址和端口号,多个managed server使用“,”隔开。
配置数据库连接失效恢复
当数据库失败或重启,或者网络中断,则数据库连接就是非法的,
当网络或数据库都恢复正常后,需要重启应用服务器,另外一个办法:
在weblogic的console中选中你的连接池--〉connections--〉下面有Advanced Options,点击Show,
选中Test Released Connections, “Specifies whether WebLogic Server tests a connection before returning it to
this JDBC connection pool. (You must specify a Test Table Name.) ”另外看下面Test Table Name
是否有 “SQL SELECT 1 FROM DUAL”
J2EE集群项目开发
序列化
EJB
中的所有方法,不管是返回值还是参数,都必须是可序列化的,返回值和参数对象保证对象中的每个域都可以被序列化。
HttpSession
Session
中的数据必须可以被序列化,如果
Session
中包含对象,需要保证对象中的每个域都可以被序列化;
Session
中如能放入太多的东西,因为
Session
复制时,序列化和反序列化会造成信息消耗,
Session
太大,也会影响同时在线人数的数量。
缓存
需要关闭
Hibernate
的二级缓存
静态变量
在我们的系统中存在静态常量。类似静态变量的需求都设计到数据库表中,在程序中需要改变或者使用该变量,直接操作数据库即可。
可变的配置文件处理
对于系统中需要操作可变的配置文件(内容经常改变),设计成数据库表的
blob
字段来存储在数据库表中,
上传和下载文件处理
类似可变的配置文件处理,可以放到
blob
字段中,也可以在数据库所在服务器上,开共享磁盘空间,把上传或下载的文件放在共享磁盘空间内。
集群开发释疑
1)
单例模式,有许多网上的文章都说要在集群开发时避免单例模式,其实是没有必要的,当系统切换时,如果系统本身有这个类的实例,则会运行初始化方法进行实例化。
2)
配置文件,配置文件作为系统参数,在系统运行的过程中也是不变的,所以当在集群部署时,该配置文件的读取并初始化系统参数,集群中所有机器都会初始化该参数,所以机器切换过程中也不会有什么问题
3)
静态常量,在系统机器切换中,每个机器的静态常量都完全相同,所以都不会有什么问题。
书写规则是:
Managed server使用相同端口号,“t3://acme1,acme2,acme3:7001”