1.实现原理
首先看下tomcat有哪些组件,以及这些组件之间有什么关系
Server组件:代表了整个servlet(运行在tomcat服务器上的小插件,动态加载和执行)容器组件。包含以下所有组件配置,可包括多个service元素
Service组件:包含一个Engine元素和多个Connector元素
Connector组件:代表和客户程序实际交互的组件,负责处理客户端请求和返回服务端响应。
Engine组件:一个Engine组件处理所有Connector组件的请求和响应
Host组件:可以有多个,虚拟主机的意思,一个虚拟主机下允许有一个或多个应用
Context组件:一个Context代表了一个Web应用。
处理过程:客户端请求最后会由Connector组件传递个Engine,并匹配这个请求的虚拟主机,匹配到虚拟主机后再去找和这个请求对应的Web应用,Web应用逻辑处理这个请求完后,返回数据给虚拟主机,给Engine,通过Connector返回到客户端,最终展示给用户页面或者文件等信息。
刚才说到了Connector组件负责处理客户请求的,而实现负载均衡就是为了防止所有的请求都到了一个服务器下,比如说1w个请求,同时给一个服务器来处理,我靠,服务器一下子要承受1w个并发量,会累死。所以我们要把1w个请求分发到多个服务器,然后每个服务器开一些线程和使用一些内存来处理这1w个请求,是不是压力瞬间就小多了。
BingGo。知道为什么要实现负载均衡了。那怎么来实现呢?有哪些技术和工具可以帮助实现呢?
不要急,让我们先看下刚才提到的Connector组件。贴代码,直接copy我server下的内容,嘿嘿。
1.第一种Connector组件是这样子的
<Connector connectionTimeout="20000" port="8090" protocol="HTTP/1.1" redirectPort="8443"/>
2.第二种是这样子的
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
问题又来了,这两个东东是什么啊?什么意思?干啥用的?
第一个组件是http连接器,监听8090端口,负责建立http链接。当浏览器直接访问tomcat上的应用时就会使用这个Connector建立一个http长链接。
第二个组件是AJP连接器,监听8009端口,负责和其他的http服务器建立链接。当tomcat需要和其他的http服务器集成时就要用到这个链接器。
到这里,负载均衡神秘的面纱已经撕开了一角。AJP?集成http服务器?没错,就是AJP链接器。接下来看下我们怎么通过AJP链接器与其他http服务器集成,又怎么来实现负载均衡。
如下图,两种链接器的区别,很清晰明了。
图里有个http服务器和jk插件,那就下下来看看是个什么东东
Apache Http Server下载链接:http://httpd.apache.org/download.cgi#apache24
JK插件下载链接:http://tomcat.apache.org/download-connectors.cgi
前些天有点累,没写完,继续。。。
记得下载的是这两个,在binary目录里找,还要选择一个China的镜像:
httpd-2.2.17-win32-x86-no_ssl.msi
mod_jk.so。
下载好后,先安装http server,安装到最后一步会让你配个访问域名,都写localhost。安装好后,启动Apache Http Services,然后再浏览器里输入http://localhost/,如果浏览器返回It Works,那就表示安装好了。
接下来配jk。怎么配?将mod_jk.so复制到http server安装路径下的modules下。放到这个目录下是不是重启服务http server就会去加载这个插件呢?不是的,还要在修改http server的配置,我的配置路径是这个,C:\Program Files (x86)\Apache Software Foundation\Apache2.2\conf,修改httpd.conf文件。找到这部分内容:
#LoadModule ssl_module modules/mod_ssl.so
#LoadModule status_module modules/mod_status.so
#LoadModule substitute_module modules/mod_substitute.so
#LoadModule unique_id_module modules/mod_unique_id.so
#LoadModule userdir_module modules/mod_userdir.so
#LoadModule usertrack_module modules/mod_usertrack.so
#LoadModule version_module modules/mod_version.so
看到上面这部分,大致可以猜到是什么意思了,就是加载插件的意思,我们在它下面增加以下内容:
LoadModule jk_module modules/mod_jk.so
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel debug
JkMount /*.jsp worker1
JkMount /MyProj/*.html worker1
具体解释:第一句就是加载jk插件啦,第二行表示的jk插件的工作文件,过会儿还要增加workers.properties这个配置文件。第三行
表示jk的日志文件,第三行表示jk的日志级别。第四五行表示jk只处理客户端对tomcat名为worker1的jsp请求和MyProj应用下的html请求。
再说下配workers.properties,看这个文件的名字,workers?工作者。。是的,http server把一个个的tomcat服务器当做是它的工作者,所有的客户端请求过来,经过jk过滤,再分给他的苦力tomcat服务器去处理,处理完了之后呢再把响应内容返回给用户。
怎么配?在conf目录下新建workers.properties文件。文件内容如下:
worker.list=worker1
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.type=ajp13
worker.worker1.lbfactor=1
具体解释:第一行,有哪些工作者,这里只配了一个worker1,表示tomcat名字为worker1的服务器,多个服务器名字之间用逗号隔开。
第二行,服务器的访问域名是localhoat,本地。
第三行,服务器的监听端口是8009
第四行,服务器类型,采用ajp协议
第五行,服务器worker1的负载因子值为1,如果再配一个worker12,指定worker.worker2.lbfactor=2,那么两个服务器上部署相同应用,一个请求过来是worker2处理的概率就是2/3,是worker1处理的概率就是1/3。这个地方可以看出我们的负载策略,分给不同服务器,给不同服务器访问权重。
好了,配置都弄好了。再来测测看。eclipse新建个工程,名字叫MyProj,给这个工程弄几个测试页面,html和jsp的。新建个tomcat服务器名字叫worker1。启动worker1,重启http server服务。浏览器中输入http://localhost/MyProj/NewFile.html,返回页面内容正确,如果请求的不是刚配置的jsp或者html资源文件,就会返回not found。在看下jk日志,是否有做拦截工作。
[Tue Nov 10 21:00:02.680 2015] [2108:2372] [debug] map_uri_to_worker_ext::jk_uri_worker_map.c (1170): Attempting to map URI ‘/MyProj/NewFile.xhtml’ from 2 maps
[Tue Nov 10 21:00:02.680 2015] [2108:2372] [debug] find_match::jk_uri_worker_map.c (984): Attempting to map context URI ‘/MyProj/*.html=worker1’ source ‘JkMount’
[Tue Nov 10 21:00:02.680 2015] [2108:2372] [debug] find_match::jk_uri_worker_map.c (984): Attempting to map context URI ‘/*.jsp=worker1’ source ‘JkMount’
[Tue Nov 10 21:00:02.680 2015] [2108:2372] [debug] jk_map_to_storage::mod_jk.c (3816): no match for /MyProj/NewFile.xhtml found
请求了一个.xhtml文件,但是jk没有在配置项里映射到这类文件,只有.jsp和/MyProj/.html文件,然后mod_jk.log给出了异常提示,no match。因为这个请求没有找到对应的匹配,所以不会到worker1里,http server会迅速返回一段信息给页面。这里也减少了服务器请求的压力,交给了http server去处理。那会不会给http server带来压力呢?觉得压力应该不会太大,毕竟只是做个匹配嘛,不知道说的对不对,不对的地方大家如果知道的话还希望帮忙指正下。
罗里吧嗦说了一堆,还没到重点。怎么实现负载均衡呢?下章再说。