Tomcat负载均衡、调优核心应用进阶学习笔记(三):LNMT nginx+tomcat、LAMT apache+tomcat、session会话保持、不错的站点

2023-06-20,,

文章目录

LNMT nginx+tomcat
LAMT apache+tomcat
基于mod_proxy
单节点
配置基于mod_proxy的负载均衡
基于mod_jk(需要编译安装)
单节点
配置基于mod_jk的负载均衡
session会话保持
Tomcat会话管理
session复制
session服务器
附 如果是php的话,如何将会话保存到memcached中
不错的站点(外面)推荐

LNMT nginx+tomcat

因为nginx处理请求的能力优于tomcat

有一个前端节点

两个tomcat node节点

将三个节点设置为host-only(主机之间可以通信也可以和主机通信,但是不能和外网通信)

前端节点

//配置网卡,如果被使用了就换一个数字
ifconfig eth1 192.168.10.254/24 up

node1节点

//配置网卡,如果被使用了就换一个数字
ifconfig eth1 192.168.10.6/24 up
//配置完之后通过前端节点 curl访问node1节点,看看是否成功例如
//curl http://192.168.10.6:8080

node2节点


前端节点安装nginx

//这里只是一种方式,为了学习linux记录下,安装nginx的形式很多,这段可以忽略
//lfgps https://www.jb51.net/LINUXjishu/117788.html
lfgps
ls
...
get nginx-1.4.7-1.el6.ngx.x86_64.rpm
//以上是从远端将nginx包拿过来
//rpm https://www.jb51.net/LINUXjishu/10984.html
rpm -ivh nginx-1.4.7-1.el6.ngx.x86_64.rpm
//查看目录
rpm -ql nginx

ps:这个目录和我知道的不太一样,经过查阅 https://segmentfault.com/q/1010000000141674

vim nginx.conf
//里面没有定义server,但是有include
http{
	include /etc/nginx/conf.d/ *.conf
}

cd conof.d
//定义了server
vi default.conf
//启动nginx
service nginx start

访问 http://173.16.00.6 显示welcom to nginx

编辑server配置,定义我们需要的location

server{
	location /{
		proxy_pass http://192.168.10.6:8080;
	}
}

访问:http://172.16.100.6/ 就会跳转到tomcat页面

动静分离

server{
	location /{
		root /web/htdocs;
		index index.jsp index.html index.htm;
	}
	//只有请求的是jsp的时候才会去请求后端,剩下的(静态资源)都由 上面的location提供
	//$匹配字符串的结束位置。
	location ~*\.(jsp|do)${
		proxy_pass http://192.168.10.6:8080;
	}
	location ~*\.(jpg|jpeg|gif|png|pdf|doc|rar|exe|zip|)${
		proxy_pass http://192.168.10.7:8080;
	}
}

代理多个tomcat

http{
	upstram tomcat {
		server 192.168.10.6:8080;
		server 192.168.10.7:8080;
	}
	server{
		location ~*\.(jsp|do)${
			proxy_pass http://tomcat;
		}
	}
}

LAMT apache+tomcat

基于mod_proxy

单节点

mod_proxy(http,https,ajp,注意ajp是mod_proxy之上的一个独立的模块)

apache环境(不详细,自行查阅)

tar xf httpd-2.4.2
cd httpd-2.4.2

/configure --prefix=/usr/local/apache --sysconfdir=/etc/httpd --enable-so --enable-ssl --enable-cgi --enable-rewrite --with-zlib --with-pcre
--with-apr=/usr/local/apra --with-apr-util=/usr/local/apr-util -enable-proxy --enable-proxy-http --enable-proxy-ajp
make && make install

tar xf tomcat-connectors-1.2.37-src.tar.gz
cd tomcat-connectors-1.2.37-src/native/
./configure --with-apxs=/usr/local/apache/bin/apxs
make && make install
//查看模块
httpd -M
//输出
proxy_module(shared)
proxy_http_module(shared)
proxy_ajp_moudle(shared)
//说明成功

在httpd.conf的全局配置段或虚拟主机中添加如下内容:

ProxyVia Off
ProxyRequest Off
<Proxy *>
	Request all granted
</Proxy>
	ProxyPass / ajp://172.16.100.1:8009/
	ProxyPassReverse /ajp://172.16.100.1:8009/
<Location />
	Requie all granted
</Location>

或让apache跟Tomcat的http连接器进行整合:

ProxyVia Off
ProxyRequests Off
ProxyPass / http://172.16.100.1:8080/
ProxyPassReverse / http://172.16.100.1:8080/
<Proxy *>
	Require all grantes
</Proxy>
<Location />
	Require all granted
</Location>

关于如上 apache 指令的说明:

ProxyPreserveHost{On|Off}:如果启用此功能,代理会将用户请求报文中的 Host:行发送给后端的服务器,而不再使用Proxy Pas 指定的服务器地址。如果想在反向代理机,则需要开启此项,否则就无需打开此功能。如下图,为了确定是传给www.a.com还是传给www.b.org,是否把用户请求的host守护向后转发。

上图中www.a.com和www.b.org是两个虚拟主机,用户如何知道请求哪个虚拟主机呢?(虚拟主机中有host),在请求报文中有host守护,用户请求哪个,就构建到相应报文中,总的来说上面的作用就是是否将用户请求的host转发给后面。虚拟主机指的是类似于nginx中http{server{location}}中的server

ProxyVia[On|Off|Full|Block}用于控制在 http 首部是否使用 Via:,主要用于在多级代理中控制代理请求的流向。默认为 0ff,即不启用此功能:0n 表示每个请求和响应报文均添加 via::Fu1 表示每个 via:行都会添加当前apache 服务器的版本号信息;Block 表示每个代理请求报文中的 via:都会被移除

ProxyRequests(on|off):是否开 apache 正向代理的功能:启用此项时为了代理 htp 协议必须启用modproxyhttp 樸块**。同时,如果为 apache 设置了ProxyPass ,即反向代理则必须将 ProxyRequests 设置为 Off**

ProxyPass [path] ! | url [key= value key= value key=value…]]:path实际上是url,|url 的url是后端主机的url,后面的key value是代理时所使用的选项,检查几次,超时时间是多少等。在url上使用!表示取反,path不带到服务器上去。将后端服务器某 URL(url) 与当前服务器的某虚拟路径(path)关联起来作为提供服务的路径,path 为当前服务器上的某虚拟径,url 为后端服务器上某 URL 路径。使用此指令时必须将 ProxyRequests 的值设置为 0,需要注意的是,如果 path 以“/”结尾,则对应的 u1 也必须以“结尾,反之亦然

如上ProxyPass / http://172.16.100.1:8080/ /就是虚拟路径 http://172.16.100.1:8080 就是后端的url

另外 modproxy 模块在 httpd2.1 的版本之后支持与后端服务器的连接池功能,连接在按需创建在可以保存至连接池中以备进一步使用。连接池大小或其它设定可以通过在 ProxyPass 中使用 key-value 的方式定义。常用的 key 如下所示:

◇min:连接池的最小容量,此值与实际连接个数无关,仅表示连接池最小要初始化的空间大小,连接池表示后端所能接受用户请求时的虚拟的默认留出的连接数的个数。

◇max:连接池的最大容量,每个 MPM 都有自己独立的容量;都值与 MPM 本身有关,如 Prefork 的总是为 1,而其它的则取决于 ThreadsPerchi1d 指令的值。

◇loadfactor:用于负载均衡集群配置中,定义对应后端服务器的权重,取值范围为 1-100

◇ retry:当 apache 将请求发送至后端服务器得到错误响应时等待多长时间以后再重试。单位是秒钟。(proxy模块会自动检测后端模块的健康状态,一转发不在线,就要重试,重试以后还是没有响应,就将这个主机,自动从可用服务器中移除了,一旦发现上线了,还能自动添加进来。)

如果 Proxy 指定是以 ba1 ancer://开头,即用于负彀均衡集群时,其还可以接受一些特殊的参效,如下所示:

◇lbmethod:apache实现负载均衡的调度方法,默认是byrequests,即基于权重将统计请求个数进行调度,bytraffic则执行基于权重的流量计数调度 ,bybusyness通过考量每个后端服务器的当前负载进行调度

◇maxattempts放弃请求之前实现故障转移的次效,默认为 1,其最大值不应该大于总的节点数。

◇nofailover:取值为On或Off,设置为On时表示后端服务器故障时,用户的session将损失,因此,在后端服务器不支持session复制时,可将其设置为On

◇stickysession:调度器的 sticky session 的名字,根据 web 程序语言的不同,其值JSESSIONID(如果后端是tomcat或者jetty使用这个,表示使用javasessionid号保持) 或 PHPSESSIONID(php服务用phpsessionid)。

述指令除了能在 ban1 ancer://或 Proxy Pass 中设定之外,也可使用 Proxy set 指令直接进行设置,如:

<Proxy balancer: //hotcluster>
Balancermemberhttp://wwwl.magedu.com8080loadfactor-l
alancermemberhttp://www2.magedu.com8080loadfactor=2
ProxySet lbmethod=bytraffic
</Proxy>

ProxyPassReverse:用于让 apache 调整 HTTP 重定向响应报文中的 Location、ContentLocation 及 URI 标签所对应的 URL,在反向代理环境中必须使用此指令避免重定向报文绕过 proxy 服务器(加入一个用户请求的是根下的bbs,我给重定向到flow,而flow没有卸载proxypass中,就绕过了proxy)

cd /etc/httpd/conf
vi httpd.conf
//也可以自己在别的配置文件中设置
cd ../conf.d/
vi mod_proxy.conf
//添加
ProxyVia Off
ProxyRequests Off
ProxyPreserveHost On
//允许哪些用户来访问的2.2上可以不用配置
//<Proxy *>
//	Require all grantes
//</Proxy>
ProxyPass / http://192.168.10.6:8080
//避免重定向保温绕过proxy服务器
ProxyPassReverse / http://192.168.10.6:8080
//location访问,在2.2不用,因为默认是都访问的。
<Location />
	Require all granted
</Location>

//检查
httpd -t
//启动
service httpd  start

访问 http://172.16.100.6 会转发到 192.168.10.6:8080的tomcat

上面没有实现动静分离,因为很少通过apache实现动静分离,所以此处省略

因为apache有很大的好处是可以使用ajp协议

修改上面的配置文件

ProxyPass / ajp://192.168.10.6:8009
//避免重定向保温绕过proxy服务器
ProxyPassReverse / ajp://192.168.10.6:8009

通过 ss -tnlp 查看8009是否被监听了

注意apache此时通过ajp协议和tomcat进行通信,http协议不用了就可以关掉了,关掉的好处是用户想通过浏览器直接访问tomcat访问不到了(浏览器不接受ajp协议),所以如果用apache代理,最好使用ajp协议

所以ajp的好处:高效的(二进制协议)、拒绝用户直接向tomcat发送请求。

重启

service httpd restart

访问 http://172.16.100.6 依然能够访问通

配置user的配置文件,通过tomcat首页发现也能够进入manager页面

配置基于mod_proxy的负载均衡

保证conf.d文件下只有一个mod_proxy.conf或者mod_jk.conf,这里是mod_proxy的所以只留下mod_proxy.conf

这里负载均衡基于

paroxy_balancer_module模块

◇lbmethod:apache实现负载均衡的调度方法,默认是byrequests,即基于权重将统计请求个数进行调度,bytraffic则执行基于权重的流量计数调度 ,bybusyness通过考量每个后端服务器的当前负载进行调度

在httpd.conf的全局配置中配置如下内容:

ProxyRequests Off
//hotcluster是一个名字可以随便取
<proxy balancer: //lbcluster1>
//route-TomcatA  需要在tomcat也必须在Engine定义jvmroot选项
//loadfactor权重
BalancerMember ajp: //172. 16. 100. 1: 8009 loadfactor=10 route-TomcatA
BalancerMember ajp: //172.16. 100.2: 8009 loadfactor=10 route=TomcatB
//lbmethod 负载均衡的调度方
Proxy set lbmethod=bytraffic
</proxy>

<VirtualHost * 80>
ServerAdminadmin@maged.com
Servernamewww.magedu.com
//通过balancer进行反向代理,stickysession -jsessionid  session会话保持
//绑定了sessionid之后就只能在访问一个节点了
//session保持的理解在下面的mod_jk的负载均衡有
ProxyPass / balancer://lbcluster1/ stickysession=JSESSIONID
ProxyPassReverse / balancer://lbclusterl/
</VirtualHost>

访问 http://172.16.100.6/testapp

mod_proxy的balance 模块是有管理页面的

vi httpd.conf
//添加:
<location /lbmanager>
//如果是这个访问路径就走这balancer-manager的处理器
	SetHandler balancer-manager
</location>
ProxyPass /lbmanager ! //这里的!意思是访问的是/lbmanager则不向后面代理

访问:http://172.16.100.6/lbmanager

基于mod_jk(需要编译安装)

单节点

注意:这里使用了lftps,具体根据实际情况安装(自行下载,解压安装)

lftps
cd Sources/tomcat-connector
get tomcat-connector-1.2.37-src.tar.gz
tar -xvf tomcat-connector-1.2.37-src.tar.gz
cd tomcat-connector-1.2.37-src

mod jk是AsF的一个项目,是一个工作于 apache端基于AP协议与 Tomcat通信的逹接器,它是 apache的一个模块,是AP协议的客户端(服务端是 Tomcat的A]P连接器

# tar xf tomcat-connectors-1. 2. 37-src.tar.gz
#cd tomcat-connectors-1.2.37-src/native/
//并没有apxs
rpm -ql httpd | grep apxs
//因为这个功能是他的开发功能,所以需要安装,如果httpd是编译安装的话,这个功能默认就有了,如果是rpm安装的,确保要装上httpd的devel包。
yun -y install httpd-devel
rpm -ql httpd | grep apxs
//   出现   /usr/sbin/apxs  ,这里的路径不容的话注意修改上面的配置
//apxsk能够实现独立像apache添加第三方模块的钩子,任意第三方模块,都必须告诉模块钩子在什么地方,编译完成之后,自动安装在apache所在的目录当中
#./configure --with-apxsk/usr/bin/install/apxs
#make && make install
//如果安装完成会生成一个mod_jk的模块  mod_jk.so
cd /usr/lib64/httpd/modules
//发现有mod_jk.so
ls
cd /etc/httpd/conf.d
//对mod_proxy.conf 进行重命名 mod_proxy.conf.bak

apache要使用modjk逹接器,需要在启动时加载此逹接器模块。为了便于管理与modjk模块相关的配置,这里使用一个专门的配置文件letc/httpd/extra/httpd_jk.conf来保存相关指令及其设置。其内容如下:

#t Load the mod jk
//在配置文件中加载mod_jk.so模块
LoadModule jk module modules/mod jk.so
//使用jk简写的worksfile,一个apache的子进程,mod_jk就是通过子进程来实现向后代理的,这里给出配置文件
//这个配置文件默认不存在,需要自己定义,名称也可以自己定义
JkworkerSfile/etc/httpd/extra/workers.properties
//日志文件保存的目录
JkLogFile logs/mod_jk.log
//模块的日志级别
kLogLevel debug
//把哪些url的访问转发值tomcat,这里表示把根目录下的任何路径,转发到TomcatA
//这里的tomcatA是上面的workers.properties中给tomcat命名的一个名称,叫jvmroot,java虚拟机的路由名称
JkMount /* TomcatA
//状态信息,start1另外一个能够实现工作的work
JkMount /status/ stat1

除了需要使用 Loadmodule指令在 apache中装载模块外, mod jk还需要在 apache的主配置文件中设置其它一些指令来配置其工作属性。如 JkWorkersFile则用于指定保存了worker相关工作属性定义的配置文件, JkLogFile则用于指定mdjk模块的日志文件, JkLogLevel则可用于指定日志的级别(info, error,debug),此外还可以使用JkRequestLogFormat自定义日志信息格式。而 JkMount(格式: JkMount< URL to match>< Tomcat worker name>)指定则用于控制URL与 Tomcat workers的对应关系。

为了让apache能使用/etc/httpd/extra/httpd-jk.conf配置文件中的配置信息,需要编辑/etc/httpd/httpd.conf添加如下一行:

Include/etc/httpd/extra/httpd-jk.conf

对于 apache代理来说,每一个后端的 Tomcat实例中的 engine都可以视作一个 worker,而每一个 worker的地址、连接器的端口等信息都需要在 apache端指定以便 apache可以识别并使用这些 worker。约定俗成,配置这些信息的文件通常为 workers.properties,其具体路径则是使用前面介绍过的 JkwlorkersFi1e指定的,在 apache启动时, mod jk会扫描此文件获取每一个 worker的配置信息。比如,我们这里使用/etehttpd/extra/workers.properties

workers. properties文件一般由商指令组成:一是 mod jk可以连接的各 worker名称列表,二是每一个 worker的属性配置信息。它们分别遵循如下使用语法

worker.list = a comma separated list of worker names
worker. <worker name> .<property> = <property value>

其中 worker.list指令可以重复指定多次,而 worker name则是 Tomcat中 engine组件 jvmRoute参数的值。如

worker. TomcatA host=172.16.100. 1

根据其工作机制的不同, worker有多种不同的类型,这是需要为每个 worker定义的一项属性 woker,< work name>,type.常见的类型如下:

◇ajp13:此类型表示当前 worker为一个运行着的 Tomcat实例,使用ajp1.3向后端建立连接的worker,所以这是一种专门实现反向代理的worker

◇lb:lb即1 oad ba1 ancing,专用于负载均衡场景中的 woker;此 worker并不真正负责处理用户请求,而是将用户请求调度给其它类型为ajp13的 worker 专门负载均衡的

◇status:用户显示分布式环境中各实际 worker工作状态的特殊 worker,它不处理任何请求,也不关联到任何实际工作的 worker实例。具体示例如诮参见后文中的配置 专门输出状态信息的

worker其它常见的属性说明

◇host: Tomcat7的 worker实例所在的主机;

◇port: Tomcat7实例上AJP1.3连接器的端口;

◇ connection_ pool minsize:最少要保存在连接池中的连接的个数;默认为poo1size/2;

◇ connection pool timeout:连接池中连接的超时时长;

◇ mount:由当前 worker提供的 context路径,如果有多个则使用空格格开;此属性可以由Jkmount指令替代;

◇ retries:错误发生时的重试次数;

◇ socket timeout: mod jk等待 worker响应的时长,默认为,即无限等待

◇ socket keepalive:是否启用 keep alive的功能,1表示启用,表示禁用

◇ lbfactor: worker的权重,可以在负载均衡的应用场景中为 worker定义此属性;

另外,在负毂均衡模式中,专用的属性还有:

◇ba1 ance workers:用于负载均衡模式中的各 worker的名称列表,需要注意的是,出现在此处的 worker名称一定不能在任何 worker.1ist属性列表中定义过,并且 worker.list属性中定义的 worker名字必须包含负载均衡 worker。具体示例请参见后文中的定义

◇ method:可以设定为R、τ或B:默认为R,即棖挹请求的个数进行调度:T表示根据已经发送给 worker的实际流贔大小进行调度:B表示根据实际负戟情况进行调度。

◇ sticky session:在将某请求调度至某 worker后,源于此址的所有后续请求都将直接调度至此 worker,实现将用户 session与某 worker綁定,默认为值为1,即启用此功

能。如果后端的各 worker之间支持 sesson复制,则可以将此属性值设为8

根据前文中的指定,这里使用/etc/httpd/extra/workers.properties来定义一个名为Tomcat的worker,并为其指定几个属性,文件内容如下

worker.list=TomcatA, stat1
worker.TomcatA.port=8009
worker.Tomcat.host=172. 16.100. 1
worker.TomcatA.type=ajp13
worker.TomcatA.lbfactor=1
worker statl.type=status
vi mod_jk.conf

#t Load the mod jk
//在配置文件中加载mod_jk.so模块
LoadModule jk module modules/mod jk.so
//使用jk简写的worksfile,一个apache的子进程,mod_jk就是通过子进程来实现向后代理的,这里给出配置文件
//这个配置文件默认不存在,需要自己定义,名称也可以自己定义
JkworkerSfile/etc/httpd/extra/workers.properties
//日志文件保存的目录
JkLogFile logs/mod_jk.log
//模块的日志级别
kLogLevel notice
//把哪些url的访问转发值tomcat,这里表示把根目录下的任何路径,转发到TomcatA
//这里的tomcatA是上面的workers.properties中给tomcat命名的一个名称,叫jvmroot,java虚拟机的路由名称
JkMount /* TomcatA
//状态信息,start1另外一个能够实现工作的work
JkMount /status/ statA
vi workers.properties

worker.list=TomcatA, statA
worker.TomcatA.type=ajp13
worker.TomcatA.port=8009
worker.Tomcat.host=192.168.10.6
worker.TomcatA.lbfactor=1
worker statA.type=status
//检查语法
service httpd configtest
//重启
service httpd restart

至此,一个基于mdjk模块与后端名为 Tomcat的 worker通信的配置已经完成,重启htpd服务即可生效

访问:http://172.16.100.6 到达tomcat页面

访问:http://172.16.100.6/manager/status 能够到达tomcat的管理页面

//查看日志
tail /var/log/httpd/mod_jk.log
tail /awr/log/httpd/access_log

访问:http://172.16.100.6/status 能够输出状态信息

注意:所有的信息详细说明都在上图的legend中

配置基于mod_jk的负载均衡

简单来说就是多家一个work

1、为了避免用户直接访问后端Tomcat实例,影响负载均衡的效果,建议在Tomcat7的各实例上禁用HTTP/1.1连接器。

2、为每一个 Tomcat7实例的引擎添加 jvmRoute参数,并通过其为当前引擎设置全局惟一标识符。如下所示。需要注意的是,每一个实例的 jvmRoute的值均不能相同

< Engine name=” Standalone” defaultHost=”1 localhost” jvmRoute=” Tomcat”>

而后去配置a

修改/etc/httpd/extra/httpd-jk.conf为如下内容

LoadModule
odule modules/mod jk.so
Jkworkersfile/etc/httpd/extra/workers.properties
OkLogFile logs/mod jk. log
JkLogLevel debug
JkMount / lbcluste
JkMount /status/

编辑/etc/httpd/extrayworkers.properties添加如下内容

worker.list lbcluster1, stat1
worker.TomcatA type aj
worker.Tomcat.host = 172.16.100.1
worker.TomcatA.port 8009
worker.Tomcat.bfactor =5
worker.TomcatB.type ajp13
worker.Tomcat.host 172.16 100.2
worker.TomcatB.port =8009
worker.Tomcat.lbfactor =5
worker.lbcluster1.type=1b
worker.lbvA.Sticky_session=0
//把tomcatA和tomcatB归并到lbcluster1
worker.lbcluster1.balance_workers=tomcatA,TomcatB
worker.stat1.type-status
service httpd configtest
service httpd restart

发现有两个节点

在两个tomcat(注意上面是不同的ip)节点中做如下

演示效果,在TomcatA上某context中(如/test),提供如下页面

index.jsp

<%@ page language="java"%>
<html>
	<head><title>TomcatA</title></head>
	<body>
		<h1><font color="red">TomcatA </font></h1>
		<table align" centre" border="1">
		<tr>
		<td>Session ID</td>
		< session setAttribute("abc","abc"):%>
		<td><%- session. getId( %></td>
		</tr>
		<tr>
		<td>Created on</td>
		<td><%- session. getCreationTime ( %></td>
		</tr>
		</table>
	</body>
</html>

演示效果,在TomcatB上某context中(如/test),提供如下页面

index.jsp

<%@ page language="java"%>
<html>
	<head><title>TomcatB</title></head>
	<body>
		<h1><font color="blue">TomcatB </font></h1>
		<table align" centre" border="1">
		<tr>
		<td>Session ID</td>
		< session setAttribute("abc","abc"):%>
		<td><%- session. getId( %></td>
		</tr>
		<tr>
		<td>Created on</td>
		<td><%- session. getCreationTime ( %></td>
		</tr>
		</table>
	</body>
</html>

访问http://172.16.100.6/testapp/

不断刷新会一会tomcatA,一会tomcatB, 并且session的值是一直在发生变化的

,没有绑定session,如果绑定了session,可能就不会负载均衡了

如果不希望一变

修改tomcat的配置文件,session是和jvmRoute属性有关联的

vi tomcat/conf/server.xml
//添加一个jvm路由jvmRoute="TomcatA",跟前端worker保持一致
<Engine name-"Catalina" defaultHost-"localhost" jvmRoute="TomcatA">
vi tomcat/conf/server.xml
//添加一个jvm路由jvmRoute="TomcatB",跟前端worker保持一致
<Engine name-"Catalina" defaultHost-"localhost" jvmRoute="TomcatB">

编辑/etc/httpd/extrayworkers.properties修改如下内容

worker.lbvA.Sticky_session=1

session会话保持

注意上面的mod_proxy和mod_jk负载均衡通过stack session保持session,破坏了负载均衡,该怎么办呢?session复制和session服务器

    session复制:

    tomcat支持session集群,仅能够在小规模节点中使用的方式。

    在节点之间通过多播或广播等方式,来实现sessoin会话的共享,每一个节点在本地接受用户会话之后,会将会话信息,通过网络发送给其他节点,因为每个节点都有整个集群中的所有会话信息,如果有三十万个会话,意味着每个节点上都有三十万个会话,消耗资源,每个节点的会话,都要复制多份给其他的主机,带宽占用量很大,所以这种集群方式,不太适用有较多节点的服务

    所以将session放在一个高兴能的服务器中
    session服务器:

    tomcat支持将会话保存在memcached中。

    双写:在两个memcached中都写一份

memcached是保存在内存中,如果断点了呢?所以还可以是一些具有持久功能的服务器比如redis

Tomcat会话管理

12、 Manager

Manger对象用于实现HP会话管理的功能, Tomcat6中有5种 Manger的实现:

    StandardManager

    Tomcat6的默认会话管理器,用于非集群环境中对单个处于运行状态的 Tomcat实例会话进行管理。当 Tomcat关闭时,这些会话相关的数据会被写入磁盘上的一个名叫 SESSION.ser的文件,并在 Tomcat下次启动时读取此文件。但是断电的情况下是来不及的。
    PersistentManager

    当一个会话长时间处于空闲状态时会被写入到swap(磁盘)会话对象,这对于内存资源比较吃紧的应用环境来说比较有用,断电的情况下有用,但是那些没来得及写在磁盘上的还是会丢失
    DeltaManager

    用于 Tomcat 集群(复制集群)的会话管理器,它通过将改变了会话数据同步给集群中的其它节点实现会话复制。这种实现会将所有会话的改变同步给集群中的每一个节点,也是在集群环境中用得最多的一种实现方式,就是上面的session复制,十分不适用于大规模节点的服务,对于中型的(三五台)就已经很消耗资源了,两三台还是可以的。
    BackupManager

    用于 Tomcat-集群的会话管理器,与 DeltaManager不同的是,某节点会话的改变只会同步给集群中的另一个而非所有节点,万一其中一个节点发生故障,另一还还是有保存的,而且不会复制太多。但是如果全部断电呢?

    注意:DeltaManager和BackupManager都是保存在内存中的,对于断电是不可避免的
    SimpleTcpReplication Manage

    Tomcat4时用到的版本,过于老旧了

13、 Stores

PersistentManager必须包含一个 Store元素以指定将会话数据存储至何处。这通常有两种实现方式: Filestore和] DBCStore

14、 Resources

经常用于实现在 Context中指定需要装载的但不在 Tomcat本地磁盘上的应用资源,如]ava类,HTM页面,]5P文件等。

15、cluster

专用于配置 Tomcat集群的元素,可用于 Engine和Host容器中,在用于 Engine容器中时, Engine中的所有Host均支持集群功能。在 Cluster元素中,需要直接定义一个 Manage

r元素,这个 Manager元素有一个其值为og. apache. cata1 ina. ha, session. DeltaManager或org. apache, catalina.ha, session

BackupManager的c1 assName属性。同时, Cluster中还需要分别定义一个 Channel和 ClusterListener元素

15.1、 Channel

用于cluster中给集群中同一组中的节点定义通信“信道”。 Channel中需要至少定以Membership(成员关系管理)、 Receiver(接收管理)和 Sender(发送管理)三个元素,此外还有一个可选元素 Interceptor(检查会话信息)。每个节点可以有多个虚拟主机,节点集群中都是相同的,所以每个节点的虚拟主机a就是一组,虚拟主机a和虚拟主机b(这里的a b只是举个栗子)都是互不干扰的,而channel就是用来节点之间通信的。

15.2、 Membership

用于 Channel中配置同一通信信道上节点集群组中的成员情况,即监控加入当前集群组中的节点并在各节点间传递心跳信息,而且可以在接收不到某成员的心跳信息时将

从集群节点中移除。 Tomcat6中 Membership的实现是org. apache. catalina, tribes, membership. Mcastservice。

15.3、 Sender

用于 Channe1中配置“复制信息”的发送器,实现发送需要同步给其它节点的数据至集群中的其它节点。发送器不需要属性的定义,但可以在其内部定义一个 Transport元素

15.4 Transpor

用于 Sender内部,配置数据如何发送至集群中的其它节点。 Tomcat6有两种 Transport的实现

    PooledMultiSender

    基于]ava阻塞式IO,可以将一次将多个信息并发发送至其它节点,但一次只能传送给一个节点

    2 )PooledParallelSener

    基于]ava非阻塞式I0,即NIO,可以一次发送多个信息至一个或多个节点。

15.5 Receiver

用于 Channe1定义某节点如何从其它节点的 Sender接收复制数据, Tomcat6中实现的接收方式有两种 BioReceiver和 NioReceiver

标准会话管理器和持久会话管理器

标准会话管理器( StandardManager):

<Manager className="org. apache. catalina. session. StandardManager
//最大保持时间
maxInactiveInterval=7200"/>

默认保存于$ CATALINA HOME/rk/Cata1ina/< hostname》/< webapp-name>/下的 SESSIONS,ser文件中。

maxActiveSessions:最多允许的活动会话数量,默认为-1,表示不限制;

axInactivelnterya1:非活动的会话超时时长,默认为60s;

athname:会话文件的保存目录;

持久会话管理器( PersistentManager)

将会话数据保存至持久存储中,并且能在服务器意外中止后重新启动时重新加载这些会话信息。持久会话管理器支持将会话保存至文件存储(Fi1 eStore)

或JDBC存储( JDBCStore)中

保存至文件中的示例

<Manager className"org. apache. catalina. session. PersistentManage
//重启的时候要不要保存到磁盘上去
saveOnRestart=true">
<Store className="org. apache. catalina. session. Filestore
//保存的目录
directory=/data/tomcat-sessions"/>
</Manager>

每个用户的会话会被保存至 directory指定的目录中的文件中,文件名为< session id, session,并通过后台线程每隔一段时间(

checkInterva1参数定义,默认为60秒)检查一次超时会话

保存至JDBCStorel中的示例

<Manager className="org. apache. catalina. session. PersistentManager
saveonRestart=true>
<Store className="org. apache. catalina. sessionlJDBCStore
driver Name="com. mysql jdbc Driver
connectionURL-"jdbc: mysql: //localhost: 3306/mydb?user=jb; pas sword=pw"/>

负载均衡,且实现会话綁定要注意给每个 tomcat实例的 egine容器一个 jvmRoute属性!此名称要跟前端调度模块使用名称保持一致!

另外,在mod_proy实现负载均衡的会话绑定时,还要使用 sticksession=JSESSIONID(字符要大写)!

需要在Engine或者host容器中添加一个cluster的组件,明确打开session集群(tomcat会话集群)

session复制

Tomcat Cluster配置:

注意 Membership和 Receiver

如果对整体的Engine做cluster,就放在nginx中,如果只对某一个主机做集群,就放在某个特定的host中

//所使用的类SimpleTcpCluster
<Cluster CyassName="org.apache.catalina.ha.tcp.SimpleTcpCluster"
//指明会话管理器为deltamanager
	<Manager className="org.apache.catalina.ha.session.DeltaManager"
	expireSessionsonShutdown="false"
	notifyListenersOnReplication="true"/>
	<Channel className="org.apache.catalina.tribes.group.Group.Channel">
	//使用McastService来实现,多播的方式
	<Membership className="org.apache.catalina.tribes.membership.McastService"
		//多播的地址
		address="228.0.0.4"
		//端口
		port="45564"
		//每隔多久向外播放一次自己的心跳信息 ms
		frequency="500"
		//如果多久没有获得对方的心跳,就将对方设置为不可用的  ms
		dropTime="3000"/>
	//接受其他人的心跳会话信息,NioReceiver,高效的网络通信方式
	<Receiver className"org. apache. catalina. tribes. transport nio. NioReceiver"
		//跟其他主机传递心跳和会话机制使用的外部的ip地址,一定不能使127.0.0.1
		//如果只有一个网卡,而且只有一个跟其他主机通信的地址,auto即可
		//如果有多块网卡,一个面向前端的主机,另外一个专门用来实现心跳信息传递和绘画信息传递。
		//那么这里就需要写成心跳传递的网卡。
		address="auto"
		//端口
		port="4000"
		//自动绑定,我们一次性可以接收多少个
		autoBind="100"
		//挑选的超时时间,receiver进来很多会话和心跳信息,要判断哪个可以哪个不可用
		selectortimeout= "5000"
		//最大线程数
		maxThread="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.TcpFailure.Detector"/>
	<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor "/
	/channel>
	//这两个保持默认就行
	<Valve className"org.apache.catalina.ha.tcp.Replication.Valve"
	filter=""/>
	<Valve className="org.apache.catalina.ha.session. vmRouteBindervalve"/>
	<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
		tempDir="/tmp/war-temp/"
		deployDir="/tmp/war-deploy/"
		watchDira"/tmp/war-listen/"
		watchEnabled="false"/>
//监听器,jvm中各个节点之间一些内部的信息传递的工具
	<ClusterListener className="org. apache. catalina.ha.session.JvmRouteSessionIDBinderListener"/>
	<ClusterListener className"org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

172.16.100.6 172.16.100.7 两个主机

cd tomcat/conf
//备份server.xml
cp server.xml server.xml.bak
vi server.xml
//找到Engine,在Engine内部粘贴就可以
<Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatB">
//注意可能粘贴的时候格式乱了,这个时候可以选择用  nano(和vim作用差不多)

//修改membership中的 address="228.101.60.4" (举个栗子),注意两个tomcat使用一样的
//reciver的地址使用auto就可以,其他的都不用改

把相同的配置复制到172.16.100.7节点上

修改

//修改为TomcatB
<Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatB">
//多播地址保持一致,不用修改,reciver还用auto即可

注意 这个配置tomcat6、7、8可能是不一样的,最好到tomcat官网查看详细文档

例如在tomcat7中

确保web.xml中有distributable

如果WEB-INF目录下没有,会使用tomcat/conf目录下默认的web.xml

两个节点都要添加

vi web.xml
//在和<servlet>同级的地方加上
<distributable/>

可能会报错 invalid argument

命令行执行

//添加一个路由,目标网络228.0.0.4 实际地址格式255.255.255.255
//route文章https://blog.csdn.net/u011857683/article/details/83795435
route add -net 228.0.0.4 netmask 255.255.255.255 dev eth0

发现有waitFormembers等字样,在等待另一个节点,启动另一个,再查看日持,发现已经开始传递了

访问 http://172.16.100.6/testapp

session会话信息是不变的

总结:构建 DeltaManager集群步骤:

1、在各节点的server.xml的engine后host容器添加如上内容:注意修改membership组件中的address=“xxx.x.xx.x” 建议修改reciver中的address为本机能够传递心跳信息的地址

2、在各节点为使用的组播地址添加组播路由 格式:

route add -net $MACAST_ADDRESS netmask 255.255.255.255 dev eth0

3、在相应应用程序的web.xml中添加

这种方式只适用于小规模节点的项目。

session服务器

一个开源项目(支持memcached和couchbase)

Msm:http://code.googlecom/p/memcached-session-manager/

http://repol.mavenorg/maven2/de/javakaffee/msm/

可以谷歌搜索关键字 tomcat memcached session等

支持tomcat6、7、8 点击网站中的wiki有配置详细说明

配置tomat1默认优先使用memcached2,通过类似双写机制,会话也保存在memcached1中,如果memcached2发生故障,就会使用memcached1的。

需要将jar包放在tomcat目录的相应目录下

放在tomcat的lib目录下

此外还需要几个文档,这几个文档是为了将会话序列化的,因为要将会话保存在memcached中,数据必须是可序列化的,即上图第二个方框的内容也放入到lib目录下

定义在context或者host(如果没有context 的情况下)中

具体内容查看官方网站

<Context>
	<Manager Name="de.avakaffee.web.msm.MemcachedBackupSessionManager"
	//定义两个节点的服务器地址和端口自
	memcachedNodes="nl: host1. yourdomain com: 11211, n2: host2. yourdomain com:11211"
	//备用节点n1
	failoverNodes="n1"
	//对于那些不做session缓存,图片等会导致session缓存命中率低下
	reqstUriIgnorePattern=". \. (ico|pngl|gif|jpg|css|js)$"
	//序列化工具,这里使用哪个,上面图中的jar文件就应该放在lib目录中
	transcoderFactoryclass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
	/>
</Context>

附 如果是php的话,如何将会话保存到memcached中

前提:

1、配置各php支持使用 memcache

2、安装配置好 memcached服务器,这里假设其地址为172.16.208.11,端口为11211:

、配置php将会话保存至 memcached中

编辑php.ini文件,确保如下两个参数的值分别如下所示:

session.save_handler=memcache
//persistent基于持久连接方式  weight权重为1  timeout超时时间  interval重试时间点
session.save_path="tcp://172 16.200. 11: 11211?persistent=1&weight=1&timeout=1&retry_interval=15

测试

新建php页面 setsess,php,为客户端设置启用 session

<?php
sessioni_start();
if (!iss($_SESSION['www.MageEdu.com'])){
	$_SESSION['www.MageEdu.com']=time();
}
print $_SESSION['www.MageEdu.com'];
print "<br><br>";
print "Session ID: " . session_id();
?>

新建php页面 showsess,php,获取当前用户的会话ID

<?php
session_start();
Memcache obj = new Memcache;
Memcache_ obj->connect('172 16.200. 11', 11211);
Smysess=session_id();
var_dump($Memcache_obj->get($mysess));
Memcache_obj->close();

不错的站点(外面)推荐

www.sourceforge.org

www.slideshare.net

www.wordpress.com

http://codegoogle.com

http://www.github.com

Tomcat负载均衡、调优核心应用进阶学习笔记(三):LNMT nginx+tomcat、LAMT apache+tomcat、session会话保持、不错的站点的相关教程结束。

《Tomcat负载均衡、调优核心应用进阶学习笔记(三):LNMT nginx+tomcat、LAMT apache+tomcat、session会话保持、不错的站点.doc》

下载本文的Word格式文档,以方便收藏与打印。