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 ...
随机推荐
- 13 ThreadLocal
ThreadLocal 在多线程环境下,每个线程都有自己的数据.一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁. 1. 使用函数 ...
- MySQL数据库服务器逐渐变慢分析
第一步 检查系统的状态 1.1 使用sar来检查操作系统是否存在IO问题 #sar -u 2 10 — 即每隔2秒检察一次,共执行20次. [root@CacheMemCache tester]# s ...
- [网站公告]18:07-18:20阿里云SLB故障造成网站不能正常访问
(注:由于阿里云SLB管理控制台监控数据不准,实际故障时间是18:07-18:20.) 17:55-18:2018:07-18:20,我们使用的阿里云SLB(负载均衡)中有3台出现突发故障,造成全站无 ...
- Vue学习(五):列表渲染
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- sphinx调用API参考(官方手册)
API的参考实现是用PHP写成的,因为(我们相信)较之其他语言,Sphinx在PHP中应用最广泛.因此这份参考文档基于PHP API的参考,而且这节中的所有的代码样例都用PHP给出. 当然,其他所有A ...
- Python 3 学习笔记之——错误和异常
1. 语法错误 Python 的语法错误被称为解析错,语法分析器会指出出错的代码行,并且在最先找到的错误的位置标记一个小小的箭头. >>> while True File " ...
- Codeforces Round #326 Div.1 C.Duff in the Army 树上倍增
题意概述: 给出一棵N个结点的树,然后有M个居民分散在这棵树的结点上(允许某个结点没有居民).现在给出一些询问形如u,v,a,定义k=min(x,a),其中x表示的是u->v路径上的居民数量.将 ...
- HDU 4722 Good Numbers(位数DP)(2013 ACM/ICPC Asia Regional Online ―― Warmup2)
Description If we sum up every digit of a number and the result can be exactly divided by 10, we say ...
- jquery用正则表达式验证密码强度
/** * 不加paste鼠标粘贴不起作用 * 不加input第一次粘贴的时候不变 * 加上input和focus可以兼容表情 * ke ...
- [org.hibernate.engine.jdbc.spi.SqlExceptionHelper]SQL Error: 1064, SQLState: 42000问题的解决办法
[org.hibernate.engine.jdbc.spi.SqlExceptionHelper]SQL Error: 1064, SQLState: 42000问题的解决办法. 出现这种情况的原因 ...