All in One到”分布式“迁移过程中的坑
为什么“分布式”要加引号?
与其他公司提高并发性能的场景可能不太一样,我们的系统之前是多个模块共用一个tomcat来运行的(All in One),模块有很多,光安装包就几十个。当某个模块或某几个模块出问题的时候,整个tomcat就挂了,请求时间长、内存占用高、垃圾回收频繁、错误日志不停的刷....现场工程解决问题的办法是,重启tomcat(小问题重启浏览器,大问题重启tomcat,万能的重启^_^)!!当然,这个对用户的使用体验很差,用户甚至提出要弃用我们公司系统的说法了,领导压力大啊...
因本项目历史久远、技术落后、规模庞大、交接频率高,想系统的发现及解决问题是件很困难的事。重新开发一套系统也是不可能的事(这套系统积累了太多的心血在上面了,无论从人力、时间成本来说都花费太大,下不了狠心)。于是,分布式部署的方案被提上了工作日程,目的是将各模块隔离开来,出问题的时候互不影响。但是,一套不是面向分布式的设计的系统,要想实现分布式部署,就像是将一大团的乱麻分成一团团小的乱麻(哈哈,这比喻我觉得挺恰当的,分开来后还是乱麻^_^),谈何容易啊!
艰巨而又头疼的任务分给了我们组。经过几轮讨论后,列出了几个关键的问题:
1、 静态变量共享问题。单独部署的情况下,各业务注册的数据,如字典数据、关键词类型等,存放在全局的静态变量中的;分布的情况下,各业务只能获取到自己模块注册的数据,获取不到全量的数据。
2、 定时任务重复执行问题。分布式的情况下,会有多个界面框架模块共存。界面框架中的定时任务执行次数和执行频率都会变高。其实从机器中的定时任务是不需要的。
3、 文件上传与读取问题。All in One的情况下,界面框架提供统一的上传组件,文件上传到一个固定目录下,各业务可以通过绝对路径获取到文件,直接操作文件流。分布式的情况下,业务上传的文件会上传至主框架上,当从节点通过绝对路径去访问时,肯定是获取不到文件的。
4、 session共享问题。All in One的情况下,各业务拿到的是同一个session;分布式的情况下,各业务的sessionID不通,session也不是同一个session,一个机器上修改了session的数据,其他机器要实时感知到数据的变化。
5、 请求分发问题。各业务的请求,应该被正确的分发给各业务机器处理,各业务机器处理请求时不需要登录,登录统一由主框架负责处理。
6、 安装时重复刷菜单的问题。All in One的情况下,安装或升级某个包时,会将对应的菜单刷到菜单表中。分布式的情况下,各从机器升级界面框架包时,也会刷界面框架的菜单,很可能导致菜单表的数据出问题。
7、 单例问题。不确定具体的影响范围。
8、 多线程执行顺序问题。不确定具体的影响范围。
9、 事务。不确定具体的影响范围。
10、 各机器对时。不确定具体的影响范围。
大概确定了思路如下:
1、 各模块单独部署在各自的tomcat里,各模块安装需依赖界面框架模块。
2、 通过nginx做代理,保证对用户的入口唯一。按各模块url请求规则,分配到各自的tomcat上处理请求。平台公共的请求由一个tomcat单独处理。
3、 tomcat通过共享session,与nginx呼应,确保用户会话在多个tomcat共享。
4、 引入Spring-session模块,将session存储到redis服务器上。
5、 将静态变量通过redis的发布/通知机制,修改代码,实现静态变量的同步。
6、 增加nginx配置服务,用于管理各业务的请求转发规则,并定义各机器的角色。主节点只能有一台,负责处理公共请求、执行界面定时任务、刷界面框架的菜单;从节点的界面框架负责支撑业务功能。
7、 增加文件服务器,将上传的文件存储到文件服务器上。
8、 其他问题暂不确定具体的影响范围。
未完待续,后面整理迁移过程中遇到的坑!
坑1:Spring session 提交问题
因要对session共享,使用的spring session本以为万事大吉,结果问题来了。看下代码:
UserBean user = (UserBean )session.getAttribute("currentLoginUser"); System.out.println(user.getName()); user.setName("张三");
单机的情况下,没毛病吧,我就想改下session里的用户信息。如果你这么放心的把sesson交给spring,那就等着测试部提问题吧。如果不退出或关闭浏览器的话,你会发现修改的用户信息,你刷新后,竟然没有生效!!!于是就想,spring-session是怎么保证session存储到redis上的呢?不卖关子了,redis通过hash类型存储session中的数据,session内的数据有变化时,会将修改的数据更新到redis上,为了提高效率,spring在filterchain结束的时候提交一次session数据到redis,而不是每次修改session数据都去提交一次。那spring怎么知道session的哪些数据变了呢?跟了下源码发下,只有在主动调用session的setAttribute和removeAttribute方法时,才会将修改的数据放到this.delta中,最后提交数据时,就是把这里的数据更新到redis的。所以为什么修改的user数据没有生效呢?因为没再次调用setAttribute方法,spring感知不到对象属性的变化!!坑爹啊~~自己修改了spring的提交逻辑,与旧的session进行了equals对比,把有变化的数据放入this.delta中,解决问题了?并没有!!最终发现UserBean重写了equals和Hash方法,只要用户ID相同,就返回true,我只想说,你大爷的!!
坑2:与其他系统融合的问题
暂给我们的系统取名A系统,现有个B系统也要用B系统的一些数据,于是取了个名字叫“A与B系统的融合”。所谓A与B的融合,其实就是实现B系统的免登陆,并获取A系统的一些内存数据。于是,两个不同的系统,session就共享了...
于是,当你在使用A系统的时候,很多莫名其妙的反序列的问题就出来了。为什么会报反序列化的错误?因为session里面有B系统的对象,但A系统根本就没有B系统的jar包。实现免登陆,可以走单点登录吧?想获取A系统的数据,可以让A系统提供接口吧?为什么要共享session?我也不知道了。
All in One到”分布式“迁移过程中的坑的更多相关文章
- 转载自lanceyan: 一致性hash和solr千万级数据分布式搜索引擎中的应用
一致性hash和solr千万级数据分布式搜索引擎中的应用 互联网创业中大部分人都是草根创业,这个时候没有强劲的服务器,也没有钱去买很昂贵的海量数据库.在这样严峻的条件下,一批又一批的创业者从创业中获得 ...
- 分布式数据库中的Paxos 算法
分布式数据库中的Paxos 算法 http://baike.baidu.com/link?url=ChmfvtXRZQl7X1VmRU6ypsmZ4b4MbQX1pelw_VenRLnFpq7rMvY ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据
转自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/index.html Zookeeper 分布式服务框架是 Apa ...
- ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据
引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们 ...
- J2EE分布式事务中的提交、回滚方法调用异常。
这个是昨天上班的时候,写一个后台程序的调试程序时碰到的问题,和项目经理纠结了一天,最后搞定了.于是今天上班正好闲着,花了几乎一天的时间去网上找各种相关的资料.目前了解的内容如此: 根据使用的weblo ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据(转载)
本文转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Had ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据--转载
原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Hadoop ...
- 在分布式数据库中CAP原理CAP+BASE
本篇博文的内容均来源于网络,本人只是整理,仅供学习! 一.关系型数据库 关系型数据库遵循ACID规则 事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性: 1.A (At ...
- SQLServer2PostgreSQL迁移过程中的几个问题
1.PostgreSQL 跨平台迁移工具Migration Toolkit的使用指南:http://www.enterprisedb.com/docs/en/8.4/mtkguide/Table%20 ...
随机推荐
- CC3100BoosterPack和CC31XXEMUBOOST板子的测试
1. 先测试右边的CC3100BoosterPack,测试发现LDO坏了,无法输出3.3V,所以只能用左边的板子供电. 2. 插上CC31XXEMUBOOST板子的J1,两个板子插在一起,等待驱动安装 ...
- 深入浅出 Webpack
深入浅出 Webpack 评价 Webpack 凭借强大的功能与良好的使用体验,已经成为目前最流行,社区最活跃的打包工具,是现代 Web 开发必须掌握的技能之一.作者结合自身的实战经验,介绍了 Web ...
- ArcGIS Server远程处理服务器(环境设置)
当使用ArcGIS Server做远程处理服务器执行影像处理操作时,提示ERROR 999999通用错误代码,如下: Start Time: Mon Jul 03 13:49:06 2017Distr ...
- 使用hibernate连接Oracle时的权限问题
在使用hibernate对象关系映射连接和创建表的时候,会涉及到很多权限问题,有些数据库管理会将权限设的很细,我们可以根据后台日志错误和异常信息作出判断. 比如下图所示这个错误(这是我在给银行投产系统 ...
- DOM操作相关案例 模态对话框,简易留言板,js模拟选择器hover,tab选项卡,购物车案例
1.模态框案例 需求: 打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框 代码如下: <!DOCTYPE html> <h ...
- AcCoder Contest-115 D - Christmas
D - Christmas Time limit : 2sec / Memory limit : 1024MB Score : 400 points Problem Statement In some ...
- (转载)Linux进程间通信
(在学习linux进程通信,看到一篇很好的文章,转载过来,原文地址是http://www.cnblogs.com/linshui91/archive/2010/09/29/1838770.html) ...
- JAVA_四大代码块_普通代码块、构造代码块、静态代码块、同步代码块。
普通代码块 在方法或语句中出现的{}里面的内容就被称为普通代码块,普通代码块和一般的语句执行顺序一样,由他们在代码中出现的次序决定,即--"先出现先执行". 但是不同的普通代码块即 ...
- gdb调试行号错位
http://blog.csdn.net/wangxmin2005/article/details/8128192 gdb调试过程中出现行号错位的情况,原因一般有两个: 1. 编译器的优化可能把某些语 ...
- 2017Nowcoder Girl初赛重现赛
https://ac.nowcoder.com/acm/contest/315#question A.平方数 代码: #include <bits/stdc++.h> using name ...