最近在开发的项目需要承受很高的并发量。综合各种情况,决定使用Apache+Tomcat+JK的方式实现负载均衡,并且作为一个统一的服务还要实现群集(同步Session)。
在网上找了很多资料,都是零零散散的,没有一个完整的过程。通过几天的努力,完成了从编译、部署到配置的整个过程,期间也遇到了一些问题。在接下来的文字中将这些过程记录下来,做个笔记同时也分享给大家。
为了重新演示整个过程,我新搭建了一个服务器,各项参数如下:
CPU:Intel Xeon 5110
内存:DDR2 1G*4
主机型号:ProLiant DL140 G3
操作系统:Red Hat Enterprise Linux Server release 5.4 x86_64版
内核版本:2.6.18
gcc版本:4.1.2
g++版本:4.1.2
java版本:1.6.0_27
- [root@lxp2 ~]# cat /etc/redhat-release
- Red Hat Enterprise Linux Server release 5.4 (Tikanga)
- [root@lxp2 ~]# uname -a
- Linux lxp2 2.6.18-164.el5xen #1 SMP Thu Sep 3 04:41:04 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
- [root@lxp2 ~]# gcc --version
- gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)
- Copyright (C) 2006 Free Software Foundation, Inc.
- This is free software; see the source for copying conditions. There is NO
- warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- [root@lxp2 ~]# g++ --version
- g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)
- Copyright (C) 2006 Free Software Foundation, Inc.
- This is free software; see the source for copying conditions. There is NO
- warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- [root@lxp2 ~]# java -version
- java version "1.6.0_27"
- Java(TM) SE Runtime Environment (build 1.6.0_27-b07)
- Java HotSpot(TM) 64-Bit Server VM (build 20.2-b06, mixed mode)
- [root@lxp2 ~]#
gcc、g++和java是必须的,如果运行上述命令提示command not found,则需要安装。具体安装方法这里不做介绍,请参阅相关文档。
接下来要准备的是apache服务器、tomcat服务器和JK连接器
1.下载apache服务器源码包
apache服务器官方没有发布编译好的linux二进制包,只能通过下载源代码,然后自己编译。因此需要先下载源码。
访问网址http://httpd.apache.org/download.cgi,可以看到apache服务器目前放出的版本信息,推荐使用稳定版的release。
然后选择Unix版源码:
2.下载tomcat服务器源码包
目前tomcat服务器个人还是觉得6.0比较稳定。7.0毕竟是新出的东西,需要一定的生产实践考验才能达到理想的状态。因此这里选择tomcat 6.0。
访问网址http://tomcat.apache.org/download-60.cgi,可以看到目前稳定的版本为6.0.33:
这里强烈建议下载tar.gz格式的压缩包。在Linux下,文件访问有着严格的权限限制。一个文件是否允许以二进制或者脚本的形式执行,完全取决于其是否拥有执行缺陷,这与Windows识别文件后缀名(.exe、.bat)的方式不同。zip格式的压缩包中是不保留文件的权限信息的,而tar.gz格式的压缩包是保存有文件的权限信息的。
3.下载JK连接器源码包
作为apache与tomcat连接的桥梁,JK连接器使用C语言编写,与apache紧密结合,作为模块装载到apache服务器中,通过配置实现与特定的tomcat服务器进行通信,从而实现负载均衡的功能。
访问网址http://tomcat.apache.org/download-connectors.cgi,可以找到最新最稳定的JK连接器版本:
这里还是推荐下载tar.gz格式的源码。原因同上。
4.解压
apache服务器、tomcat服务器和JK连接器都已经下载好了,如下图所示:
然后将这三个包都解压出来:
5.编译apache服务器
首先编译apache服务器。在编译之前需要执行其自带的检测配置脚本。对于不同发行版本的Linux,默认安装的库都有所差别,即便是同一个发行版本,由于用户安装软件的软件不同,也会导致系统内包含的库有所区别。因此apache作为开源服务器,在编译前需要了解系统的库安装情况,某些模块需要依赖于特定的库,如果这些库不存在,配置脚本将自动忽略这些库的编译。经过检测时候会生成合适的MakeFile文件。这里特别提醒一句,如果直接执行配置脚本,是不会编译额外的模块的,我们希望使用额外模块时,需要在运行配置脚本命令后加入参数,让其尽最大可能编译可用的库。关于这方面的介绍可以参阅我的另外一篇文章“Linux下编译apache服务器modules文件夹缺少模块(.so)的问题”(http://blog.csdn.net/chaijunkun/article/details/6977466)。下面进入apache服务器源码目录并执行配置脚本:
- [root@lxp2 Downloads]# cd httpd-2.2.21
- [root@lxp2 httpd-2.2.21]# ./configure --enable-so --enable-mods-shared=most --with-mpm=worker
加入--with-mpm=worker是修改apache服务器的工作模式。默认模式是prefork。prefork采用预派生子进程方式,用单独的子进程来处理 不同的请求,进程之间彼此独立。相对于prefork,worker是全新的支持多线程和多进程混合模型的MPM(多路处理模块)。由于使用线程来处理,所以可以处理相对海量的请求,而系统资源的开销要小于基于进程的服务器。但是,worker也使用了多进程,每个进程又生成多个线程,以获得基于进程服务器的稳定性。
如果配置过程中出现
- configure: error: Cannot use an external APR with the bundled APR-util
这样的错误信息,说明本机没有安装apr运行库,需要下载并安装。访问网址:http://apr.apache.org/download.cgi,下载apr和apr-util:
解压apr和apr-util
- [root@lxp2 Downloads]# tar -xf apr-1.4.5.tar.gz
- [root@lxp2 Downloads]# tar -xf apr-util-1.3.12.tar.gz
进入apr,并编译
- [root@lxp2 Downloads]# cd apr-1.4.5
- [root@lxp2 apr-1.4.5]# ls
- apr-config.in build.conf helpers memory shmem
- apr.dep build-outputs.mk include misc strings
- apr.dsp CHANGES libapr.dep mmap support
- apr.dsw config.layout libapr.dsp network_io tables
- apr.mak configure libapr.mak NOTICE test
- apr.pc.in configure.in libapr.rc NWGNUmakefile threadproc
- apr.spec docs LICENSE passwd time
- atomic dso locks poll user
- build emacs-mode Makefile.in random
- buildconf file_io Makefile.win README
- [root@lxp2 apr-1.4.5]# ./configure
生成了MakeFile后直接编译
- [root@lxp2 apr-1.4.5]# ls
- apr-1-config buildconf dso locks poll
- apr-config.in build.conf emacs-mode Makefile random
- apr.dep build-outputs.mk file_io Makefile.in README
- apr.dsp CHANGES helpers Makefile.win shmem
- apr.dsw config.layout include memory strings
- apr.mak config.log libapr.dep misc support
- apr.pc config.nice libapr.dsp mmap tables
- apr.pc.in config.status libapr.mak network_io test
- apr.spec configure libapr.rc NOTICE threadproc
- atomic configure.in libtool NWGNUmakefile time
- build docs LICENSE passwd user
- [root@lxp2 apr-1.4.5]# make
编译好之后使用root权限安装:
- [root@lxp2 apr-1.4.5]# sudo make install
然后使用类似的方法配置apr-util:
- [root@lxp2 Downloads]# cd apr-util-1.3.12
- [root@lxp2 apr-util-1.3.12]# ./configure --with-apr=/usr/local/apr
编译apr-util:
- [root@lxp2 apr-util-1.3.12]# make
编译好之后使用root权限安装:
- [root@lxp2 apr-util-1.3.12]# sudo make install
当然如果你在配置apache服务器编译的时候没有提示缺少“APR”,请忽略上面关于APR编译的几步。
回到apache服务器源码所在目录,开始编译:
- [root@lxp2 httpd-2.2.21]# make
编译过程大概不到十分钟,完成之后使用root权限进行安装
- [root@lxp2 httpd-2.2.21]# sudo make install
如果不出意外,至此apache就安装成功了。来测试一下:
进入apache服务器的bin目录,并启动服务器:
- [root@lxp2 httpd-2.2.21]# cd /usr/local/apache2/bin/
- [root@lxp2 bin]# sudo ./apachectl start
- httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
在本地打开浏览器,访问http://127.0.0.1
如果出现“It Works!”则表示启动成功了
这里要注意一点就是Linux的防火墙问题。如果你的Linux服务器启动了防火墙,本地访问上面的网址是没有问题的,但如果其它计算机访问你的服务器有可能会连接失败。
出现这种情况的原因是防火墙将入站80端口封锁了。解决方法是将80端口加入到允许列表中:
进入防火墙设置后,如果发现Firewall状态为Enabled,表示防火墙已启用,需要将WWW(HTTP)服务标记为信任,如果需要使用hhtps协议,还要将Secure WWW(HTTPS)服务也标记为信任。如下图所示:
另外,此时如果有其他程序占用80端口也是会影响到apache服务器的,需要确保这个端口没有被占用。
还有我还要补充一点,在Mac OS中按照上述方法安装apache服务器是不行的。开始的时候我不想搭建Linux服务器,想到Mac OS也是类Unix的系统,操作命令什么的都一样,就先在Mac上实验了。结果安装上apache服务器后启动了,每次访问都提示505错误,service temporarily unavailable。经过查阅很多资料和尝试才发现,原来Mac系统中已经自带了apache服务器。具体应用是在“系统设置”中的“共享”功能。这个功能里有“Web共享”方式。其实现时使用的服务器就是apache。它采用的配置文件在/etc/httpd/目录中。这里的配置文件和自己安装的apache服务器配置文件冲突了,因此造成505错误。这一点需要注意。(注:我是用的Mac系统为Mac OS X Lion 10.7.2)
2011年11月23日补充:
如果你希望把apache服务器注册为系统服务,让它随着系统启动而启动,则需要在/etc/init.d/目录中建立服务管理脚本,我们将其命名为httpd:
-
-
-
-
- pidfile="/usr/local/apache2/logs/httpd.pid"
- httpd_process_name="httpd"
- httpd_path="/usr/local/apache2/bin/apachectl"
-
- RETVAL=0
- start(){
- echo "Starting Apache Httpd Service..."
- httpd_pid_list=`pidof $httpd_process_name`
- if test -n "$httpd_pid_list"
- then
- echo "Fail To Launch Httpd, Since It Has Already Started"
- RETVAL=1
- else
- echo "Launching Apache Httpd Server"
- `$httpd_path "start"`
- RETVAL=$?
- echo "Launch Httpd Successfully"
- fi;
- }
-
- stop(){
- echo "Stopping Apache Httpd Service..."
- httpd_pid_list=`pidof $httpd_process_name`
- if test -n "$httpd_pid_list"
- then
- echo "Find Httpd Process, Start To End Them"
- `$httpd_path "stop"`
- if test "$?" = "0"
- then
- echo "Success to Terminate Httpd Service"
- RETVAL=0
- else
- echo "Can Not Terminate Httpd Service"
- RETVAL=1
- fi;
- else
- echo "Can Not Find Any Httpd Process, Fail To Stop Service"
- RETVAL=0
- fi;
- }
-
- restart(){
- stop
- if test "$?"="0"
- then
-
- sleep 3
- start
- RETVAL= $?
- else
- RETVAL= $?
- fi;
- }
-
- status(){
- if test -f $pidfile
- then
- pid_list=`cat $pidfile`
- echo "$httpd_process_name (pid:$pid_list) is running"
- else
- echo "$httpd_process_name is stopped"
- fi;
- }
-
- case "$1" in
- start)
- start
- RETVAL=$?
- ;;
- stop)
- stop
- RETVAL=$?
- ;;
- restart)
- restart
- RETVAL=$?
- ;;
- status)
- status
- ;;
- *)
- echo {1}quot;Usage:$0 {start|stop|restart} asdfasdfasdfasdf "
- RETVAL=2
- esac
-
- exit $RETVAL
编写完成后保存并赋予755权限。然后在该目录下执行
- [root@lxp2 init.d]# chkconfig --add httpd
将服务添加到系统。脚本的具体解释请参阅我的另外一篇博文:
Linux中将memcached注册为系统服务(地址:http://blog.csdn.net/chaijunkun/article/details/7000600)。
6.编译JK连接器
刚刚完成了apache服务器的编译,接下来顺便把JK连接器也编译出来。
进入刚刚解压出来的tomcat-connector目录,再进入native目录。执行配置:
- [root@lxp2 Downloads]# cd tomcat-connectors-1.2.32-src
- [root@lxp2 tomcat-connectors-1.2.32-src]# ls
- BUILD.txt conf docs jkstatus LICENSE native NOTICE support tools xdocs
- [root@lxp2 tomcat-connectors-1.2.32-src]# cd native/
- [root@lxp2 native]# ls
- aclocal.m4 BUILDING.txt configure.in Makefile.am nt_service TODO.txt
- apache-1.3 CHANGES docs Makefile.in README.txt
- apache-2.0 common iis netscape scripts
- buildconf.sh configure jni NEWS STATUS.txt
- [root@lxp2 native]# ./configure --with-apxs=/usr/local/apache2/bin/apxs
这里需要注意的是配置脚本要添加一个apxs完整路径作为参数。apxs是一个为Apache HTTP服务器编译和安装扩展模块的工具,用于编译一个或多个源程序或目标代码文件为动态共享对象,使之可以用由mod_so提供的LoadModule指令在运行时加载到Apache服务器中。
另外,配置脚本运行时会检查g++所在的目录,如果没有安装g++,则会显示:
- configure: error: C++ preprocessor "/lib/cpp" fails sanity check
请检查是否已经正确安装了c++编译器。
因为实验用的服务器安装的是X86_64版的Red Hat Enterprise Linux Server ,因此要安装如下的包:
libstdc++-devel-4.1.2-46.el5.x86_64.rpm
gcc-c++-4.1.2-46.el5.x86_64.rpm
如果使用rpm命令无法安装,可以在http://szmov.net/centos5464/CentOS/里查找到相应的资源,下载下来安装也是一样的。
配置无误后就可以编译了,执行make命令:
7.JK连接器模块的部署
编译完成后使用ls命令来列出native目录下的所有目录和文件。注意有apache-1.3和apache-2.0两个目录。由于在配置编译的时候指定了apxs工具的位置。配置脚本会根据apxs的反馈结果自动识别目标apache服务器为2.x版本,因此本次编译生成的mod_jk.so模块会放在apache-2.0目录中,apache-1.3目录中是没有mod_jk.so的,这一点请注意。如下所示:
- [root@lxp2 native]# ls
- aclocal.m4 CHANGES configure libtool NEWS TODO.txt
- apache-1.3 common configure.in Makefile nt_service
- apache-2.0 config.log docs Makefile.am README.txt
- buildconf.sh config.nice iis Makefile.in scripts
- BUILDING.txt config.status jni netscape STATUS.txt
- [root@lxp2 native]# cd apache-2.0/
- [root@lxp2 apache-2.0]# ls
- bldjk54.qclsrc Makefile.apxs mod_jk.a mod_jk.lo
- bldjk.qclsrc Makefile.apxs.in mod_jk.c mod_jk.o
- config.m4 Makefile.in mod_jk.dsp mod_jk.so
- Makefile Makefile.vc mod_jk.la NWGNUmakefile
- [root@lxp2 apache-2.0]#
我们现在将编译好的mod_jk.so拷贝到apache服务器的modules目录中,这个目录是专门用来存放扩展模块的:
- [root@lxp2 apache-2.0]# sudo cp ./mod_jk.so /usr/local/apache2/modules/
- [root@lxp2 apache-2.0]# cd /usr/local/apache2/modules/
- [root@lxp2 modules]# ls
- httpd.exp mod_authz_user.so mod_include.so
- mod_actions.so mod_autoindex.so mod_info.so
- mod_alias.so mod_cgi.so mod_jk.so
- mod_asis.so mod_dav_fs.so mod_log_config.so
- mod_auth_basic.so mod_dav.so mod_logio.so
- mod_auth_digest.so mod_dbd.so mod_mime.so
- mod_authn_anon.so mod_deflate.so mod_negotiation.so
- mod_authn_dbd.so mod_dir.so mod_reqtimeout.so
- mod_authn_dbm.so mod_dumpio.so mod_rewrite.so
- mod_authn_default.so mod_env.so mod_setenvif.so
- mod_authn_file.so mod_expires.so mod_speling.so
- mod_authz_dbm.so mod_ext_filter.so mod_status.so
- mod_authz_default.so mod_filter.so mod_substitute.so
- mod_authz_groupfile.so mod_headers.so mod_userdir.so
- mod_authz_host.so mod_ident.so mod_version.so
- mod_authz_owner.so mod_imagemap.so mod_vhost_alias.so
至此JK连接器模块就部署完成了,但是还需要配置,具体配置将在下文中详细描述。
8.部署tomcat服务器
由于要在本地开启两个tomcat服务器实例以模拟负载均衡+群集的效果,因此我们需要将之前解压出来的tomcat复制成两份,进入解压时的目录,重命名解压出来的原始目录为tomcat_server_1,然后复制此目录,副本目录名称为tomcat_server_2:
- [root@lxp2 ~]# cd Downloads/
- [root@lxp2 Downloads]# ls
- apache-tomcat-6.0.33 cpp
- apache-tomcat-6.0.33.tar httpd-2.2.21.tar
- apr-1.4.5 tomcat-connectors-1.2.32-src
- apr-1.4.5.tar.gz tomcat-connectors-1.2.32-src.tar
- apr-util-1.3.12
- apr-util-1.3.12.tar.gz
- [root@lxp2 Downloads]# mv apache-tomcat-6.0.33 tomcat_server_1
- [root@lxp2 Downloads]# cp -r tomcat_server_1 tomcat_server_2
- [root@lxp2 Downloads]# ls
- apache-tomcat-6.0.33.tar httpd-2.2.21.tar
- apr-1.4.5 tomcat-connectors-1.2.32-src
- apr-1.4.5.tar.gz tomcat-connectors-1.2.32-src.tar
- apr-util-1.3.12 tomcat_server_1
- apr-util-1.3.12.tar.gz tomcat_server_2
- httpd-2.2.21
- [root@lxp2 Downloads]#
现在测试tomcat_server_1是否能够正常工作。
将我实现写好的一个测试用例下载下来(测试用例基于Spring 3.0编写,已经打成war包),下载地址:http://download.csdn.net/detail/chaijunkun/3815798。下载得到的文件是TestProject.war。将此压缩包放入tomcat_server_1的webapps目录下。然后切换到tomcat_server_1的bin目录下,启动tomcat_server_1:
- [root@lxp2 bin]# ./startup.sh
- Using CATALINA_BASE: /root/Downloads/tomcat_server_1
- Using CATALINA_HOME: /root/Downloads/tomcat_server_1
- Using CATALINA_TMPDIR: /root/Downloads/tomcat_server_1/temp
- Using JRE_HOME: /usr/java/jdk1.6.0_27
- Using CLASSPATH: /root/Downloads/tomcat_server_1/bin/bootstrap.jar
然后在浏览器中访问http://127.0.0.1:8080/TestProject/showInfo.do,如果没什么意外会显示类似于下面的信息:
- This message is from Server, RealPath:
- /root/Downloads/tomcat_server_1/webapps/TestProject/
- Current Session Id:
- 471D55C942346EC7BB48D07D9437D57E
信息中显示了当前测试用例所在的路径以及当前会话的SessionId。
此处要注意的地方同测试apache服务器是否正常工作时是一样的,需要注意防火墙是否阻塞了tomcat服务器默认采用的8080端口,是否有其他程序占用此端口。
看到没什么问题,我们先吧tomcat_server_1关闭
- [root@lxp2 bin]# ./shutdown.sh
- Using CATALINA_BASE: /root/Downloads/tomcat_server_1
- Using CATALINA_HOME: /root/Downloads/tomcat_server_1
- Using CATALINA_TMPDIR: /root/Downloads/tomcat_server_1/temp
- Using JRE_HOME: /usr/java/jdk1.6.0_27
- Using CLASSPATH: /root/Downloads/tomcat_server_1/bin/bootstrap.jar
9.apache服务器的配置
apache服务器、tomcat服务器和JK连接器都部署完成并能正确执行后就可以开始配置了
用vi或者其它编辑器打开/usr/local/apache2/conf/httpd.conf文件(由于该文件权限属性为rw-r--r--,因此要想修改此文件需要root权限),这就是apache服务器的主配置文件了。
这里我推荐使用图形化的编辑器来编辑它。因为这个文件很多行,如果用文本模式的编辑器编辑个人感觉很繁琐。
在有很多LoadModule语句的地方,末尾追加一行
LoadModule jk_module modules/mod_jk.so
然后在写有<IfModule XXXX>的区域追加一行如下配置
<IfModule jk_module>
JkWorkersFile conf/workers.properties
JkMountFile conf/uriworkermap.properties
JkLogFile logs/mod_jk.log
JkLogLevel warn
</IfModule>
下面给出了一个我写的配置。注意配置中有注释的地方。“#”开头的行为注释行。已经去除了原有的配置中的多余注释。
LoadModule表示当apache服务启动时要加载模块 jk_module为模块的别名,后面跟的modules/mod_jk.so就是相对于apache服务器所在目录(/usr/local/apache2/)的模块文件名。
<IfModule jk_module>区域表示当apache服务器加载jk_module(在LoadModule指令中指定的模块别名)模块时所做的配置。
其中:
JkWorkersFile 指定负载均衡服务器的配置文件,文件名为相对于apache服务器所在目录的conf/workers.properties文件
JkMountFile 指定那些请求交由负载均衡服务器来处理,那些由apache服务器来处理,配置文件为相对于apache服务器所在目录的conf/uriworkermap.properties文件
JkLogFile 指定JK连接器的日志输出文件,文件为相对于apache服务器所在目录的logs/mod_jk.log文件
JkLogLevel 指定JK连接器输出日志的级别,级别为warn以上的日志将被输出到日志文件中,可选的值级别由低到高分别为:TRACE DEBUG INFO WARN ERROR FATAL
------------------------------------------------------------------------------------------------------------------------------------------------
<IfModule worker.c>区域表示当apache服务器以worker模式工作时使用的配置。
指令说明:
StartServers:设置服务器启动时建立的子进程数量。因为子进程数量动态的取决于负载的轻重,所有一般没有必要调整这个参数。
ServerLimit:服务器允许配置的进程数上限。只有在你需要将MaxClients和ThreadsPerChild设置成需要超过默认值16个子进程的时候才需要使用这个指令。不要将该指令的值设置的比MaxClients 和ThreadsPerChild需要的子进程数量高。修改此指令的值必须完全停止服务后再启动才能生效,以restart方式重启动将不会生效。
ThreadLimit:设置每个子进程可配置的线程数ThreadsPerChild上限,该指令的值应当和ThreadsPerChild可能达到的最大值保持一致。修改此指令的值必须完全停止服务后再启动才能生效,以restart方式重启动将不会生效。
MaxClients:用于伺服客户端请求的最大接入请求数量(最大线程数)。任何超过MaxClients限制的请求都将进入等候队列。默认值是"400",16 (ServerLimit)乘以25(ThreadsPerChild)的结果。因此要增加MaxClients的时候,你必须同时增加 ServerLimit的值。笔者建议将初始值设为(以Mb为单位的最大物理内存/2),然后根据负载情况进行动态调整。比如一台4G内存的机器,那么初始值就是4000/2=2000。
MinSpareThreads:最小空闲线程数,默认值是"75"。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太少,子进程将产生新的空闲线程。
MaxSpareThreads:设置最大空闲线程数。默认值是"250"。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太多,子进程将杀死多余的空闲线程。MaxSpareThreads的取值范围是有限制的。Apache将按照如下限制自动修正你设置的值:worker要求其大于等于 MinSpareThreads加上ThreadsPerChild的和。
ThreadsPerChild:每个子进程建立的线程数。默认值是25。子进程在启动时建立这些线程后就不再建立新的线程了。每个子进程所拥有的所有线程的总数要足够大,以便可以处理可能的请求高峰。
MaxRequestsPerChild:设置每个子进程在其生存期内允许伺服的最大请求数量。到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为"0",子进程将永远不会结束。将MaxRequestsPerChild设置成非零值有两个好处:可以防止(偶然的)内存泄漏无限进行而耗尽内存;
给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
如果设置为非零值,笔者建议设为10000-30000之间的一个值。
公式:
ThreadLimit >= ThreadsPerChild
MaxClients <= ServerLimit * ThreadsPerChild,并且MaxClients必须是ThreadsPerChild的倍数
MaxSpareThreads >= MinSpareThreads+ThreadsPerChild
------------------------------------------------------------------------------------------------------------------------------------------------
接下来配置上面提到的conf/workers.properties文件和conf/uriworkermap.properties文件:
进入apache服务器的conf目录
- [root@lxp2 ~]# cd /usr/local/apache2/conf/
建立workers.properties和uriworkermap.properties文件
下面给出我已经配置好的两个文件
-
-
-
-
-
- worker.list=loadBalanceServers, jk_watcher
-
-
-
- worker.s1.port=8109
- worker.s1.host=localhost
- worker.s1.type=ajp13
- worker.s1.lbfactor=10
- worker.s1.cachesize=5
-
-
-
- worker.s2.port=8209
- worker.s2.host=localhost
- worker.s2.type=ajp13
- worker.s2.lbfactor=10
- worker.s2.cachesize=5
-
- worker.loadBalanceServers.type=lb
- worker.loadBalanceServers.balanced_workers=s1,s2
- worker.loadBalanceServers.sticky_session=false
- worker.jk_watcher.type=status
-
- worker.jk_watcher.mount=/admin/jk
- worker.retries=3
worker.list 首先配置了两个worker,一个用于负载均衡,一个用于监视负载均衡状态。别名分别为loadBalanceServers和jk_watcher
然后分别配置位于本机的两个负载均衡服务器
worker.s1.port:第一台负载均衡服务器AJP协议连接器的连接端口,这里配置为8109
worker.s1.host:第一台负载均衡服务器的主机名、域名或者IP地址,这里配置为本机localhost
worker.s1.type:JK模块实现负载均衡采用的是AJP协议1.3版本,因此第一台负载均衡服务器的类型配置为ajp13
worker.s1.lbfactor:第一台负载均衡服务器在整个负载均衡系统中所占的权重,这里配置为10,权重越大,越有可能处理更多的请求,建议给性能好的机器配置更高的权重。
worker.s1.cachesize:apache服务器是多线程的,tomcat能够利用这一优势来维持一定数量的连接作为缓存。根据用户的多少来配置一个合适缓存连接数量有助于提高性能。这里配置为5
s1是第一台负载均衡服务器的别名,这个别名要牢记,因为在接下来的配置中还会用到。
s2作为第二台负载均衡服务器,配置与s1大致相同。区别是AJP协议连接器的连接端口与s1的不同,这是因为要在同一台物理机上部署两个tomcat服务器的缘故。如果是两台物理机,则可以配置相同的端口,那么host属性就应该不一样了。两个tomcat服务器的权重都是10,则两个tomcat服务器将会有相同的处理请求的机会。
worker.loadBalanceServers.type:设置名称为“loadBalanceServers”的worker类型,这里配置为lb,也就是Load Balance负载均衡
worker.loadBalanceServers.balanced_workers:设置名称为“loadBalanceServers”的worker拥有哪些负责负载均衡的服务器实例,这里配置为s1和s2
worker.loadBalanceServers.sticky_session:设置负载均衡是否采用粘性会话。如果该属性设置为true,假设一个请求被s1处理了,下次来源于同一个客户端的请求也将被s1处理。直到s1已经达到最大连接数,JK才会将会话切换到其他服务器上。但是如果恰巧一直负责处理该会话的服务器down掉了,则会话将会丢失,明显的故障现象就是关于session的操作会出现莫名其妙的错误(例如你所运行的应用中用户可能已经登录了,但突然在一次访问后莫名其妙地提示没有登录)。这里配置为false,不启用粘性会话,让服务器都有机会处理请求,提高了系统的稳定性。
worker.jk_watcher.type:设置名称为“jk_watcher”的worker类型,这里配置为status,用于监视各个负载均衡服务器实例的运行状态
# worker.jk_watcher.read_only:设置名称为“jk_watcher”的worker是否为只读。上面已经将这个worker设置为了监控worker,如果设置为只读,就不能对负载均衡服务器参数进行配置了,这里先将这条配置注释掉,默认值为false,表示可以配置参数。
worker.jk_watcher.mount:设置名称为“jk_watcher”的worker(负载均衡服务器实例监视器)的挂载路径,这里配置为/admin/jk。这样就可以通过http://127.0.0.1/admin/jk来访问监视工具了,可以很方便地看到各个负载均衡服务器的工作情况。
worker.retries:这是worker全局的重试次数。在apache服务器启动后,会最多尝试若干次去连接这些负载均衡服务器,若连接不上就认为是down掉了,这里配置为3
下面给出配置,其作用是告诉apache服务器哪些请求由负载均衡服务器处理:
-
-
-
-
-
-
-
- /*=loadBalanceServers
- /jkstatus=jk_watcher
- !/*.gif=loadBalanceServers
- !/*.jpg=loadBalanceServers
- !/*.tif=loadBalanceServers
- !/*.png=loadBalanceServers
在配置文件中,以“!”开头的条件表示“不要”,“=”表示交给。
因此条件“/*=loadBalanceServers”表示将任何请求交给负载均衡服务器。
条件“!/*.jpg=loadBalanceServers”表示不要将.jpg结尾的请求交给负载均衡服务器
apache服务器接收到一个请求后会按照配置文件中的约束条件一个一个地检查,然后按照最后满足的匹配条件来决定由哪个worker来处理请求。
我的测试用例中需要输入http://127.0.0.1/TestProject/showInfo.do来查看信息。那么接下来就将这个请求作为示例来解释上面配置文件的工作过程:
经过上面的条件筛选,最符合条件的就是“/*=loadBalanceServers”。因此将请求转给了负载均衡服务器。
试想一下,如果在apache主目录下放置了一个名为a.jpg的图片,访问路径为http://127.0.0.1/a.jpg,请求经过该配置的检查,最后满足的条件就是“!/*.jpg=loadBalanceServers”,不要将.jpg结尾的请求交给负载均衡服务器,因此apache服务自己处理了该请求。
.jpg是静态数据,apache由C语言实现,直接针对系统底层进行IO操作,因此静态性能优良。而tomcat作为Servlet容器,擅长的是J2EE相关业务的解析。因此通过这样配置可以实现应用的“动静态分离”,相互取长补短,优化了性能。类似地也可以将.js、.css和.html等等静态文件按照上述格式填写到uriworkermap.properties配置文件中。
10.tomcat服务器的配置
由于在同一台物理机中部署了两个tomcat服务器实例,因此需要对端口相关的设置特别小心。tomcat服务器的主配置文件server.xml位于conf目录内。为了配置简单,我将最原始server.xml配置文件中的所有注释删除,然后配置好了一个模板,该模板是s1((即tomcat_server_1)的配置文件,如下所示:
- <?xml version='1.0' encoding='utf-8'?>
-
- <Server port="8005" shutdown="SHUTDOWN">
- <Listener className="org.apache.catalina.core.AprLifecycleListener"
- SSLEngine="on" />
- <Listener className="org.apache.catalina.core.JasperListener" />
- <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
- <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
- <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
- <GlobalNamingResources>
- <Resource name="UserDatabase" auth="Container"
- type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved"
- factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
- pathname="conf/tomcat-users.xml" />
- </GlobalNamingResources>
- <Service name="Catalina">
-
- <Connector port="8081" protocol="HTTP/1.1"
- connectionTimeout="20000" redirectPort="8443" />
-
- <Connector port="8109" protocol="AJP/1.3" redirectPort="8443" />
-
-
-
- <Engine name="Catalina" defaultHost="localhost" jvmRoute="s2">
- <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
- resourceName="UserDatabase" />
- <Host name="localhost" appBase="webapps" unpackWARs="true"
- autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
-
-
-
- <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>
-
- </Host>
- </Engine>
- </Service>
- </Server>
配置好s1服务器后再配置s2服务器。按照上面模板中的注释要求,修改相应的端口就可以了。PS:<Cluster ...></Cluster>节点之间部分不必自己动手敲进去,在tomcat服务器目录的/webapps/docs/cluster-howto.html文件中有这一段文字,拷贝出来贴到server.xml文件中即可。
11.部署测试用例
将我提供的TestProject.war文件复制到两个tomcat服务器实例的webapps目录下,然后分别启动tomcat服务器,TestProject.war会自动部署上:
- [root@lxp2 Downloads]# cd tomcat_server_1/bin/
- [root@lxp2 bin]# ./startup.sh
- Using CATALINA_BASE: /root/Downloads/tomcat_server_1
- Using CATALINA_HOME: /root/Downloads/tomcat_server_1
- Using CATALINA_TMPDIR: /root/Downloads/tomcat_server_1/temp
- Using JRE_HOME: /usr/java/jdk1.6.0_27
- Using CLASSPATH: /root/Downloads/tomcat_server_1/bin/bootstrap.jar
- [root@lxp2 bin]# cd ../../
- [root@lxp2 Downloads]# cd tomcat_server_2/bin/
- [root@lxp2 bin]# ./startup.sh
- Using CATALINA_BASE: /root/Downloads/tomcat_server_2
- Using CATALINA_HOME: /root/Downloads/tomcat_server_2
- Using CATALINA_TMPDIR: /root/Downloads/tomcat_server_2/temp
- Using JRE_HOME: /usr/java/jdk1.6.0_27
- Using CLASSPATH: /root/Downloads/tomcat_server_2/bin/bootstrap.jar
- [root@lxp2 bin]#
这里需要注意的是两个tomcat服务实例的配置文件server.xml的访问权限。我这里使用的是root账户,所以不用太关心,但是如果用非root账户,一定要看看当前账户是否有server.xml的读写权限。如果没有,则tomcat服务器将不能成功启动。这种情况下要么修改server.xml的访问权限,要么使用root权限启动tomcat服务器。
- [root@lxp2 bin]# sudo ./startup.sh
开启了tomcat服务器之后,就可以开启apache服务器了(注意,顺序很重要!一定要先开tomcat)
- [root@lxp2 ~]# cd /usr/local/apache2/bin/
- [root@lxp2 bin]# sudo ./apachectl start
- httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
- [root@lxp2 bin]#
这时候如果没问题,在本机浏览器访问http://127.0.0.1会出现如下页面:
然后输入网址访问http://127.0.0.1/TestProject/showInfo.do来看看效果:
然后再来刷新一下看看:
我们看到,访问URL没有改变,但是apache把两次访问的负载平均分配给了两个tomcat服务器实例,并且SessionId是相同的。
当再次刷新页面的时候,请求又再一次交给了s1服务器。这也正好验证了之前workers.properties文件中关于两服务器的权重设置。
至此,apache服务器+tomcat服务器+JK连接器实现负载均衡与群集的操作结束。
相关推荐
Apache+Tomcat+JK 实现集群负载均衡是一种常见的Web服务器和应用服务器的部署方式,它能够提高系统的可用性和响应速度,实现服务的高并发处理。本文将详细介绍如何配置这一环境。 首先,我们需要准备以下软件: 1. ...
Apache+Tomcat+JK是一个常见的Web服务器和应用服务器集群解决方案,用于实现负载均衡和高可用性。这个配置中,Apache作为前端反向代理服务器,Tomcat作为后端的应用服务器,而JK模块是Apache与Tomcat之间的连接器,...
"Apache+Tomcat7+jk负载均衡"的组合就是一种常见的解决方案,它通过Apache HTTP Server作为前端代理服务器,利用JK模块(mod_jk)将请求分发到多台后端的Tomcat7应用服务器上,实现负载均衡和故障转移。下面我们将...
以下是对标题“tomcat+apache+jk集群和负载均衡”以及描述“tomcat+apache+jk集群和负载均衡”的深入解析,涵盖其原理、配置步骤以及关键参数调整。 ### 1. 理论基础 #### Tomcat Tomcat是Apache软件基金会下的一...
### Linux环境下Apache+Tomcat+JK集群配置详解 #### 一、集群基础知识 集群技术是提升系统服务能力和高可用性的关键技术之一。通过将多台独立的服务器组织成一个集群,可以实现故障无缝迁移,即当集群中某台服务器...
### Apache+Tomcat+Linux集群和负载均衡 在IT领域,Apache+Tomcat+Linux集群与负载均衡技术是实现高可用性、高性能Web服务的重要手段之一。本文将围绕这一主题展开详细讨论,涵盖关键技术概念、配置流程及注意事项...
通过以上步骤,我们完成了在 Red Hat Linux 9.0 上安装 Apache、Tomcat 和 Mod_jk 的过程,并进行了简单的负载均衡配置。这些配置能够帮助我们更好地管理应用服务器集群,提高系统的稳定性和性能。当然,实际部署时...
Apache+Tomcat+JK配置负载均衡是Web服务器与应用服务器集群的一种常见组合,用于实现高可用性和高并发处理能力。Apache作为前端服务器,通过JK模块(mod_jk)与后端的Tomcat应用服务器进行通信,将HTTP请求分发到多...
超级无敌web服务器 linux+apache+tomcat+mysql+jsp+php 整合安装 自己的安装过程,以前发表在新浪博客,现在换地盘了转过来... 自我感觉写得还是不错滴.. 在安装过程更是学到了很多东西 做好这个项目以后linux...
Apache+Tomcat+Linux集群和均衡负载(Session同步复制
Apache+JK+Tomcat搭建负载均衡是一种常见的高可用性和性能优化策略,主要目的是分散网络流量,提高服务的稳定性和响应速度。这个方案特别适合大型网站或应用,可以有效防止单点故障,提升用户体验。 首先,负载均衡...
配置安装Apache+Apache Tomcat实现tomcat负载均衡教程.doc
本篇文章将详细介绍如何使用Apache和Tomcat实现负载均衡。 负载均衡的核心思想是将来自用户的请求分发到多个服务器上,以避免单一服务器过载。在Apache与Tomcat的组合中,Apache通常作为前端负载均衡器,通过HTTP...
apache+tomcat+mod_jk整合文档,内有安装包。apache+tomcat+mod_jk整合文档,内有安装包。
反向代理负载均衡 Apache + Tomcat集群 多的我也不多说了 看文档
总之,利用Apache+Tomcat+mod_jk实现的负载均衡和集群配置是一种常见的Web服务器解决方案,它提供了一种灵活、可扩展的方式,以应对高并发访问和服务器故障的情况。在实际部署中,还需要考虑监控、性能调优以及安全...
本人自己配置的windows平台apache+tomcat负载均衡实现,这个资源中包括apache,tomcat,测试项目+说明文档。只要正确安装apache,即可直接正常运行。本人参考网络,所以给贡献网络。
总结,通过以上步骤,我们可以成功地在 Linux 上安装并配置 Apache、Tomcat 和 mod_jk,实现负载均衡。这不仅可以提高系统的可用性,还能有效利用多台服务器的资源,降低单点故障的风险。在实际应用中,根据服务器...