Tomcat-03-session集群+安全
Tomcat Session集群
参考文档:https://tomcat.apache.org/tomcat-9.0-doc/cluster-howto.html
1 | <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" |
配置说明
- Cluster集群配置
- Manager会话管理器配置
- Channel信道配置
- Membership成员判定。使用什么多播地址、端口多少、间隔时长ms、超时时长ms。同一
个多播地址和端口认为同属一个组。使用时修改这个多播地址,以防冲突 - Receiver接收器,多线程接收多个其他节点的心跳、会话信息。默认会从4000到4100依次
尝试可用端口。- address=”auto”, auto可能绑定到127.0.0.1上,所以一定要改为可以用的IP上去
- Sender多线程发送器,内部使用了tcp连接池。
- Interceptor拦截器
- Membership成员判定。使用什么多播地址、端口多少、间隔时长ms、超时时长ms。同一
- Valve
- ReplicationValve检测哪些请求需要检测Session,Session数据是否有了变化,需要启动复
制过程
- ReplicationValve检测哪些请求需要检测Session,Session数据是否有了变化,需要启动复
- ClusterListener
- ClusterSessionListener集群session侦听器
使用<cluster className="org.apache.catalina.ha.tcp.simpleTcpCluster" / >
添加到<Engine>
所有虚拟主机都可以启用Session复制
添加到<Host>
,该虚拟主机可以启用Session复制
最后,在应用程序内部启用了才可以使用
前提:
- 时间同步,确保NTP或Chrony服务正常运行。
systemctl status chronyd
- 防火墙规则。
systemctl stop firewalld
IP | 主机名 | 服务 | |
---|---|---|---|
192.168.142.151 | t0 | 调度器 | Nginx、Httpd |
192.168.142.152 | t1 | tomcat1 | JDK8、Tomcat8 |
192.168.142.153 | t2 | tomcat2 | JDK8、Tomcat8 |
本次把多播复制的配置放到缺省虚拟主机里面,即Host之下。
特别注意修改Receiver的address属性为一个本机可对外的IP地址。
t2的server.xml中,如下
1 | <Host name="t1.kinmfer.com" appBase="/data/webapps" autoDeploy="true" > |
t3的server.xml中,如下
1 | <Host name="t2.kinmfer.com" appBase="/data/webapps" autoDeploy="true" > |
Tomcat重启后,ss命令能看到tomcat监听在4000端口上
尝试使用刚才配置过得负载均衡(移除Session黏性),测试发现Session还是变来变去。
准备web.xml
在应用中增加WEB-INF,从全局复制一个web.xml过来
1 | cp /usr/local/tomcat/conf/web.xml /data/webapps/ROOT/WEB-INF/ |
为web.xml的<web-app>
标签增加子标签<distributable/>
来开启该应用程序的分布式。
重启全部Tomcat,通过负载均衡调度到不同节点,返回的SessionID不变了。
NoSQL
NoSQL是对非SQL、非传统关系型数据库的统称。
NoSQL一词诞生于1998年,2009年这个词汇被再次提出指非关系型、分布式、不提供ACID的数据库设
计模式。
随着互联网时代的到来,数据爆发式增长,数据库技术发展日新月异,要适应新的业务需求。
随着移动互联网、物联网的到来,大数据的技术中NoSQL也同样重要。
https://db-engines.com/en/ranking
分类
- Key-value Store
- redis、memcached
- Document Store
- mongodb、CouchDB
- Column Store列存数据库,Column-Oriented DB
- HBase、Cassandra
- Graph DB
- Neo4j
- Time Series时序数据库
- InfluxDB
Memcached
Memcached只支持能序列化的数据类型,不支持持久化,基于Key-Value的内存缓存系统。
内存分配机制
应用程序运行需要使用内存存储数据,但对于一个缓存系统来说,申请内存、释放内存将十分频繁,非
常容易导致大量内存碎片,最后导致无连续可用内存可用。
Memcached采用了Slab Allocator机制来分配、管理内存。
- Page:分配给Slab的内存空间,默认为1MB,分配后就得到一个Slab。Slab分配之后内存按照固
定字节大小等分成chunk。 - Chunk:用于缓存记录kv值的内存空间。Memcached会根据数据大小选择存到哪一个chunk中,
假设chunk有128bytes、64bytes,数据只有100bytes存储在128bytes中,存在些浪费。- Chunk最大就是Page的大小,即一个Page中就一个Chunk
- Slab Class: Slab按照大小分组,就组成不同的Slab Class
懒过期Lazy Expiration
memcached不会监视数据是否过期,而是在取数据时才看是否过期,过期的把数据有效期限标识为0
并不清除该数据。以后可以覆盖该位置存储其它数据。
LRU
当内存不足时,memcached会使用LRU (Least Recently Used)机制来查找可用空间,分配给新纪录使用。
集群
Memcached集群,称为基于客户端的分布式集群。
Memcached集群内部并不互相通信,一切都需要客户端连接到Memcached服务器后自行组织这些节点,并决定数据存储的节点。
安装
1 | dnf install -y memcached |
修改memcached运行参数,可以使用下面的选项修改/etc/sysconfig/memcached文件
- -u username memcached运行的用户身份,必须普通用户
- -p 绑定的端口,默认11211
- -m num最大内存,单位MB,默认64MB
- -c num最大连接数,缺省1024
- -d 守护进程方式运行
- -f 增长因子Growth Factor,默认1.25
- -v 详细信息,-vv能看到详细信息
- -M 内存耗尽,不许LRU
- -U 设置UDP监听端口,0表示禁用UDP
session共享服务器
msm
msm (memcached session manager)提供将Tomcat的session保持到memcached或redis的程序,可以实现高可用。
目前项目托管在Github,https://github.com/magro/memcached-session-manager
支持Tomcat的6.x、7.x、8.x、9.x。
- Tomcat的Session管理类,Tomcat版本不同
- memcached-session-manager-2.3.2.jar
- memcached-session-manager-tc8-2.3.2.jar
- Session数据的序列化、反序列化类
- 官方推荐kyro
- 在webapp中WEB-INF/lib/下
- 驱动类
- memcached(spymemcached.jar)
- Redis(jedis.jar)
安装
https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
将spymemcached.jar、memcached-session-manage、kyro相关的jar文件都放到Tomcat的lib目录中
去,这个目录是$CATALINA_HOME/lib/
,对应本次安装就是/usr/local/tomcat/lib。
1 | asm-5.2.jar |
sticky模式
原理
当请求结束时Tomcat的session会送给memcached备份。即Tomcat session为主session,
memcached session为备session,使用memcached相当于备份了一份Session。
查询Session时Tomcat会优先使用自己内存的Session,Tomcat通过jvmRoute发现不是自己的
Session,便从memcached中找到该Session,更新本机Session,请求完成后更新memcached。
部署
1 | <t1> <t2> |
t1和m1部署在一台主机上,t2和m2部署在同一台。
配置
放到$CATALINA_HOME/conf/context.xml
中
特别注意,t1配置中为failoverNodes=”n1”,t2配置为failoverNodes=”n2”
1 | 以下是sticky的配置 |
memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"
memcached的节点们; n1、n2只是别名,可以重新命名。
failoverNodes故障转移节点,n1是备用节点,n2是主存储节点。另一台Tomcat将n1改为n2,其主节
点是n1,备用节点是n2。
实验
如果配置成功,可以在logs/catalina.out中看到下面的内容
1 | 信息 [t1.kinmfer.com-startStop-1] |
配置成功后,网页访问以下,页面中看到了Session。然后运行下面的Python程序,就可以看到是否存储到了memcached中了。
1 | import memcache # pip install python-memcached |
t1、t2、n1、n2依次启动成功,分别使用http://t1.kinmfer.com:8080/和http://t2.kinmfer.com:8080/观察。
看起负载均衡调度器,通过http://t0.kinmfer.com来访问看看效果
1 | on tomcats |
可以看到浏览器端被调度到不同Tomcat上,但是都获得了同样的SessionID。
non-sticky模式
原理
从msm 1.4.0之后开始支持non-sticky模式。
Tomcat session为中转Session,如果n1为主session,n2为备session。产生的新的Session会发送给主、备memcached,并清除本地Session。
n1下线,n2转正。n1再次上线,n2依然是主Session存储节点。
memcached配置
放到$CATALINA_HOME/conf/context.xml
中
1 | 以下是non-sticky的配置 |
redis配置
下载jedis.jar,放到$CATALINA_HOME/lib/
,对应本次安装就是/usr/local/tomcat/lib。
1 | dnf install redis -y |
放到$CATALINA_HOME/conf/context.xml
中
1 | 以下是non-sticky的配置 |
Session粘性总结
通过多组实验,使用不同技术实现了session持久机制
- session绑定,基于IP或session cookie的。其部署简单,尤其基于session黏性的方式,粒度小,
对负载均衡影响小。但一旦后端服务器有故障,其上的session丢失。 - session复制集群,基于tomcat实现多个服务器内共享同步所有session。此方法可以保证任意一
台后端服务器故障,其余各服务器上还都存有全部session,对业务无影响。但是它基于多播实现
心跳,TCP单播实现复制,当设备节点过多,这种复制机制不是很好的解决方案。且并发连接多的
时候,单机上的所有session占据的内存空间非常巨大,甚至耗尽内存。 - session服务器,将所有的session存储到一个共享的内存空间中,使用多个冗余节点保存
session,这样做到session存储服务器的高可用,且占据业务服务器内存较小。是一种比较好的解
决session持久的解决方案。
以上的方法都有其适用性。生产环境中,应根据实际需要合理选择。
不过以上这些方法都是在内存中实现了session的保持,可以使用数据库或者文件系统,把session数据
存储起来,持久化。这样服务器重启后,也可以重新恢复session数据。不过session数据是有时效性
的,是否需要这样做,视情况而定。
安全
配置安全
删除webapps目录下的所有文件,禁用tomcat管理界面;
注释或删除tomcat-users.xml文件内的所有用户权限;
更改关闭tomcat指令或禁用;
Tomcat的server.xml中定义了可以直接关闭 Tomcat 实例的管理端口(默认8005)。可以通过 telnet 连接上该端口之后,输入 SHUTDOWN (此为默认关闭指令)即可关闭Tomcat 实例(注意,此时虽然实例关闭了,但是进程还是存在的)。由于默认关闭Tomcat 的端口和指令都很简单。默认端口为8005,指令为SHUTDOWN。
方案一:
1
2更改端口号和指令:
<Server port="8456" shutdown="itcast_shut">方案二:
1
2禁用8005端口:
<Server port="‐1" shutdown="SHUTDOWN">定义错误页面
在webapps/ROOT目录下定义错误页面 404.html,500.html;
然后在tomcat/conf/web.xml中进行配置 , 配置错误页面:1
2
3
4
5
6
7
8
9<error‐page>
<error‐code>404</error‐code>
<location>/404.html</location>
</error‐page>
<error‐page>
<error‐code>500</error‐code>
<location>/500.html</location>
</error‐page>这样配置之后,用户在访问资源时出现404,500这样的异常,就能看到我们自定义的错误
页面,而不会看到异常的堆栈信息,提高了用户体验,也保障了服务的安全性。
应用安全
在大部分的Web应用中,特别是一些后台应用系统,都会实现自己的安全管理模块(权限模块),用于控制应用系统的安全访问,基本包含两个部分:认证(登录/单点登录)和授权(功能权限、数据权限)两个部分。对于当前的业务系统,可以自己做一套适用于自己业务系统的权限模块,也有很多的应用系统直接使用一些功能完善的安全框架,将其集成到我们的web应用中,如:SpringSecurity、Apache Shiro等。
传输安全
Tomcat支持HTTPS
生成密钥库文件
1
keytool -genkeypair -alias [user] -keyalg [认证类型] -keystore [file]
输入对应的密钥库密码, 秘钥密码等信息之后,会在当前文件夹中出现一个秘钥库文件:tomcatkey.keystore
将秘钥库文件 tomcatkey.keystore 复制到tomcat/conf 目录下。
配置tomcat/conf/server.xml
1
2
3
4
5
6
7
8
9<Connector port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" schema="https" secure="true" SSLEnabled="true">
<SSLHostConfig certificateVerification="false">
<Certificate
certificateKeystoreFile="xxx/tomcatkey.keystore"
certificateKeystorePassword="itcast" type="RSA" />
</SSLHostConfig>
</Connector>访问Tomcat,使用https协议