集群产生的session共享问题

  • Post author:
  • Post category:其他

前言:

为了解决集群产生的session共享问题,我们首先需要知道以下三个概念:

  • cookie
  • session
  • nginx

​ 下面将逐个分析。

Cookie

1.Cookie是什么

​cookie的中文翻译是曲奇,小甜饼的意思。cookie其实就是一些数据信息,类型为“小型文本文件”,存储于电脑上的文本文件中。

2.Cookie有什么用

其作用很简单,就是保存我们的一些登录信息,如我们的账号和密码,避免我们频繁重新输入。
我们想象一个场景,当我们打开一个网站时,如果这个网站我们曾经登录过,那么当我们再次打开网站时,发现就不需要再次登录了,而是直接进入了首页。
这是怎么做到的呢?其实就是游览器保存了我们的cookie,里面记录了一些信息,当然,这些cookie是服务器创建后返回给游览器的。游览器只进行了保存。

3.Cookie的生命周期

​ cookie有2种存储方式,一种是会话性,一种是持久性。

  • 会话性:如果cookie为会话性,那么cookie仅会保存在客户端的内存中,当我们关闭客服端时cookie也就失效了
  • 持久性:如果cookie为持久性,那么cookie会保存在用户的硬盘中,直至生存期结束或者用户主动将其销毁。

​ cookie我们是可以进行设置的,我们可以人为设置cookie的有效时间,什么时候创建,什么时候销毁。

4.Cookie的表示

一般情况下,cookie是以键值对进行表示的(key-value),例如name=jack,这个就表示cookie的名字是name,cookie携带的值是jack。

5.Cookie使用的常见方法

下面我只对Java中Cookie对象的方法进行讲解
  • new Cookie(String name, String value):创建一个Cookie对象,必须传入cookie的名字和cookie的值
  • getValue():得到cookie保存的值
  • getName():获取cookie的名字
  • setMaxAge(int expiry):设置cookie的有效期,默认为-1。这个如果设置负数,表示客服端关闭,cookie就会删除。0表示马上删除。正数表示有效时间,单位是秒。
  • setPath(String uri):设置cookie的作用域
  • response.addCookie(Cookie cookie):将cookie给客户端进行保存
  • resquest.getCookies():得到客服端传过来的所有cookie对象

session { #point2 }

1.session是什么

在计算机中,尤其是在网络应用中,称为“会话控制”。Session 对象存储特定用户会话所需的属性及配置信息。简而言之,session就是一个对象,用于存储信息。

当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。
这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。

2.sessio有什么用

​ 我们可以先想一个问题,我们在一个未登录的购物网站中将几个物品放入购物车后,关闭浏览器,再次打开浏览器后我们的购物车中仍然有那些商品,这是为什么呢?当然我们可以用cookie来存放这些数据,但是cookie能存放大数据吗?如果你看了前面的内容你就知道是不行的。这时,我们就需要一种新的技术,Session。session是存储于服务器端的特殊对象,服务器会为每一个游览器(客户端)创建一个唯一的session。这个session是服务器端共享,每个游览器(客户端)独享的。我们可以在session存储数据,实现数据共享。

3.session底层实现机制

​ session是每一个游览器(客户端)所唯一的,这个是怎么实现的呢?其实,在访问一个网站时,在HTTP请求中往往会携带一个cookie,这个cookie的名字是JSESSIONID,这个JSESSIONID表示的就是session的id,这个是由服务器创建的,并且是唯一的。服务器在使用session时,会根据JSESSIONID来进行不同操作。下面我将图示:

session底层实现机制

4.session的生命周期

  • 根据需求设定,一般来说,半小时。举个例子,你登录一个服务器,服务器返回给你一个sessionID,登录成功之后的半小时之内没有对该服务器进行任何HTTP请求,半小时后你进行一次HTTP请求,会提示你重新登录。

5.session使用的常见方法

下面我只对Java中Cookie对象的方法进行讲解
  • resquest.getSession():得到请求游览器(客户端)对应的session。如果没有,那么就创建应该新的session。如果有那么就返回对应的session
  • setAttribute(String s, Object o):在session存放属性
  • getAttribute(String s):从session中得到s所对应的属性
  • removeAttribute(String s):从session中删除s对应的属性
  • getId():得到session所对应的id
  • invalidate():使session立即无效
  • setMaxInactiveInterval(int i):设置session最大的有效时间。注意,这个有效时间是两次访问服务器所间隔的最大时间,如果超过最大的有效时间,那么这个session就失效了。

cookie与session的异同

  • cookie保存在客户端,session保存在服务端
  • cookie作用于他所表示的path中(url中要包含path),范围较小。session代表客户端和服务器的一次会话过程,web页面跳转时也可以共享数据,范围是本次会话,客户端关闭也不会消失。会持续到我们设置的session生命周期结束(默认30min)
  • 我们使用session需要cookie的配合。cookie用来携带JSESSIONID
  • cookie存放的数据量较小,session可以存储更多的信息。
  • cookie由于存放在客服端,相对于session更不安全
  • 由于session是存放于服务器的,当有很多客户端访问时,肯定会产生大量的session,这些session会对服务端的性能造成影响。

Nginx

1.Nginx是什么

​ Nginx 是高性能的 HTTP 和反向代理的web服务器,处理高并发能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50,000 个并发连接数。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等(本文章不涉及如何进行Nginx的安装、配置和运用)。

Nginx作为web服务器

​ Nginx 可以作为静态页面的 web 服务器,同时还支持 CGI 协议的动态语言,比如 perl、php 等。但是不支持 java。Java 程序只能通过与 tomcat 配合完成。Nginx 专为性能优化而开发, 性能是其最重要的考量,实现上非常注重效率 ,能经受高负载的考验,有报告表明能支持高 达 50,000 个并发连接数。

2.正向代理

​ Nginx 不仅可以做反向代理,实现负载均衡。还能用作正向代理来进行上网等功能。 正向代理:如果把局域网外的 Internet 想象成一个巨大的资源库,则局域网中的客户端要访 问 Internet,则需要通过代理服务器来访问,这种代理服务就称为正向代理

  • 简单一点:通过代理服务器来访问服务器的过程 就叫 正向代理。
  • 需要在客户端配置代理服务器进行指定网站访问

3.反向代理

  • 反向代理,其实客户端对代理是无感知的,因为客户端不需要任何配置就可以访问
  • 我们只 需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,在返 回给客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器 地址,隐藏了真实服务器 IP 地址。

4.负载均衡 { #point1 }

  • 增加服务器的数量,然后将请求分发到各个服务器上,将原先请求集中到单个服务器上的 情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我们所说的负载均衡
  • 客户端发送多个请求到服务器,服务器处理请求,有一些可能要与数据库进行交互,服务器处理完毕后,再将结果返回给客户端。

​ 这种架构模式对于早期的系统相对单一,并发请求相对较少的情况下是比较适合的,成 本也低。但是随着信息数量的不断增长,访问量和数据量的飞速增长,以及系统业务的复杂度增加,这种架构会造成服务器相应客户端的请求日益缓慢,并发量特别大的时候,还容易造成服务器直接崩溃。很明显这是由于服务器性能的瓶颈造成的问题,那么如何解决这种情况呢?

​ 我们首先想到的可能是升级服务器的配置,比如提高 CPU 执行频率,加大内存等提高机器的物理性能来解决此问题,但是我们知道摩尔定律的日益失效,硬件的性能提升已经不能 满足日益提升的需求了。最明显的一个例子,天猫双十一当天,某个热销商品的瞬时访问量 是极其庞大的,那么类似上面的系统架构,将机器都增加到现有的顶级物理配置,都是不能 够满足需求的。那么怎么办呢?上面的分析我们去掉了增加服务器物理配置来解决问题的办法,也就是说纵向解决问题 的办法行不通了,那么横向增加服务器的数量呢?这时候集群的概念产生了,单个服务器解决不了,我们增加服务器的数量,然后将请求分发到各个服务器上,将原先请求集中到单个服务器上的情况改为将请求分发到多个服务器上,将负载分发到不同的服务器,也就是我所说的负载均衡。

由集群引发的Session共享问题

​ 通过上面的学习我们知道了现在的大部分服务器应该都是一个服务器集群,里面会含有多个服务器,而客户端在某个时刻访问哪个服务器是由负载均衡器决定的,这里就产生了一个问题如果一个用户的Session信息如果存储在一个服务器上,那么当负载均衡器把用户的下一个请求转发到另一个服务器上,由于服务器上没有用户的session信息,那么该用户就需要重新进行登录操作。下面我将介绍几种解决方式:

1.客户端cookie保存

​ 以cookie加密的方式保存在客户端.优点是减轻服务器端的压力,每次session信息被写在客服端,然后经浏览器再次提交到服务器。即使两次请求在集群中的两台服务器上完成,也可以到达session共享。

优点:

  1. session信息不用存放在服务器端,大大减轻了服务器的压力。
  2. session中的两次或多次请求可以在一个集群中的多个服务器上完成,可以避免单点故障。目前,淘宝是采用的这种解决方案。

缺点:

  1. 传递cookie时,http信息头的长度限制使我们只能够在cookie中存入一部分用户信息。
  2. 需要额外地做session信息加密的工作。
  3. 如果采用这种方式,每次访问网站二级域名时都会在http信息头中带有这些以cookie形式存储的session信息,会占用一定的带宽。
  4. 由于这种方式是在客户端进行信息存储,用户完全可以禁用cookie或删除cookie,不是很可靠。

2.基于Memcached 存储Session

​ 利用Memcached来保存Session数据,直接通过内存的方式,效率自然能够提高不少。 在读写速度上会比 files 时快很多,而且在多个服务器需要共用 session 时会比较方便,将这些服务器都配置成使用同一组 memcached 服务器就可以,减少了额外的工作量。

缺点:

  1. session 数据都保存在 memory 中,一旦宕机,数据将会丢失。但对 session 数据来说并不是严重的问题。如果网站访问量太大,session太多的时候,memcached会将不常用的部分删除,但是如果用户隔离了一段时间之后继续使用,已经全部乱套了。

3.粘滞会话(Sticky Sessions)

​ 需要配置负载均衡器,使得一个用户的所有请求都路由到同一个服务器上,这样就可以把用户的Session都存放在该服务器上。

Sticky Sessions

缺点:

  1. 缺点:当服务器宕机时,将丢失该服务器上的所有Session。

4.Session Replication

​ 在服务器之间进行Session同步操作,每个服务器都有 所有用户的Session信息,因此用户可以向任何一个服务器进行请求。

Session Replication

缺点:

  1. 占用过多内存,同步过程占用网络带宽以及服务处理器时间

5.使用数据库存放session

​ 使用一个单独的服务器存储Session数据。可以使用传统的Mysql,也可以使用Redis或者Memcached这种内存型数据库。适合数据库访问量不大的网站。

Session Server

为了使大型网站具有伸缩性,集群中的应用服务器需要保持无状态,那么应用服务器不能存储用户的会话信息,Session Server将用户的会话信息单独进行存储,从而保证了应用服务器的无状态。

优点:

  1. 实现简单

缺点:

  1. 由于数据库服务器相对于应用服务器更难扩展且资源更为宝贵,在高并发的Web应用中,最大的性能瓶颈通常在于数据库服务器。因此如果将 Session存储到数据库表,频繁的数据库操作会影响业务。

6.使用文件系统存放session

​ 通过文件系统(比如NFS方式)来实现各台服务器间的Session共享,各台服务器只需要mount共享服务器的存储Session的磁盘即可,实现较为简单。但NFS 对高并发读写的性能并不高,在硬盘I/O性能和网络带宽上存在较大瓶颈,尤其是对于Session这样的小文件的频繁读写操作。

​ 适合并发量不大的网站。


版权声明:本文为ajiaxiaohua原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。