当前位置: 首页 > news >正文

用Redis存储Tomcat集群的Session

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

前段时间,我花了不少时间来寻求一种方法,把新开发的代码推送到到生产系统中部署,生产系统要能够零宕机、对使用用户零影响。 我的设想是使用集群来搞定,通过通知负载均衡Nginx,取下集群中的Tomcat节点,然后对Tomcat上的应用进行升级,再通知负载均衡Nginx,把Tomcat节点重新加载上去。依次这么做,把集群中的所有Tomcat都替换一次即可。 那么问题来了,在取下Tomcat节点和加载新Tomcat节点时如何做到对用户无影响呢?方法很简单,共享Session。 下面,我们用实例来说明此方案。我们的例子使用了一台Nginx做负载均衡,后端挂接了两台Tomcat,且每台Tomcat的Session会话都保存到Redis数据库中。其中,Nginx配置为non-sticky运行模式,也即每一个请求都可以被分配到集群中的任何节点。当要上线新代码时,只需简单地取下Tomcat实例,此时所有的访问用户会被路由到活动的Tomcat实例中去,而且由于会话数据都是保存在Redis数据库中,所以活跃用户并不会受影响。当Tomcat更新完毕,又可以把此节点加入到Nginx中。 安装Nginx

# sudo rpm -ivh nginx-1.4.2-1.el6.ngx.x86_64.rpm  

修改配置文件/etc/nginx/nginx.conf,并添加下面的内容:

http {  
upstream tomcat  {  
        server localhost:8080;  
        server localhost:8081;  
    }  
include       /etc/nginx/mime.types;  
default_type  application/octet-stream;  

修改配置文件/etc/nginx/conf.d/default.conf并替换location部分的内容:

location / {  
    proxy_pass  http://tomcat;  
  }  

重启Nginx

# sudo service nginx restart  

接下来,安装两个Tomcat实例。由于我们是在同一台服务器上做的演示,要让两台Tomcat不发生冲突,需要修改第二个Tomcat实例的端口号。由于Nginx配置为non-sticky运行模式,对每个请求采用的是Round-robin负载均衡方式,这意味着它会为每个请求都抽奖一个新会话。
接着,下载并安装Redis。步骤省略,很简单。
最后,我们需要配置Tomcat,让Tomcat把会话Session保存到Redis数据库。
我们要使用tomcat-redis-session-manager这样的第三方库,主页见:
https://github.com/jcoleman/tomcat-redis-session-manager 要注意此库并非开箱即用的,使用时需要做一些调整。你需要下载源码,并在更新了依赖库的版本后,重建项目。比如我使用了commons-pool2-2.2.jar和jedis-2.6.1.jar依赖库。要记住把这些jar文件复制到每一个Tomcat实例的lib子目录下。 在更新了commons-pool、jedis和tomcat版本这些库后,你可以使用build.gradle来构建整个项目。构建完毕后,复制新生成的tomcat-redis-session-manager-1.2.jar到每一个Tomcat实例的lib子目录下。并在修改每一个Tomcat实例的context.xml配置文件:

<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />  
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"  
         host="localhost"  
         port="6379"  
         database="0"  
         maxInactiveInterval="60" />  

重启Tomcat实例。可以检查到Redis确实保存了Tomcat的会话。然后我们对Tomcat实例取下或恢复时,访问用户确实没受影响。

转载于:https://my.oschina.net/daidetian/blog/704976

相关文章:

  • XForms - 更强大的Form
  • Git学习总结(6)——作为一名程序员这些代码托管工具你都知道吗?
  • PHP SPL笔记
  • 三十六计阅读手记
  • PAT (Advanced Level) 1112. Stucked Keyboard (20)
  • SVN代码丢失惊魂
  • 【jacob word】使用jacob,合并多个word为一个word文件
  • string、wstring、cstring、 char、 tchar、int、dword转换方法(转)
  • 对动画对概念和动画实现的思想的理解
  • pomelo连接redis
  • 推荐几款软件界面模型设计工具
  • BZOJ3189 : [Coci2011]Slika
  • logback日志交给logstash处理
  • Tutorial: Android Wear with Genymotion
  • Maven 版 JPA 最佳实践(转)
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • ES6核心特性
  • Git初体验
  • Intervention/image 图片处理扩展包的安装和使用
  • Java Agent 学习笔记
  • JavaScript的使用你知道几种?(上)
  • KMP算法及优化
  • magento 货币换算
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • vue的全局变量和全局拦截请求器
  • Wamp集成环境 添加PHP的新版本
  • 阿里云Kubernetes容器服务上体验Knative
  • 大快搜索数据爬虫技术实例安装教学篇
  • 浮现式设计
  • 基于游标的分页接口实现
  • 开发基于以太坊智能合约的DApp
  • 利用jquery编写加法运算验证码
  • 前端存储 - localStorage
  • 前端技术周刊 2019-01-14:客户端存储
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (20050108)又读《平凡的世界》
  • (done) 两个矩阵 “相似” 是什么意思?
  • (接口封装)
  • (算法)Game
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • .gitignore
  • .htaccess 强制https 单独排除某个目录
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .NET连接数据库方式
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [BT]BUUCTF刷题第8天(3.26)
  • [CISCN2021 Quals]upload(PNG-IDAT块嵌入马)
  • [flume$2]记录一个写自定义Flume拦截器遇到的错误