文档章节

集群环境下的用户会话方案

南湖船老大
 南湖船老大
发布于 2016/10/02 11:52
字数 1422
阅读 82
收藏 1

集群环境下,必然需要考虑用户和会话的问题,如果不加处理的话,由于每一个会话cookies是对应服务器后端的一个session(Java是jsessionid,PHP是PHPSESSID),也就是说session是和具体的服务器绑定的,一旦后端IP轮询切换,会话cookies找不到对应的session,会话也就断了。在这种场景下,就存在5种处理方案。下文主要讨论的是Java和PHP的处理,对于其他语言一样适用。

    1、依然使用集群,但集群的轮训策略使用hash ip,将每一个客户和后端服务器绑定,这样一来,用户的会话始终落在一台固定的服务器上,这也是成本最小的方案。如果是很老的架构的话,这种方案是改造成本最小的。

upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
    server.backend3.example.com;
}

但这样存在一个问题,就是一旦某台服务器挂了,切换到另外一台服务器后,对应的会话也就丢了。还存在一个情况就是如果前端是CDN的话,客户端IP可能变化的频率是很高的,有可能是一个小时或更短就变一次,在校园网这种网络环境下也容易产生这种情况。

2、使用session复制方案。这是早期tomcat采用的方案。

    session复制模式就可以很好的解决failureover的问题,即某一台web服务器挂掉后,用户的请求还会被负载到其他的web服务器上,而且由于session也被复制了,这样对用户而言就像是在同一台机器上操作一样。不好的地方就是session复制需要系统资源和网络的开销,也就是所谓的“网络风暴”,尤其是当web服务器多的时候或session里存储的数据量大的时候,这点将会比较的明显。
  session复制本身的操作还是比较复杂的,但是对于服务器来说,配置也算简单,但性能是个很大的问题。当处于一个大于两台服务器的集群中时,复制就比较吃力了。这种方案现在一般不使用了。

3、Nginx的sticky方案。

    其实sticky方案和方案一类似,但是sticky能做到把会话死死的粘滞在其中一台服务器上,算是方案一的补充,可以避免CDN网络下的客户端IP突变。很明显,方案1和方案3都存在failover的问题。

4、方案4,NoSQL的集中存储方案

    基于Redis等NoSQL的session集中存储。这种是目前最流行的方案,早期的方案是用MySQL来存储。但仍然存在以下问题:

(1)redis有单点,并且redis的引入增加了系统复杂度,要解决这个单点就得使用redis集群方案,比如codis。

(2)用户量大的情况下,用来连接redis的类库可能存在瓶颈,比如有部分用户反应jedis性能不稳定,高并发下容易挂。

但是就配置而言,不论是PHP还是Java都相对很简单,例如对于PHP而言,只需要安装predis扩展,在php.ini里配置下session存储方案即可

vi /etc/php.ini
session.save_handler = redis
session.save_path = "tcp://192.168.1.102:6379?timeout=15"

注意注释掉/etc/php-fpm.d/www.conf里session的配置,以免配置被覆盖而无效。

对于Java而言,只需要引入一个jar包(https://github.com/jcoleman/tomcat-redis-session-manager),配置server.xml即可。

    不过,对于tomcat而言,tomcat在启动时就会创建一个session,当会话越多的时候,session也就越多。而session在tomcat中属于重量级对象。一个没有任何内容的空session就需要消耗1.5K的内存存储空间。当然,使用redis都是默认内存足够大。

5、放弃session,使用纯cookies

    纯cookies,不使用session,天然分布式。存在的问题:

(1)cookies需要加解密,性能消耗要考虑,而且不能存太多东西,如果cookies存放了一些复杂的数据时,序列化本身消耗也不少。

(2)对于浏览器而言,每次请求都会带上cookies,包括JS和CSS等请求,浪费宽带,除非部署了CDN或专用服务器。这时就需要为静态文件配置一个独立的域名了。其实这个问题,前面几个方案同样存在。

  另外也可以转用token与openid等方式验证用户。

    我个人所使用的方案是方案5+方案4的结合,即仅使用cookies来存储会话标记,不使用应用服务器本身自带的session方案,对于会话信息,不使用session存储,而是直接存放到Redis中。本质上就是方案4的基础上,自己实现一套session机制。这种实现要看具体的语言而定。对于PHP而言,这种做法是多此一举。而对于Java而言,由于tomcat的session实现比较重量级,这种做法能提高一些性能。针对这种方案,我实现了一个自定义的session管理器,用来替代tomcat的默认session管理器,达到节省内存,提高性能的目的。地址在此:

https://github.com/iminto/tomcat-no-session

    需要注意的是:对于方案5,存在一个问题就是如果应用需要考虑“禁止同时登录”的时候,用cookies的解决方案就麻烦很多了。

      如果有更好的方案,也希望你能提供给我。

© 著作权归作者所有

共有 人打赏支持
南湖船老大
粉丝 678
博文 11
码字总数 10246
作品 0
深圳
其他
session会话-nginx-mysql-tomcat

一、如何保持session会话 目前,为了使web能适应大规模的访问,需要实现应用的集群部署。集群最有效的方案就是负载均衡,而实现负载均衡用户每一个请求都有可能被分配到不固定的服务器上,这...

柴鑫旺
2017/09/11
0
0
集群环境下session方案好还是no session方案好

集群环境下,必然需要考虑用户和会话的问题,如果不加处理的话,一旦后端IP轮询切换,session也就断了。所以就有了4种方案。先说下session的问题,tomcat在启动时就会创建一个session,当会话...

南湖船老大
2016/03/04
2.2K
18
Nginx反向代理,负载均衡+Tomcat实现Session共享

Nginx反向代理,负载均衡+Tomcat实现Session共享 防伪码:学而不思则罔,思而不学则殆。 作者:何小帅 博客URL:http://hexiaoshuai.blog.51cto.com 一、如何保持session会话 目前,为了使w...

何小帅
06/26
0
0
分布式session共享常用的几种方式

tomcat session共享常用的几种方式 1、请求精确定位 粘性会话:session sticky 例如基于访问ip的hash策略,即当前用户的请求都集中定位到一台服务器中,这样单台服务器保存了用户的session登...

啃不动地大坚果
06/14
0
0
用Spring Web Flow和Terracotta搭建Web应用

Spring Web Flow 是Spring Framework 中的web应用组件,它提供了一种编写有状态和基于会话的web应用的简便手段。Spring Web Flow 使得逻辑流程成为Web应用中的一等公民,它能让你定义为自包含...

红薯
2009/04/24
2.5K
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

react native 开发碰到的问题

react-navigation v2 问题 问题: static navigationOptions = ({navigation, navigationOptions}) => ({ headerTitle: ( <Text style={{color:"#fff"}}>我的</Text> ), headerRight: ( <View......

罗培海
30分钟前
0
0
Mac Docker安装流程

久仰Docker大名已久,于是今天趁着有空,尝试了一下Docker 先是从docker的官网上下载下来mac版本的docker安装包,安装很简易,就直接拖图标就好了。 https://www.docker.com/products/docker...

writeademo
38分钟前
0
0
TensorFlow rnn mnist 分类

使用rnn 对mnist进行分类 参考 http://www.360doc.com/content/17/0321/10/10408243_638692495.shtml 网络定义 其中最后一层不需要进行sofmax,lstmcell返回的数据是两个,一个是阶段性的,一...

阿豪boy
40分钟前
0
0
使用ELK构建微服务的日志平台

1 概述 在微服务架构中,会部署众多的应用,其中有基础应用,比如:网关,服务发现等。同时还有大量的业务应用。所以,如何有效的收集它们的日志,并且方便查询,同时提供友好的可视化展示,...

Java大蜗牛
48分钟前
0
0
Spring源码阅读——4

BeanDefinitionHolder的创建 Spring框架中BeanDefinition的继承结构如下图: BeanDefinition是配置文件<bean>元素标签在容器中内部表示形式。<bean>元素标签拥有class、scope、lazy-init等配...

叶枫啦啦
56分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部