会话保持

理论部分

会话也就是session,主要存储在服务器端,用来识别用户的身份。

在浏览器中向服务端发送请求的时候,不是http协议就是https协议,而两种协议在发送请求的时候,都是基于http协议,http协议又是无状态的,也就是stateless,在每次用户发送请求过去的时候,这都是一次新的连接,服务端是不会认识你是谁的。

那么怎么让服务端来识别客户端谁是谁呢,从而也就有cookie,cookie好像没有中文翻译,cookie主要存储在客户端,一般是保存在某个特定路径的文件之中,从而在每次发送请求的时候,都会附加上这个cookie信息,服务端得到这个信息之后,就会判定你是哪个用户等信息,cookie主要就是找到服务端的session信息,从而用来追踪用户。

在生产环境中,只要涉及到负载均衡的地方,我们就需要考虑会话保持,否则假如一个应用程序是需要登录的,那么会频繁的需要登录。

负载均衡主要分为硬件负载均衡F5,CITRIX等,nginx负载均衡,apache负载均衡,无论是硬件负载均衡或者是软件负载均衡都会有一个会话保持的选项,在需要进行会话保持的时候,在每一个环节都需要进行会话保持,也就是硬件负载均衡要选择会话保持,在软件负载均衡也要进行会话保持。

生产环境使用的过时的(第一种):

在中间件的选择上面,apache和webspare在逐渐淘汰,在使用此种架构的时候,F5会使用会话保持,nginx也使用的是ip_hash进行会话保持。此种架构的最大的优势是部署比较简单,在进行部署的时候只要将java程序的war包放置到具体的目录即可进行部署,在进行自动化发布的时候,进行部署是非常简单的事,因为集群中各个机器是独立的,一个机器出问题,不会影响其他的机器;缺点就是在部署的时候,需要在每个主机上进行放置相同的war包,并且配置要保持一直;在需要会话保持的场景中,如果一台主机down,那么就会导致所有的会话丢失。

生产环境使用的过时的架构(第二种):

在使用domain模式的时候,前端的F5和nginx都不需要进行会话保持,只要做到负载均衡就好了。此种方式的最大有点就是在自动化部署的时候只要在domain节点的master或者是dmgr部署程序即可,主节点会自动将相关的程序同步到其他的slave或者node节点上去,在修改配置的时候,也只要在master上进行修改即可,在会话保持的上面,主机之间会同步相关的会话信息,从而不用担心某台服务器宕机从而导致会话丢失。缺点就是,无论是在发布或者同步配置的时候,主节点总要联系上从节点,进行同步,而从节点的相关进程还是比较容易出现假死的情况,在使用这种集群的时候,只要master节点或者dmgr节点的服务器损坏,那么这个集群就不能重新发布新的程序版本了,但是不会影响服务的可用性,在每次出现问题的时候,因为同步进程有好几个,你都不知道是那个进程假死了,只能全部进行重启一遍,说好的稳定性呢。为啥这种慢慢淘汰,一个是因为在自动化发布的时候,很容易出现问题;在进行灰度发布的时候,standalone模式更容易控制,而且domain模式有主机数量的限制,而standalone模式理论上无上限。

生产环境目前架构如下:

在使用此种架构的时候,前端无须进行会话保持,后端也无须进行会话的同步,在有后端主机宕机的时候,也不会丢失会话,灰度发布也很容易,自动化做起来比较简单,从而也就成为了目前的架构。

使用tomcat standalon演示会话保持

tomcat的首页内容如下所示(可以查看到页面的session信息):

[[email protected] kel]# cat index.jsp 

<%@ page language="java" %>

<%@ page import="java.util.*" %>

<html>

    <head>

        <title>JAVA PAGE</title>

    </head>

    <body>

        <% out.println("mogilenode3"); %>

<%= session.getId() %>

    </body>

</html>

  

在使用负载均衡的时候,准备两台主机,均需要安装jdk和tomcat,并且提供相同的应用程序,在首次访问的时候,均会设置cookie信息,在java程序中,其中会有JSESSIONID,在第二次访问同样的主机的时候,就不会再次设置这个cookie信息了。

使用nginx进行反代的时候,nginx的主要配置文件如下所示:

在nginx的时候,主要的就是使用ip_hash。

在使用apache进行反代的时候,可以使用http协议或者ajp协议,配置文件如下所示(在编译的时候,需要几个模块mod_proxy,mod_proxy_http,mod_proxy_ajp,mod_proxy_balancer):

NameVirtualHost *:80

<proxy balancer://tomserver>

    BalancerMember ajp://192.168.1.236:8009 loadfactor=1 route=mogilenode1

    BalancerMember ajp://192.168.1.238:8009 loadfactor=1 route=mogilenode3

    ProxySet stickysession=ROUTEID

</proxy>

<VirtualHost *:80>

    DocumentRoot "/usr/local/apache/htdocs"

    ServerName www.kel.com

    ServerAlias www.kel.com

    ProxyVia On

    ProxyRequests Off

    ProxyPreserveHost On

    ProxyPass /status !

    <Location /balancer-manager>

        SetHandler balancer-manager

        ProxyPass !

        order allow,deny

        allow from all

    </Location>

    ProxyPass  / balancer://tomserver/

    ProxyPassReverse  / balancer://tomserver/

    ErrorLog "logs/www.kel.com-error_log"

    CustomLog "logs/www.kel.com-access_log" common

</VirtualHost>

<Location /status>

    SetHandler server-status

    Order allow,deny

    Allow from all

</Location>

ExtendedStatus On

  

使用http协议的配置如下:

NameVirtualHost *:80

Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e;path=/" env=BALANCER_ROUTE_CHANGED

<proxy balancer://tomserver>

    BalancerMember http://192.168.1.236:8080 loadfactor=1 route=mogilenode1

    BalancerMember http://192.168.1.238:8080 loadfactor=1 route=mogilenode3

    ProxySet stickysession=ROUTEID

</proxy>

<VirtualHost *:80>

    DocumentRoot "/usr/local/apache/htdocs"

    ServerName www.kel.com

    ServerAlias www.kel.com

    ProxyVia On

    ProxyRequests Off

    ProxyPreserveHost On

    ProxyPass /status !

    <Location /balancer-manager>

        SetHandler balancer-manager

        ProxyPass !

        order allow,deny

        allow from all

    </Location>

    ProxyPass  / balancer://tomserver/

    ProxyPassReverse  / balancer://tomserver/

    ErrorLog "logs/www.kel.com-error_log"

    CustomLog "logs/www.kel.com-access_log" common

</VirtualHost>

<Location /status>

    SetHandler server-status

    Order allow,deny

    Allow from all

</Location>

ExtendedStatus On

  

在次两种的配置下,tomcat需要配置如下信息:

<Engine name="Catalina" defaultHost="www.kel.com" jvmRoute="mogilenode1">

使用tomcat cluster演示会话保持

在apache或者nginx端只要做负载均衡的配置即可,也就是在nginx中去掉ip_hash,在apache中去掉ProxySet stickysession=ROUTEID,主要的配置在tomcat的host标签中,如下所示:

        <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="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.MessageDispatchInterceptor"/>

          </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.ClusterSessionListener"/>

        </Cluster>

  

在其中需要修改的组播地址,防止部署多个集群的时候,出现地址冲突,在部署的时候,可能出现的错误如下:

java.net.SocketException: No such device; No faulty members identified.

SEVERE: Unable to start cluster.

  

主要是因为没有设置网关地址或者组播地址,在其中如下:

[[email protected] extra]# route add default gw 192.168.1.1

[[email protected] extra]# route -n

Kernel IP routing table

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0

192.168.249.0   0.0.0.0         255.255.255.0   U     0      0        0 eth1

169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0

169.254.0.0     0.0.0.0         255.255.0.0     U     1003   0        0 eth1

0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0

  

或者使用如下方法:

[[email protected] kel]# route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0

[[email protected] kel]# route -n

Kernel IP routing table

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface

192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0

192.168.249.0   0.0.0.0         255.255.255.0   U     0      0        0 eth1

169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0

169.254.0.0     0.0.0.0         255.255.0.0     U     1003   0        0 eth1

224.0.0.0       0.0.0.0         240.0.0.0       U     0      0        0 eth0

在应用程序的web.xml中,在web-app标签中添加指令:

<distributable/>

监听的地址如下:

[[email protected]mogilenode3 WEB-INF]# netstat -tnlp|grep java

tcp        0      0 :::8080                     :::*                        LISTEN      3920/java           

tcp        0      0 ::ffff:192.168.1.238:4000   :::*                        LISTEN      3920/java           

tcp        0      0 ::ffff:127.0.0.1:8005       :::*                        LISTEN      3920/java           

tcp        0      0 :::8009                     :::*                        LISTEN      3920/java

测试

在第一次发送请求的时候,会设置cookie信息,如下所示:

在第二次发送请求的时候,会带上Cookie信息,如下:

在JAVA程序中,只要收到了jsp或者servlet的请求,那么就会生成JSESSIONID。

时间: 2024-10-11 20:12:12

会话保持的相关文章

(转)web会话管理方式

阅读目录 1. 基于server端session的管理 2. cookie-based的管理方式 3. token-based的管理方式 4. 安全问题 5. 总结 http是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的.当然它知道是哪个客户端地址发过来的,但是对于我们的应用来说,我们是靠用户来管理,而不是靠客户端.所以对我们的应用而言,它是需要有状态管理的,以便服务端能够准确的知道http请求是哪个用户发起的,从而判断他是否有权限继续这个请求.这

会话技术Session&amp;Cookie

一.会话技术简介 1.存储客户端的状态 由一个问题引出今天的内容,例如网站的购物系统,用户将购买的商品信息存储到哪     里?因为Http协议是无状态的,也就是说每个客户访问服务器端资源时,服务器并不知道该客户端是谁,所以需要会话技术识别客户端的状态.会话技术是帮助服务器   记住客户端状态(区分客户端) 举例购物过程: 2.会话技术 从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,成为一次会话.会话技术就是记录这次会话中客户端的状态与数据的. 会话技术分为Cookie和Sessio

快速入门系列--WCF--06并发限流、可靠会话和队列服务

这部分将介绍一些相对深入的知识点,包括通过并发限流来保证服务的可用性,通过可靠会话机制保证会话信息的可靠性,通过队列服务来解耦客户端和服务端,提高系统的可服务数量并可以起到削峰的作用,最后还会对之前的事务知识做一定补充. 对于WCF服务来说,其寄宿在一个资源有限的环境中,为了实现服务性能最大化,需要提高其吞吐量即服务的并发性.然而在不进行流量控制的情况下,并发量过多,会使整个服务由于资源耗尽而崩溃.因此为相对平衡的并发数和系统可用性,需要设计一个闸门(Throttling)控制并发的数量. 由于

JavaWeb基础—会话管理之Session

一.什么是session session类似于客户端在服务器端的账户.使用Map存放 一个会话锁定一个用户(一般情况下是一个客户端,即一个浏览器独占一个session对象),即使使用浏览器访问其他程序资源,也可以共享这个session (如何确定是同一个用户?创建session时把sessionID以cookie的形式传给客户端,客户端访问时再把此sessionID传过去进行校验 JSESSIONID ) 二.session和cookie的区别 cookie 把用户的数据保存到浏览器端,sess

如何在Ubuntu 16.04上将Redis服务器设置为PHP的会话处理程序

介绍 Redis是一个开源的键值缓存和存储系统,也称为数据结构服务器,因为它对几种数据类型(如散列,列表,集合和位图等)提供高级支持.它还支持集群,使其在高可用性和可扩展的环境中非常有用. 在本教程中,我们将看到如何安装和配置一个外部Redis服务器,用作在Ubuntu 16.04上运行的PHP应用程序的会话处理程序. 会话处理程序负责存储和检索保存到会话中的数据.默认情况下,PHP使用文件这一点.这对于单个服务器工作得很好,但是由于会话信息被绑定到单个服务器,所以具有一些显着的性能和可扩展性限

LVS负载均衡之持久性连接介绍(会话篇)

在实际生产环境中,往往需要根据业务应用场景来设置lvs的会话超时时间以及防session连接丢失的问题提,如在业务支付环节,如若session丢失会导致重复扣款问题,严重影响到安全性,本小节解将会讲到关于lvs持久性连接问题 一.lvs负载均衡持久连接介绍: 引子(案例) 对于电子商务网站来说,用户在挑选商品的时候使用的是80端口来浏览的,当付款的时候则是通过443的ssl加密的方式,当然当用户挑选完商品付款 的时候,我们当然不希望https的443跳转到另外一台REAL SERVER上,很显然

信息会话Thread_id异常处理(MMS草稿修改收件人,SMS新信息丢失thread数据)

1, sms收到信息,thread表没有create新数据.导致一直有一条未读信息数量显示,但在会话列表中却看不到. (偶现. 解决方法:查询未读信息时,过滤thread丢失的sms信息.先规避此Bug) 分析:Ril层接收新信息会通过Framework发通知——android.provider.Telephony.SMS_DELIVER com.android.mms.transaction.PrivilegedSmsReceiver接收广播,应用程序MMS开始处理 protected voi

HTTP会话原理解释与应用

一.什么是会话 首先解释一下什么是会话.在计算机术语中,会话是指一个终端用户与交互系统进行通讯的过程,比如从输入账户密码进入操作系统到退出操作系统就是一个会话过程.会话较多用于网络上,TCP的三次握手就创建了一个会话,TCP关闭连接就是关闭会话.用平述的语言可以解释为:你拔打你女友的电话号码,你女友接听,然后一翻“亲爱的”,直到任何一方挂掉电话,这个过程就是一个会话.你挑逗一只小狗,它跟你互动,也是会话:它不鸟你,那就不形成会话. 二.什么是HTTP会话 协议的状态是指下一次传输可以“记住”这次

会话控制cookie和session

Cookie Cookie简介 HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分中两次请求是否由一个客户端发出.这样的设计严重阻碍的Web程序的设计.如:在我们进行网购时,买了一条裤子,又买了一个手机.由于http协议是无状态的,如果不通过其他手段,服务器是不能知道用户到底买了什么.而Cookie就是解决方案之一. Cookie实际上就是服务器保存在浏览器上的一段信息.浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就

Shiro会话管理器与验证码实现(十四)

和shiro整合后,使用shiro的session管理,shiro提供sessionDao操作 会话数据. 配置sessionManager 注入到securityManager ----------------------------------------验证码(自定义验证器)--------------------------------- 思路 shiro使用FormAuthenticationFilter进行表单认证,验证校验的功能应该加在FormAuthenticationFilte