- 會(huì)話保持
- Tomcat Cluster
- Tomcat實(shí)現(xiàn)會(huì)話粘滯
- Tomcat實(shí)現(xiàn)會(huì)話集群
- Tomcat實(shí)現(xiàn)會(huì)話服務(wù)器
一、會(huì)話保持
三種實(shí)現(xiàn)方式:
- session sticky:會(huì)話粘滯
- source_ip:源IP地址綁定
nginx: ip_hash
haproxy: source
lvs: sh - cookie:cookie綁定
nginx:hash
haproxy: cookie
- source_ip:源IP地址綁定
- session cluster:會(huì)話集群
delta session manager - session server:會(huì)話服務(wù)器
redis(store), memcached(cache)
二、Tomcat Cluster:Tomcat 集群
httpd或nginx作為調(diào)度器,三種實(shí)現(xiàn)方式:
- nginx + tomcat cluster
- httpd + tomcat cluster
httpd: mod_proxy, mod_proxy_http, mod_proxy_balancer
tomcat cluster: http connector - httpd + tomcat cluster
httpd: mod_proxy, mod_proxy_ajp, mod_proxy_balancer
tomcat cluster: ajp connector
(一)nginx作為調(diào)度器
(1)配置tomcat cluster
ntpdate 172.18.0.1
// 分別將兩臺(tái)主機(jī)命名為node1.hellopeiyang.com和node2.hellopeiyang.com
hostnamectl set-hostname node1.hellopeiyang.com
hostnamectl set-hostname node2.hellopeiyang.com
yum install java-1.8.0-openjdk-devel tomcat tomcat-webapps tomcat-admin-webapps tomcat-docs-webapp tomcat-webapps
systemctl start tomcat
mkdir -pv /usr/share/tomcat/webapps/myapp/WEB-INF
vim /usr/share/tomcat/webapps/myapp/index.jsp
// node1主機(jī)上的內(nèi)容
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.magedu.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("magedu.com","magedu.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
// node2主機(jī)上的內(nèi)容
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">TomcatB.magedu.com</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("magedu.com","magedu.com"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
分別測(cè)試node1和node2的tomcat服務(wù),成功運(yùn)行


(2)配置nginx調(diào)度器
ntpdate 172.18.0.1
yum install nginx
systemctl start nginx
hostnamectl set-hostname www.hellopeiyang.com
vim /etc/nginx/nginx.conf
upstream tcsrvs {
server 192.168.136.130:8080;
server 192.168.136.131:8080;
}
server {
listen 80 default_server;
server_name www.hellopeiyang.com;
root /usr/share/nginx/html;
location / {
proxy_pass http://tcsrvs;
}
}
nginx -t
nginx -s reload
登錄nginx服務(wù)器的文本服務(wù),成功調(diào)度


(二)httpd作為調(diào)度器,通過(guò)http協(xié)議
-
BalancerMember:定義后端服務(wù)器
語(yǔ)法:BalancerMember [balancerurl] url [key=value [key=value ...]]status:狀態(tài)
D:服務(wù)器不可用
H:服務(wù)器只有在其他服務(wù)器都不可用時(shí)才提供服務(wù)loadfactor:負(fù)載因子,即權(quán)重
lbmethod:調(diào)度算法
byrequests:默認(rèn),按照設(shè)置的權(quán)重調(diào)度,相當(dāng)于wrr
bytraffic:按照流量調(diào)度
bybusyness:按照存在的連接調(diào)度,相當(dāng)于lc-
實(shí)現(xiàn)httpd通過(guò)http協(xié)議調(diào)度
- tomcat cluster 保持不變,現(xiàn)在配置httpd服務(wù)
ntpdate 172.18.0.1
yum install httpd
vim /etc/httpd/conf.d/httpd-tomcat.conf
<proxy balancer://tcsrvs>
BalancerMember http://192.168.136.130:8080
BalancerMember http://192.168.136.131:8080
ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
ServerName www.hellopeiyang.com
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/
ProxyPassReverse / balancer://tcsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
systemctl start httpd
測(cè)試成功進(jìn)行調(diào)度

(三)httpd作為調(diào)度器,通過(guò)ajp協(xié)議
- tomcat cluster 保持不變,現(xiàn)在配置httpd服務(wù)
mv /etc/httpd/conf.d/httpd-tomcat.conf /etc/httpd/conf.d/httpd-tomcat.conf.bak
vim /etc/httpd/conf.d/ajp-tomcat.conf
<proxy balancer://tcsrvs>
BalancerMember ajp://192.168.136.130:8009 loadfactor=2
BalancerMember ajp://192.168.136.131:8009 loadfactor=1
ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
ServerName www.hellopeiyang.com
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/
ProxyPassReverse / balancer://tcsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
httpd -t
systemctl restart httpd
測(cè)試成功按照權(quán)重進(jìn)行調(diào)度

當(dāng)后端服務(wù)器出現(xiàn)故障不能提供服務(wù)時(shí),調(diào)度器具備健康狀態(tài)檢查功能;
當(dāng)將后端node2服務(wù)器的tomcat服務(wù)關(guān)閉時(shí),自動(dòng)全部調(diào)度至node1

(四)啟用httpd的調(diào)度器管理接口
vim /etc/httpd/conf.d/ajp-tomcat.conf // 添加以下幾行內(nèi)容
<Location /balancer-manager>
SetHandler balancer-manager
ProxyPass !
Require all granted // 演示用,實(shí)際工作要具體設(shè)置權(quán)限,并設(shè)置賬號(hào)認(rèn)證
</Location>
systemctl restart httpd

三、Tomcat實(shí)現(xiàn)會(huì)話粘滯(session sticky)
httpd實(shí)現(xiàn)通過(guò)cookie會(huì)話粘滯
原理:客戶端的第一次請(qǐng)求調(diào)度至后方主機(jī)后,響應(yīng)報(bào)文經(jīng)過(guò)調(diào)度器時(shí)會(huì)添加cookie說(shuō)明具體被調(diào)度至后方哪一臺(tái)主機(jī)。此后客戶端的請(qǐng)求報(bào)文報(bào)文都會(huì)附帶此cookie信息,調(diào)度器通過(guò)cookie信息調(diào)度至第一次調(diào)度到的主機(jī),實(shí)現(xiàn)會(huì)話粘滯。
實(shí)現(xiàn)過(guò)程:主要是在httpd服務(wù)器上對(duì)balancer設(shè)定不同的cookie_ID
vim /etc/httpd/conf.d/ajp-tomcat.conf
// 添加自定義cookie屬性ROUTEID
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e;path=/" env=BALANCER_ROUTE_CHANGED
<proxy balancer://tcsrvs>
// 給cookie的ROUTEID賦值,下一條語(yǔ)句作用相似
BalancerMember ajp://192.168.136.130:8009 loadfactor=2 route=TomcatA
BalancerMember ajp://192.168.136.131:8009 loadfactor=1 route=TomcatB
ProxySet lbmethod=byrequests
// 設(shè)置以ROUTEID作為會(huì)話粘滯的依據(jù)
ProxySet stickysession=ROUTEID // 設(shè)置以ROUTEID作為會(huì)話粘滯的依據(jù)
</Proxy>
<VirtualHost *:80>
ServerName www.hellopeiyang.com
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://tcsrvs/
ProxyPassReverse / balancer://tcsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
<Location /balancer-manager>
SetHandler balancer-manager
ProxyPass !
Require all granted
</Location>
httpd -t
systemctl reload httpd
在瀏覽器上測(cè)試成功,從客戶端的第二次請(qǐng)求開(kāi)始,請(qǐng)求報(bào)文都包含有cookie信息,內(nèi)容中存在設(shè)置的ROUTEID

- 通過(guò)http協(xié)議實(shí)現(xiàn)負(fù)載均衡、會(huì)話粘滯與ajp協(xié)議下的實(shí)現(xiàn)非常相似,只需修改http協(xié)議與端口號(hào)即可,不再贅述
四、Tomcat實(shí)現(xiàn)會(huì)話集群(session cluster)
實(shí)現(xiàn)原理:與會(huì)話粘滯通過(guò)配置調(diào)度器實(shí)現(xiàn)不同,會(huì)話集群是通過(guò)設(shè)置后臺(tái)tomcat服務(wù)器,在tomcat服務(wù)器集群的內(nèi)部主機(jī)中以多播通信同步會(huì)話信息,實(shí)現(xiàn)會(huì)話保持的
實(shí)現(xiàn)過(guò)程:在每臺(tái)tomcat服務(wù)器上執(zhí)行以下配置
// 配置啟用集群,將下列配置放置于<engine>或<host>中
vim /etc/tomcat/server.xml
<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.58.5.8" // 多播地址必須相同
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="192.168.136.132" // 填入每臺(tái)服務(wù)器的ip地址
port="4000"
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>
// 確保Engine的jvmRoute屬性配置正確
<Engine name="Catalina" defaultHost="localhost" jvmRoute="TomcatA"> //每個(gè)服務(wù)器的jvmRoute值不同
// 配置webapps
vim /usr/share/tomcat/webapps/myapp/WEB-INF/web.xml
<distributable/> // 在web-app標(biāo)簽下添加
// 重啟tomcat服務(wù)
systemctl restart tomcat
調(diào)度器可以使用nginx, httpd調(diào)度,在瀏覽器測(cè)試,成功進(jìn)行了session cluster


從測(cè)試結(jié)果看出:盡管調(diào)度器分別調(diào)度至后臺(tái)的兩臺(tái)tomcat服務(wù)器,但是兩臺(tái)服務(wù)器提供服務(wù)的session id相同,證明通過(guò)集群實(shí)現(xiàn)了會(huì)話保持
五、Tomcat實(shí)現(xiàn)會(huì)話服務(wù)器(session server)
(一)memcached:高性能、分布式的內(nèi)存對(duì)象緩存系統(tǒng)
(1)特性:
- k/v cache:僅可存儲(chǔ)可序列化數(shù)據(jù);存儲(chǔ)項(xiàng):k/v
- 智能性一半依賴(lài)于客戶端(調(diào)用memcached的API開(kāi)發(fā)程序),一半依賴(lài)于服務(wù)端
- 分布式緩存:互不通信的分布式集群
- 分布式系統(tǒng)請(qǐng)求路由方法:取模法,一致性哈希算法,算法復(fù)雜度:O(1)
- 清理過(guò)期緩存項(xiàng):
- 緩存耗盡:LRU,最近最少使用算法
- 緩存項(xiàng)過(guò)期:惰性清理機(jī)制(標(biāo)記過(guò)期緩存而不刪除,新緩存直接覆蓋舊緩存,減少了系統(tǒng)開(kāi)銷(xiāo))
(2)安裝配置:
- 由CentOS 7 base倉(cāng)庫(kù)直接提供:
yum install memcached - 監(jiān)聽(tīng)的端口:
11211/tcp, 11211/udp - 文件結(jié)構(gòu):
主程序:/usr/bin/memcached
配置文件:/etc/sysconfig/memcached
Unit File:memcached.service - 協(xié)議格式:memcached協(xié)議
文本格式,易理解,效率低
二進(jìn)制格式,效率高
(3)命令:
- 統(tǒng)計(jì)類(lèi):stats, stats items, stats slabs, stats sizes
- 存儲(chǔ)類(lèi):set, add, replace, append, prepend
- 命令格式:
<command name> <key> <flags> <exptime> <bytes> <cas unique> - 檢索類(lèi):get, delete, incr/decr
- 清空:flush_all
(4)memcached程序的常用選項(xiàng):
- -m <num>:緩存的最大內(nèi)存空間,默認(rèn)64MB
- -c <num>:最大并發(fā)連接,默認(rèn)1024
- -u <username>:以指定的用戶身份來(lái)運(yùn)行進(jìn)程
- -l <ip_addr>:監(jiān)聽(tīng)的IP地址,默認(rèn)為本機(jī)所有地址
- -p <num>:監(jiān)聽(tīng)的TCP端口, 默認(rèn)11211
- -U <num>:監(jiān)聽(tīng)的UDP端口,默認(rèn)11211,當(dāng)為0時(shí)為關(guān)閉UDP監(jiān)聽(tīng)
- -M:內(nèi)存耗盡時(shí),不執(zhí)行LRU清理緩存,而是拒絕存入新的緩存項(xiàng),直到有多余的空間可用時(shí)為止
- -f <factor>:增長(zhǎng)因子;默認(rèn)是1.25
- -t <threads>:?jiǎn)?dòng)的用于響應(yīng)用戶請(qǐng)求的線程數(shù)
(二)實(shí)現(xiàn)memcached緩存下的session server
(1)實(shí)現(xiàn)環(huán)境:
使用memcached-session-manager作為會(huì)話管理器,需要下載相應(yīng)的jar包
項(xiàng)目地址:https://github.com/magro/memcached-session-manager
(2)實(shí)現(xiàn)過(guò)程:
- 項(xiàng)目地址下載相關(guān)的jar包,并復(fù)制jar包至tomcat的庫(kù)目錄中
cp memcached-session-manager-${version}.jar /usr/share/java/tomcat/
cp memcached-session-manager-tc${6,7,8}-${version}.jar /usr/share/java/tomcat/
cp spymemcached-${version}.jar /usr/share/java/tomcat/
cp msm-kryo-serializer-${version}.jar /usr/share/java/tomcat/
cp kryo-serializers-${0.34+}.jar /usr/share/java/tomcat/
cp kryo-${3.x}.jar /usr/share/java/tomcat/
cp minlog.${version}.jar /usr/share/java/tomcat/
cp reflectasm.${version}.jar /usr/share/java/tomcat/
cp asm-${5.x}.jar /usr/share/java/tomcat/
cp objenesis-${2.x}.jar /usr/share/java/tomcat/
- 分別在兩個(gè)tomcat上的某host上定義一個(gè)用于測(cè)試的context容器,并在其中創(chuàng)建一個(gè)會(huì)話管理器
vim /etc/tomcat/server.xml
<Context path="/myapp" docBase="/usr/share/tomcat/webapps/myapp" reloadable="true">
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.136.131:11211,n2:192.168.136.132:11211"
failoverNodes="n2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
- 測(cè)試用例仍舊使用之前的myapp應(yīng)用,啟動(dòng)memcached和tomcat服務(wù)
systemctl start memcached
systemctl start tomcat
- 調(diào)度器服務(wù)器上使用nginx或httpd配置轉(zhuǎn)發(fā),方法如上文,不再贅述
在瀏覽器中測(cè)試,可以確定session ID在負(fù)載均衡環(huán)境中保持不變

