1 概述
应用的合理部署即能提高系统的可靠性和稳定性,又能提高系统的可维护性和扩展性。本文档详细阐述基于Apache负载均衡和JBOSS7集群的应用系统部署方案和配置步骤。内容涉及部署方案、环境配置、方案特性。
2 安装步骤
介绍支持以上设计方案所需的各个相关软件的版本信息及针对以上方案在实施时的详细配置过程。
2.1 安装准备
2.1.1 版本列表
功能模块 |
版本 |
下载 |
JAVA |
jdk-6u45-linux-x64.bin (注:64位) |
|
负载均衡 |
Apache2.2.25 (依赖:apr-1.4.8.tar.gz apr-util-1.5.2.tar.gz) |
http://httpd.apache.org/download.cgi |
mod_jk-1.2.31-httpd-2.2.x.so (注:64位) |
http://archive.apache.org/dist/tomcat/tomcat-connectors/jk/binaries/linux/jk-1.2.31/ |
|
集群 |
jboss-eap-6.2.0.zip |
http://www.jboss.org/jbossas/downloads/ |
2.1.2 安装注意事项
1) 安装前请先确认操作系统是64位
查看命令:echo $HOSTTYPE
说明:后面是X686或X86_64则内核是64位的,i686或i386则内核是32位的
2) JDK安装包必须为64位
查看命令:java -version
说明:如果是64位的则会显示Java HotSpot<TM>64-Bit 字样,32位的则没有类似信息
3) JBOSS使用官方推荐安装包jboss-eap-6.2.0.zip
2.2 JDK安装
Linux系统自带了jdk,但还是1.4的老版本,所以需要先卸载,然后在安装1.6,卸载步骤如下:
[[email protected]t ~]# rpm -qa | grep jdk
[[email protected] ~]# rpm -qa | grep gcj
libgcj-4.1.2-42.el5
java-1.4.2-gcj-compat-1.4.2.0-40jpp.115
上面先确认jdk的具体版本号,然后
[[email protected] ~]# yum -y remove java-1.4.2-gcj-compat-1.4.2.0-40jpp.115
1) 解压jdk安装包
./
jdk-6u45-linux-x64.bin
2) etc/profile最后加入
JAVA_HOME=/prog/jdk/jdk1.6.0_45 PATH=$JAVA_HOME/bin:$PATH set CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export JAVA_HOME export PATH export CLASSPATH |
3) 测试
命令行输入java –version,如果显示当前版本,则JDK安装成功。
2.3 APACHE安装
1) 进入到安装程序所在目录,执行以下命令对其进行解压缩
tar -zxvf httpd-2.2.25.tar.gz
在同级目录下会生成 httpd-2.2.25 文件,执行以下命令创建一个新的目录来存放将要安装的apache软件
mkdir –p /usr/local/web/apache2.2/
执行以下命令将生成的源码文件移动到其他目录,便于管理
mv httpd-2.2.25 /usr/local/src/
进入到src目录,再进入到httpd-2.2.25目录执行以下命令进行安装前的配置
./configure --prefix=/usr/local/web/apache2.2 --enable-so --enable-mods-shared=most --enable-rewrite
2) 如果上述过程报错依赖apr与apr-util,则首先安装apr与apr-util;如果无报错,则忽略
[[email protected] 52lamp]# cd apr-1.4.8 [[email protected] apr-1.4.8]# ./configure [[email protected] apr-1.4.8]# make [[email protected] apr-1.4.8]# make install |
Apr-util安装与上述完全相同。
3) Apr与apr-util安装完毕后重新执行configure、make、make install
#./configure --prefix=/usr/local/web/apache2.2 --enable-so --enable-mods-shared=most --enable-rewrite --with-apr=/usr/local/apr/ --with-apr-util=/usr/local/apr-util/ #make #make install |
4) 执行 service httpd start 命令,看是否能够启动apache 如果不能启动并提示httpd unrecognized service则是apache没有配置成系统服务
5) 将apache配置成系统服务
cp /usr/local/web/apache/bin/apachectl /etc/rc.d/init.d/httpd
vi /etc/rc.d/init.d/httpd
当httpd文档打开后,在#!/bin/sh 内容下面添加以下内容(含#符号的)
# chkconfig: 2345 90 90
# description: Activates/Deactivates Apache Web Server
添加完成后,保存并退出到命令模式,输入以下命令将apache添加到系统服务
chkconfig --add httpd
chkconfig --level 345 httpd on
6) 测试
命令行输入 service httpd start
然后打开浏览器访问http://localhost出现it works.
Apache安装结束。
2.4 JBOSS安装
2.4.1 JBoss-eap-6.2简单介绍
Jboss-eap-6.2是基于jboss as 7的企业级版本,JBoss AS7新加入了域(domain)的概念并实现了相关功能。域的提出及实现,其目的是使得多台JBoss AS服务器的配置可以集中于一点,统一配置、统一部署,从而在管理多台JBoss AS服务器时,实现集中管理。
域的目的则是将多台服务器组成一个服务器组(Server Group),并为一个服务器组内的多台主机(Host)提供:
* 单点集中配置(通过一个域控制器,即Domain Controller,实现组内主机的统一配置)。
* 单点统一部署,通过域控制器将项目一次部署至组内全部主机。
简单来讲,群集的目标是让多台服务器分摊压力,当一台或多台服务器当机时,服务可以继续保持运转;而域的目标则是提供集中配置和管理多台服务器的能力。在没有域的概念时,要想让群集内的多台服务器或几组服务器保持统一的配置,一个一个分别的去手工维护,是非常麻烦的事情,而域的引入解决了这一问题。
2.4.2 准备工作
现在两台电脑的IP分别为10.0.1.3及10.0.1.18,分别运行JBoss AS7,并组成一个服务器组(Server Group)。其中,使用10.0.1.3这台机器做为域控制器(Domain Controller):
如上图所示,两台主机分别被命名为”master“及”slave“。通过配置,将master与slave组成一个服务器组,其中master将做为这个服务器组的域控制器。
需要说明一点的是,服务器组(Server Group)可以由多台服务器(Host)组成,并不一定只有两台,所以不要被master及slave这样的名字给迷惑了,以为一个服务器组仅支持一主一从两台hosts。本文中因为只使用两台服务器做实验,因此出于方便角度将它们分别命名为master及slave。此外,在一个服务器组中,只有一台域控制器,在本实验中我们将使用master这台机器做为domain controller。
2.4.3 Domain Controller配置
1) 在domain controller一段创建一个Management User,具体到JBOSS_HOME/bin目录下执行add-user.sh
[[email protected] bin]$ ./add-user.sh What type of user do you wish to add? a) Management User (mgmt-users.properties) b) Application User (application-users.properties) (a): Enter the details of the new user to add. Realm (ManagementRealm) : Username : admin123 Password :admin111_ Re-enter Password :admin111_ About to add user ‘admin123‘ for realm ‘ManagementRealm‘ Is this correct yes/no? yes Added user ‘admin123‘ to file ‘/home/kylin/work/./standalone/configuration/mgmt-users.properties‘ Added user ‘admin123‘ to file ‘/home/kylin/work/./domain/configuration/mgmt-users.properties‘ Is this new user going to be used for one AS process to connect to another AS process? e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls. yes/no? yes To represent the user add the following to the server-identities definition <secret value="YWRtaW4xMTFf=" /> |
2) JBOSS_HOME/domain/configuration/host.xml中,删除servers,表示这台主机只用来做域控制器,不用于发布server,jboss已经为我们提供了对应的配置文件便于参考,即JBOSS_HOME/domain/configuration/host-master.xml
3) Domain.xml中< hornetq-server>节点加入<security-enabled>false</security-enabled>
<hornetq-server> <security-enabled>false</security-enabled> … </hornetq-server> |
4) 测试
运行/bin/domain.sh,然后浏览器中输入http://localhost:9990/ ,输入用户、密码(刚才add-user.sh配置的),即可进入Domain管理界面
2.4.4 Host Controller配置
1) 因为Slave这台机器不作为域控制器而存在,删除domain/configuration/domain.xml文件
2) 同样jboss已经为我们提供了对应的配置文件便于参考,即JBOSS_HOME/domain/configuration/host-slave.xml,打开host.xml,修改<domain-controller>部分内容如下:
<domain-controller> <remote host="10.0.1.3" port="9999" username=”admin123” security-realm="ManagementRealm"/> </domain-controller> |
3) 修改 <security-realm name="ManagementRealm">如下
<security-realm name="ManagementRealm"> <server-identities> <secret value="YWRtaW4xMTFf="/> </server-identities> <authentication> <properties path="mgmt-users.properties" relative-to="jboss.domain.config.dir"/> </authentication> </security-realm> |
注意事项:密码值为admin123用户对应密码的BASE64编码值,同时加上’=’结尾。
编码值可以使用网上在线工具查看。
4) 确保host名字唯一
<host name="slave1" |
5) 确保server的名字唯一,并修改端口,递增数为150或100(这是端口偏移量,jboss默认http端口是8080,这样以后访问具体的server,如果server1的端口偏移量是150,则端口就是8230)
<servers> <server name="server1" group="other-server-group" auto-start="false"> <socket-bindings port-offset="150"/> </server> </servers> |
6) 运行domain.sh测试
访问http://localhost:8230,进入JBOSS页面即OK。启动成功的话,应该可以在master上面看到日志,slave被成功的注册进来。
2.4.5 应用部署
1) 访问控制台http://10.0.1.3:9990/,在Runtime标签页下左侧,点击Manage Deployments, 进入部署功能页面:
2) 此时点击右边的"Add "功能,将ShoppingCart.war添加进Content Repository(域控制器用于保存待部署资源的目录)。
3) 然后点击"Assign"将ShoppingCart.war添加至 "other-server-group",并将其enable
注意:这里有一点值得注意的是,jboss-eap-6.2默认设置了两个server group分别是:main-server-group和other-server-group,但是这两个组是有区别的main-server-group使用的默认profile和socket是full,而other-server-group使用的默认profile和socket是full-ha,然而在jboss-eap-6.2的四种profile中只有ha和full-ha支持集群的multicast协议,这一点可以在domain/configuration/domain.xml里面看到,而且jboss-eap-6.2官方文档也有指出,如下图:
所以在对应用分配组(Assign)的时候,如果该应用最终访问方式是要通过apache服务器来分发请求访问,那就不要分配给main-server-group,否则最终发布的时候,通过apache默认端口访问的结果要么出现404,要么503.如果非要分配给main-server-group,则需要修改它默认的profile和socket为:ha或者full-ha.
2.5 集群配置
2.5.1 Apache mod_jk配置【必须】
1) 将下载的 mod_jk-1.2.31-httpd-2.2.x.so 文件改名为mod_jk.so
2) 将mod_jk.so 文件复制到 APACHE_HOME/modules/目录下
3) 打开APACHE_HOME/conf/httpd.conf 在文件最后添加以下内容后保存
# module mod_jk config file
Include conf/mod_jk.conf
4) 进入APACHE_HOME/conf/目录中,新建mod_jk.conf
#load module mod_jk-1.2.31-httpd-2.2.3.so is for Apache 2.2.x. LoadModule jk_module modules/mod_jk.so #配置 mod_jk conf #加载集群中的workers JkWorkersFile conf/workers.properties #加载workers的请求处理分配文件 JkMountFile conf/uriworkermap.properties #指定jk的日志输出文件 JkLogFile logs/mod_jk.log #指定日志级别 JkLogLevel info |
5) 进入APACHE_HOME/conf/目录,新建workers.properties
# worker列表 worker.list=node_lb,jkstatus #配置实例节点1 worker.node1.host=10.0.0.18 worker.node1.port=8009 worker.node1.type=ajp13 ----对于mod_jk,jboss仅支持ajp13协议 worker.node1.lbfactor=1 #配置实例节点2 worker.node2.host=10.0.0.18 worker.node2.port=8159 ----8009+150的偏移量 worker.node2.type=ajp13 worker.node2.lbfactor=1 worker.node_lb.type=lb worker.node_lb.retries=3 worker.node_lb.balance_workers=node1,node2 worker.node_lb.sticky_session=true ----粘性session,非粘性只需改成false即可 #worker.node_lb.sticky_session_force=false worker.jkstatus.type=status |
6) 进入APACHE_HOME/conf/目录中,新建uriworkermap.properties
#所有请求都由LB_worker这个worker处理 /*=node_lb #所有包含jkstatus请求的都由名称叫jkstatus的这个worker处理 /jkstatus =jkstatus /jkstatus/* =jkstatus |
7) 测试
重新启动apache,首先进入http://localhost:9990部署ShoppingCart.war
访问http://localhost/ShoppingCart进行测试
2.5.2 jvmRoute配置【必须】
给 jboss每个host配置apache mod_jk的分发路由
<system-properties> <property name="org.apache.catalina.connector.URI_ENCODING" value="UTF-8"/> </system-properties> |
2.5.3 Apache反向代理配置
Apache mod_proxy跟mod_jk功能类似,也具有整合负载均衡的能力,当服务搭建在一台内网机器上,通过外网机器的80端口映射内网的8080端口进行访问。由于可对外暴露的端口只有被映射的一个8080端口,这时可以使用mod_proxy进行反向代理配置。
1) 首先httpd.conf配置中需要启用Apache的几个模块
LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_balancer_module modules/mod_proxy_balancer.so LoadModule proxy_http_module modules/mod_proxy_http.so |
2) httpd.conf中打开httpd-vhosts.conf注释,这是反向代理配置文件,如果没有,需要自行添加如下:
# Virtual hosts
Include conf/httpd-vhosts.conf
3) 修改apache80监听端口为8080
在httpd.conf配置文件中查找listen 80 改成8080 即可。
4) 编辑httpd-vhosts.conf
# # Virtual Hosts # # If you want to maintain multiple domains/hostnames on your # machine you can setup VirtualHost containers for them. Most configurations # use only name-based virtual hosts so the server doesn‘t need to worry about # IP addresses. This is indicated by the asterisks in the directives below. # # Please see the documentation at # <URL:http://httpd.apache.org/docs/2.2/vhosts/> # for further details before you try to setup virtual hosts. # # You may use the command line option ‘-S‘ to verify your virtual host # configuration. # # Use name-based virtual hosting. # NameVirtualHost *:8080 # # VirtualHost example: # Almost any Apache directive may go into a VirtualHost container. # The first VirtualHost section is used for all requests that do not # match a ServerName or ServerAlias in any <VirtualHost> block. # RewriteEngine On Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; " env=BALANCER_ROUTE_CHANGED #建立虚拟主机来作为负载均衡 <Proxy balancer://main_cluster> Order deny,allow Allow from all BalancerMember ajp://172.16.3.136:8109 route=slave1:cks-main ProxySet stickysession=ROUTEID </Proxy> <Proxy balancer://report_cluster> Order deny,allow Allow from all BalancerMember ajp://172.16.3.136:8209 route=slave1:WebReport ProxySet stickysession=ROUTEID </Proxy> <VirtualHost *:8080> Timeout 7200 ProxyRequests Off # ProxyPassReverseCookiePath / / ProxyPass /cks-main balancer://main_cluster/cks-main ProxyPassReverse /cks-main balancer://main_cluster/cks-main ProxyPass /WebReport balancer://report_cluster/WebReport ProxyPassReverse /WebReport balancer://report_cluster/WebReport ProxyPreserveHost On #KeepAliveTimeout 500 #MaxKeepAliveRequests 200 </VirtualHost> |
5) 最后重启apache
service httpd restart
6) 测试
http://172.16.3.136:8080/cks-main
http://172.16.3.136:8080/WebReport/ReportServer
2.6 Session管理
2.6.1 session复制
session同步除了上述的sticky模式,还可以通过session复制实现。要实现session复制只需要在项目的web.xml里面加入<distributable />标签即可。不过session复制会导致应用服务器性能下降,所以要慎用。
官方文档:
2.6.2 统一管理session
如何通过一种session管理策略,确保集群某一个结点失效后,其session数据能由其他结点获取以便其他结点接替失效结点,实现集群的容错(failover),对于这个问题,多数的应该服务器(包括Tomcat在内)使用的是session复制(session replication)机制,即结点之间通过组播方式将各自的session发到其他所有结点上,如果其中一个访问出错,则另外结点仍然具有有效的session内容,从而能正常接管其session。由于服务器内置了session复制机制的实现,因而使用这种方案非常简单,只需要做简单的配置即可完成,但是其缺点也是很明显的,由于大量的session信息需要复制,在用户数量和集群数量达到一定规模后,session复制就有可能成为性能瓶颈。
session共享的另一种思路就是采用memcached。使用memcached来存储session可以通过自己编写filter实现.
主要思路:
(1)继承重构HttpServletRequestWrapper,HttpSessionWrapper类,覆盖原来和session存取相关的方法呢,都通过SessionService类来实现.
(2)使用filter拦截cookie中的sessionId,通过sessionId构造新的HttpServletRequestWrapper对象,传给后面的应用.
(3)SessionService连接memcached服务,以sessionId作为key,存取的对象是一个map.map的内容即为session的内容.
Demo请看:附件
使用过程注意几个问题和改进思路:
1、memcache的内存应该足够大,这样不会出现用户session从Cache中被清除的问题(可以关闭memcached的对象退出机制)。
2、如果session的读取比写入要多很多,可以在memcache前再加一个Oscache等本地缓存,减少对memcache的读操作,从而减小网络开销,提高性能。
3、如果用户非常多,可以使用memcached组,通过set方法中带hashCode,插入到某个memcached服务器
对于session的清除有几种方案:
(1)可以在凌晨人最少的时候,对memcached做一次清空。(简单)
(2)保存在缓存中的对象设置一个失效时间,通过过滤器获取sessionId的值,定期刷新memcached中的对象.长时间没有被刷新的对象自动被清除.(相对复杂,消耗资源)
2.7 JBOSS后台启动、关闭、重启
2.7.1 启动
nohup ./domain.sh &
运行日志可以查看domain.sh对应目录下的nohup.out
2.7.2 关闭
正常退出可以使用jboss提供的./jboss-cli.sh来连接后台裕兴的domain.sh,步骤:
./jboss-cli.sh
connect
:shutdown
可以参考官方文档,如下:
当然,如果以上方法无法奏效,那只能使用强行杀进程了:
ps aux | grep java 查PID
kill –s 9 PID
2.7.3 重启
重启跟关闭采用同样的方式命令为:
:reload
2.8 JVM参数配置
设置位置:bin/domain.conf
2.8.1 内存设置
参考大小:
bin\domain.conf中
if [ "x$JAVA_OPTS" = "x" ]; then
JAVA_OPTS="-Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true
或者:
可以对具体的server进行内存设置,如下:
2.8.2 GC设置
GC文件名为日期+时间,以便进行GC性能跟踪。
bin\domain.conf中
if [ "x$JAVA_OPTS" = "x" ]; then
JAVA_OPTS="-Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -verbose:gc -Xloggc:/prog/gc/`date +%Y%m%d__%H%M%S`.out -XX:+PrintGCTimeStamps -XX:+PrintGCDetails
"
2.8.3 jboss线程数配置
\domain\configuration\domain.xml
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" max-connections="1000"/>
2.8.4 jboss请求日志配置
\domain\configuration\domain.xml中
<subsystem xmlns="urn:jboss:domain:web:1.4" default-virtual-server="default-host" native="false"> <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" max-connections="1000"/> <virtual-server name="default-host" enable-welcome-root="true"> <alias name="localhost"/> <alias name="example.com"/> <access-log pattern="%a %t %H %p %U %s %T" > <directory relative-to="jboss.server.log.dir" /> </access-log> </virtual-server> </subsystem> |
pattern的详细说明
%a 远端IP
%A 本地IP
%b 发送的字节数,不包含HTTP头,如果为0,使用”-”
%B 发送的字节数,不包含HTTP头
%h 远端主机名(如果resolveHosts=false),远端的IP
%H 请求协议
%l 从identd返回的远端逻辑用户名,总是返回’-’
%m 请求的方法
%p 收到请求的本地端口号
%q 查询字符串
%r 请求的第一行
%s 响应的状态码
%S 用户的sessionID
%t 日志和时间,使用通常的log格式
%u 认证以后的远端用户(如果存在的话,否则为’-’)
%U 请求的URI路径
%v 本地服务器的名称
%D 处理请求的时间,以毫秒为单位
%T 处理请求的时间,以秒为单位
2.8.5 jboss请求响应时间配置
默认响应超时时间为60秒
注:7.1.1不支持此设置,7.1.2支持此设置
\domain\configuration\domain.xml中
org.apache.coyote.http11.DEFAULT_CONNECTION_TIMEOUT system property. <system-properties> <property name="org.apache.coyote.http11.DEFAULT_CONNECTION_TIMEOUT" value="600000"> </system-properties> |
3 方案特性
3.1 高性能
Ø 基于负载均衡的请求分发,快速响应客户端请求
Ø 多应用系统实例支持,降低应用系统压力
3.2 隔离性
Ø 物理主机硬件隔离,提供稳定可靠的服务
Ø 应用软件部署隔离,即可独立服务又可集群共享
3.3 可靠性
Ø 应用负载均衡,降低应用系统故障频率及宕机风险
Ø 单个应用故障,其他应用可接管服务
3.4 伸缩性
Ø 可方便扩充硬件设备,满足业务扩展需求
Ø 可方便应用实例扩充、部署等变更需求
4 参考文档
https://docs.jboss.org/author/display/AS71/AS7+Cluster+Howto
https://docs.jboss.org/author/display/AS71/Using+mod_jk+with+JBoss+AS7
http://www.jbossauthority.com/jboss-eap-6-extensions-subsystems-and-profiles/