在计算机科学中,特别是在网络中,session是两个或更多个通讯设备之间或计算机和用户之间的临时和交互式信息交换。session在某个时间点创建,而后在以后的某一时间点拆除。创建的通讯session能够在每一个方向上涉及多个消息。session一般是有状态的,这意味着至少一个通讯部分须要保存关于会话历史的状态信息以便可以进行通讯,而在无状态通讯中,通讯由具备响应的独立请求组成。——Wikipediacss
Session:在计算机中,尤为是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,若是该用户尚未会话,则 Web 服务器将自动建立一个 Session 对象。当会话过时或被放弃后,服务器将终止该会话。Session 对象最多见的一个用法就是存储用户的首选项。例如,若是用户指明不喜欢查看图形,就能够将该信息存储在 Session 对象中。——百度html
在WEB应用中,通常都是采用http协议进行通讯,但http是一种无状态的通讯协议,这里的无状态是指协议对于事务处理没有记忆能力,在会话结束后,服务器不知道客户端是什么状态。在http协议初期,为了保证WEB的并发访问处理能力,http协议不会保存客户端访问的任何状态信息。后来http协议中加入了keep-alive功能,这是一种会话保持机制,这样即可以将会话持续保持一段时间,当用户在这个时间段又一次访问时会提升响应速度节省资源,但keep-alive也不会记录用户的状态,只是让链接保持一段时间,当用户超过这个时间段再次访问,依然仍是会当作新请求进行处理。但在WEB应用中有不少场景都须要根据用户的历史访问状态来将请求分配给后端服务器处理,例如登陆记录、购物车记录,浏览记录等,用户每次访问都没法找到之前的记录是很影响用户体验的,这样就诞生了cookie和session机制。前端
先来讲说cookie,当用户访问www.abc.com时须要登陆,由于http是无状态的,因此致使访问www.abc.com/xxx又须要从新登陆,这样是很头痛的事情,cookie的出现解决了这个问题,cookie能够将用户的少许信息保存至用户客户端本地,它将www.abc.com域名做为一个全局,在用户登陆此域名下的全部URI时都不须要从新登录。但用户本地的存储大小是有限的,而且将一些私密信息储存在本地是有安全风险的。java
如何保证用户体验,又能保证安全性,这就是Session的意义,session也是一种用户状态储存机制,但与cookie不一样的是,session储存在后端服务器的内存中。session在web应用中有着很是重要的意义,它能够很方便很安全的控制访问权限。linux
会话粘性是指在用户第一次访问后按必定的算法与之将其中一台后端服务器作绑定,通常分为两种:nginx
a.souce_ip:如nginx中的ip_hash算法、LVS中的sh算法web
b.cookie:HAProxy中的cookie算法
Session Cluster是指将后端服务器组成一个集群,共享全部的session, 当某一台服务器故障后不至于影响用户体验。这种方法通常用在后端服务器较少的状况(3-4台),由于当服务器太多时会占用大量的IO,影响集群性能。数据库
下面将以Tomcat为例介绍介绍这种session保持机制。apache
Tomcat Session Cluster的实现是利用组播将集群中的session进行共享,这与keepalived相似。Tomcat原生就支持这种机制,因此配置起来比较简单,但不能支持太多的主机,
Nginx主机:IP:192.168.29.109
Tomcat主机集群:192.168.29.10七、192.168.29.13二、192.168.29.110
安装好Nginx和Tomcat,教程:http://www.javashuo.com/article/p-qbvvzhgh-bk.html
关闭防火墙和Selinux
vim /etc/nginx/nginx.conf #配置主配置文件
upstream tcsv { #在http模块中插入upstream模块 server 10.10.10.130:8080; server 10.10.10.131:8080; server 10.10.10.132:8080; }
vim /etc/nginx/conf.d/tomcat.conf #添加虚拟主机
server { listen 80; server_name www.ready.com; location / { proxy_pass http://tcsv; } }
mkdir -pv /var/lib/tomcat/webapps/test/{WEB-INF,META-INF,classes,lib} #建立jsp文件所需目录
vim /var/lib/tomcat/webapps/test/index.jsp #建立jsp测试文件,功能为session ID监控
<%@ page language="java" %> <html> <head><title>TomcatA</title></head> <body> <h1><font color="red">Tomcat.ready.com</font></h1> #将3台Tomcat主机配置为不一样颜色,我这里分别是red、green、blue <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("ready.com","ready.com"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>
不一样颜色表明不一样主机的响应,咱们能够发现就算响应的主机相同Session ID也不一样,这说明Session机制未开启(由于前端Nginx调度默认采用的rr算法),就算在同一主机访问也会被识别为不一样用户。
Tomcat原生就是支持此服务的,因此只须要在/etc/tomcat/server.xml中嵌入 <Cluster> 组件便可,要注意的是 <Cluster> 组件只能用在 <Engine> 和 <Host> 中。注意事项以下:
1.默认多播地址为228.0.0.4
2.默认多播端口是45564(端口和地址一块儿决定集群成员。
3.广播的IP是 java.net.InetAddress.getLocalHost().getHostAddress() (确保没有广播127.0.0.1,这是一个常见的错误)
4.监听复制消息的TCP端口是范围4000-4100中的第一个可用服务器套接字
5.侦听器被配置为 ClusterSessionListener
6.配置两个拦截器 TcpFailureDetector 和 MessageDispatch15Interceptor
vi /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.0.0.4" #默认组播地址 port="45564" #默认端口 frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="192.168.29.132" #填写本机IP地址,默认为auto 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>
web.xml文件是用来初始化配置信息:好比Welcome页面、servlet、servlet-mapping、filter、listener、启动加载级别等。
cp /etc/tomcat/web.xml /usr/share/tomcat/webapps/test/WEB-INF/
vim /usr/share/tomcat/webapps/test/WEB-INF/web.xml
在 <web-app> 内任意位置插入代码 <distributable/> ,其余Tomcat主机也作相同操做。
在日志中看到下面的信息就说明session共享配置成功:
能够看到无论怎么刷新Session ID都保持不变,但标题颜色会变化,说明不管去前端Nginx怎么调度Session都没有发生变化。
1.在插入 <Cluster> 组件时要注意 <Receiver> 中的 address= 的IP配置,尽可能不要用“auto”。
2.Tomcat主机的网关必定要设置正确,否则没法发送和接收组播信息。
3.要在日志中看到相似 [tcp://{192, 168, 29, 107}:4000,{192, 168, 29, 107},4000, alive=1037 的信息才说明组播信息成功发送,也可使用 tcpdump 命令来检查组播信息状态:
tcpdump -i ens33 -nn host 228.0.0.4
在Tomcat Session Cluster方式实现session共享时,后端不能承载太多的Tomcat主机,只适用于小型的集群使用,为了克服这一问题,咱们能够将后端的Tomcat集群的全部session都存放在一个共享的存储中,这样无论用户请求被反代到哪个后端服务器都不会影响体验。
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。memcached特性:
1.仅可用来存储可序列化的数据。
2.分布式缓存:互不通讯的分布式集群。
3.数据存储在内存中,重启即丢失数据。
4.缓存耗尽:LRU
5.惰性清理机制。
memcached已经收录在yum的base仓库,安装起来很是简单。
~]# yum install -y memcached
查看memcached的配置文件
~]# cat /etc/sysconfig/memcached
PORT="11211" #监听端口 USER="memcached" #用户名 MAXCONN="1024" #最大并发链接数 CACHESIZE="64" #缓存空间大小,默认为64MB OPTIONS=""
memcached经常使用选项:
memcached程序的经常使用选项:
-m <num>:Use <num> MB memory max to use for object storage; the default is 64 megabytes.
-c <num>:Use <num> max simultaneous connections; the default is 1024.
-u <username>:以指定的用户身份来运行进程;
-l <ip_addr>:监听的IP地址,默认为本机全部地址;
-p <num>:监听的TCP端口, the default is port 11211.
-U <num>:Listen on UDP port <num>, the default is port 11211, 0 is off.
-M:内存耗尽时,不执行LRU清理缓存,而是拒绝存入新的缓存项,直到有多余的空间可用时为止;
-f <factor>:增加因子;默认是1.25;
-t <threads>:启动的用于响应用户请求的线程数;
MSM是一个将Tomcat Session存储在memcached中的工具,这样就能克服Tomcat自建的session共享机制后端服务器的数量限制。
试验结构图:
我这里是yum安装的,目录是在/usr/share/java/tomcat/下,须要复制到该目录的文件以下(两台Tomcat主机操做相同),这一步很重要,若是文件版本不对会致使后面session共享不成功,我所用到的版本以下:
memcached-session-manager-1.8.2.jar memcached-session-manager-tc7-1.8.2.jar msm-javolution-serializer-1.8.2.jar spymemcached-2.10.2.jar javolution-5.5.1.jar
放在 /usr/share/java/tomcat/ 目录下
在两台Tomcat主机上修改相同配置
vim /etc/tomcat/server.xml
<Host ......
<Context path="/test" docBase="test" reloadable="true"> <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" memcachedNodes="n1:192.168.29.107:11211,n2:192.168.29.110:11211" failoverNodes="n1" requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory" /> </Context>
......
</Host>
192.168.29.107主机上的配置:
mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF/{classes,lib} vim /usr/share/tomcat/webapps/test/index.jsp
<%@ page language="java" %> <html> <head><title>TomcatB</title></head> <body> <h1><font color="blue">Tomcat.Ready.com</font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("ready.com","ready.com"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>
192.168.29.110主机上的配置:
mkdir -pv /usr/share/tomcat/webapps/test/WEB-INF/{classes,lib} vim /usr/share/tomcat/webapps/test/index.jsp
<%@ page language="java" %> <html> <head><title>TomcatB</title></head> <body> <h1><font color="red">Jerrmouse.Ready.com</font></h1> <table align="centre" border="1"> <tr> <td>Session ID</td> <% session.setAttribute("ready.com","ready.com"); %> <td><%= session.getId() %></td> </tr> <tr> <td>Created on</td> <td><%= session.getCreationTime() %></td> </tr> </table> </body> </html>
systemctl start tomcat
systemctl start memcached
ss -lntup
完成上述步骤后浏览器访问显示以下:
Session ID后面多出了n1字符,而且不断刷新页面Session ID都不会改变,说明MSM+Tomcat的session共享配置成功。
再强调一次,复制到/usr/share/java/tomcat/的jar文件版本很重要。