准备花点时间,简单回顾一下我们企业站点的10年演化,主要从技术的角度。其实从业务的角度也有很多可以谈的,这个暂时不做太多展开,涉及到技术要点时会简述业务特征。
在我加入公司时,公司业务已经上了轨道,并且还在爆炸式增长中,公司本身已经在nasdaq上市。整个系统的架构分server,client,enterprise site三部分。server集群由c++开发而成,管理各种资源(包括文件共享,语音,视频,白板,远程控制,讨论组,投票,Chat等等)的协作. Client是上述资源的展示,它是一个单独或嵌在浏览器的应用程序。而客户是通过web site入口启动client的。
看起来,web site貌似没啥技术含量, 只是一个入口而已嘛。可是10几年过去了,web的发展出乎大多数人的意料,随着web2.0,3.0的迅猛发展,而今构架在J2EE平台上的web site完全可以扩展和取代client甚至是server。
目录:
一 php时代
php是CGI进程模型的,意味着每个请求要新建一个CGI进程,这个对server的消耗实在有点大。当用户越来越多,请求越来越密集时,PHP已经无法抗住。
另外一个方面,由于历史的原因,php代码抽象的程度不够高,当时相当多的代码是php和html混合,可维护性比较差,无法应对潮水般涌来的新需求。当一个新员工接手面对数千行逻辑和显示都高度混杂的页面时,真是令人发狂的场面。
技术团队决定整体平台向java迁移。这其实是一个困难的决定,当时团队中java方面的高手并不多,90%都是只听过,没用过或者写过几行helloworld。就是在这种情况下,大家毅然决定边维护php版本,一边学习java开发。
二 java时代(传统架构)
经过艰苦的努力,java版上线了,得力于开源社区的给力,我们用上了Struts和ibatis,
整个系统是参考j2ee blue print范例写的。总体上封装了很多公用功能到common组件包,比如DB访问接口,Email发送组件包,文件操作组件包等,比起上一个版本,很多基础功能已经做了一定程度的封装。
mvc框架和velocity模板的使用,使得复杂页面展现和维护不再变得艰难痛苦无比。性能上,也有了不小提高,web server crash的次数大大减少。当然,由于引入了weblogic,成本也高了一大块;不过相比于蓬勃发展的业务,似乎算不了什么。
上线那一刻,我们很欣慰,这一年多的辛苦是值得的。我们似乎一下轻松了很多。
不过这样的轻松,没有维持太久。仅仅一年之后,我们重新陷入到新的困境中。
主要有三个问题:
1)随着数据量大增,oracle也终于步履蹒跚,查询慢,页面响应慢
2)频繁的jvm outofmemory,weblogic restart,严重时客户无法使用站点服务。
3)Service层,Struts actionForm越来越臃肿,各种随手写的XXXActionForm,XXXXVO,XXXServiceImpl满天飞,搞到最后原作者也记不清是干嘛用的了。经常不同的业务团队,在埋头写功能有交叉的模块代码......
DB团队开始大规模优化SQL语句;架构师团队开始定期开会研究jvm参数调整,error log分析来消除潜在代码隐患;同时对Service进行清理,分派任务到各小组和个人。
这些都起到了一定的作用,解决了一些问题(比如通过jvm参数调整,log分析Fix了很多潜在的bugs,很多废弃的Service代码被移除),但是总觉得是疲于奔命穷于应付。
像sql优化,是有限度的;当频繁进行亿级数据查询,怎么优化也快不到哪里去了。
三 java时代(引入前沿架构)
1)对某些并发特别高的业务,前面使用Nginx做负载均衡
2)对密集读的业务,引入cache center
3)使用Spring框架管理各业务bean对象,spring mvc也取代了Struts
4)引入分布式数据访问层,透明地进行分库分表,解决数据访问慢的问题
这里实际使用中,涉及太多的问题。比如
a)当单台Nginx也成为瓶颈,怎么办?[
前端使用lvs转发到多台nginx]
b)cache与db的一致性问题,使用什么策略?
[
1 写db成功才继续写入cache
2 如写入cache失败,第一次读只能命中DB,在读时写回cache
3 分布式cache的一致性:
a. 共享cache法. 禁止local cache. 这是memcached,redis的做法.采用集中式cache。这是目前使用最广泛的分布式cache策略。集中式易于管理,容易扩容.
b. 写无效法(write-invalidate). 这个是指local cache更新局部cache时,除了用写直达法更新后端存储,还需要作废其他处理机的本地cache中的相关内容. swarmcache和oscache在集群环境下采用的就是这个办法。
c. 播写法(write-update). 如名字所说.有更新时广播,同步复制(更新)到各个机器的local cache. JBossCache可以做到这一点。但是节点太多,广播的代价就过大。
d. 目录表法. 简单的说就是有一张目录表表示某一项内容在各个节点缓存中是否存在和存在状态. 写的时候用这些信息来避免写操作. 可以采用多级缓存体系,第一级用oscache,第二级用memcached.
]
c)Spring内部怎么划分业务的边界,实则是service ben的查找和互相通讯的问题
d)DDAL 怎么控制扩容时数据迁移? 全量数据和增量数据分别怎么处理?跨区处理怎么解决?(读取结果进行排序,分组问题)
e)关键字搜索使用什么技术? 搜索结果怎么排序,聚合?
每一个问题几乎都可以写一篇论文。有时间慢慢补上来。
四 java时代(服务平台架构)