这个是一个为TS公司做的一个项目,专门门针对其特定角色所使用的一个系统,并且这个是一个典型
的web application system 下面来具体谈谈个人感受.
1.网络拓扑结构
在以前的项目当中,很少去考虑和了解这个问题,为什么? 因为一般都是单个服务器上发布应用程序,
(因为鄙人技术所限制,这里所讲的所有系统都是指的与JAVA相关的系统) 如简单的免费的应用服务器
tomcat , oc4j, resin, 到稍微复杂点的 apache 整合配置 这些服务器,再到商业应用服务器oracle's 9ias
server ,weblogic server,等等,在这些服务器上发布产品,跟一般的开发模式没有太大区别,各个服务器之间
的差异也就是在配置项不同而已,所以针对这些服务器我们根本不需要去考虑系统所在网络的拓扑结构
到底是什么样的,只要确定我们的系统在服务器上能正常运行就OK了.
回到spestore system 的设计,在项目初期,也是按照这个思路来设计系统的,因为当时只是了解spestore
将要发布的平台就是oracle 9i application server, 而并没有去了解其它的信息,包括服务器是处于一种
什么样的网络架构当中.
直到spestore system 将要发布的时候,才知道我们的产品将要发布在一个9ias cluster 中.
因为缺少cluster项目的经验,不知道程序哪些动作应该做,哪些动作不应该做,而在cluster中一定都有个同步的
的动作,在一定时候它们回去同步相关信息,如果程序的关键步骤没有处理得当的话,整个应用程序的设计将就
是一个失败的设计.对整个项目的而言必将delay. 下面我们先来看看客户系统的所在网络拓扑结构,再来谈谈
在这样的一个架构当中,设计应用程序应该注意哪些东西.如下是我记忆当中系统的一个简略图:
最先client 机器上通上 发布一个请求,这个请求通过internet ,穿过firewall到达客户网络的内部.
首先来处理这个请求的将是一个LBR,一个物理的负载均衡器,通过这个均衡器自动把请求交个
后端两台web cache server 当中的负载量较小的一台server上,接着WCS 继续把我们的请求
往后端发送,(这里web cache server类似于一个software load balancer),当请求到我们9ias server
时,我们的spestore system 就会response 这个request,从而用户就可以登陆我们的系统.
置于后面的infrastructure ,db 这个就是9ias需要的基础件和数据库,我们这里就不多讲了.详细资料请
查阅oracle 的相关文档.
当用户只有1台9IAS的时候,事情很好办,我们把系统发布上去,一切都OK了.但现在关键是用户做了
cluster,那我们怎么办? 经过和客户沟通,了解到一些情况,原来客户使用的是wcs上针对后端的两台
9IAS做了软件的cluster.同时还了解到在9ias有一个同步进程,经常同步某个系统目录.所以能只要
我们程序没有写文件系统的应用,那么只需要以相同方式在两台AS上发布我们的应用,理论上是可以正常运行的.
而我们的系统使用的是3层架构的方式来设计的,DB层在另外一台机器上,所以我们不用担心发布两套系统
后数据的不一致的问题.
接下来的问题就是需要设置session的问题,因为Spestore system 是需要经过验证授权才能登陆系统的.
所以用户登陆后,接着访问其它页面时,LBR相应给客户的是同一台AS.这样才不会出现会话丢失的问题.
for example. 用户在使用AS-1服务器登陆后,当他想访问其它页面时,必须有一种机制限制AS-1继续响应客户,
而不时AS-2来响应客户的请求,否则的话如果时AS-2响应,那么用户就会看到需要重新登陆的界面.
经过查阅文档,我们发现WCS可以设置session holding.这样在软件方我们解决了session 丢失的问题.
于是,我们就以相同的方式发布正式系统在两台AS 服务器上. 系统这样就跑起来了,但是仍然还有问题.
客户测试过程中发现还是有登陆超时的页面,时有时无,但在单机测试没有发现类似问题.
在排除程序错误后,我们将错误定位到物理的LBR层,经过了解,发现LBR使用的polling而不使用
session holding ,polling动作将客户的请求使用的是另外一台WCS,这里就存在漏洞,WCS可能将
请求发给没有客户已登陆信息的AS服务器,而服务器相应给客户的就是一个没有登陆的提示页面.
因此,我们就寻求客户网络部门的人员帮助,把LBR换成session holding方式.问题解决.
问题虽然解决了,庆幸应用程序因为没有做写文件系统的操作,而得以以相对快速的方式解决问题.
但是俺还是要提醒大家一点,在系统设计初期,对程序所要发布的平台还是需要多了解些信息再开始
动手.多问自己几个如这样的问题.
a.系统需要发布在什么样的平台上面?
b.平台是否做了集群?
c.针对集群平台是否可以做写文件系统的操作?
d.平台所在的网络拓扑结构如何?
....
.
.
2.Excel文件的处理
处理excel文件,一般使用的两种常用的组件.POI,JExcel.我倾向于后者,这个开源组件
使用起来非常容易上手.但在项目需要注意的是必须事先定好excel模板的格式,再写java程序处理
这些信息,但是如果变动excel模板格式的话,java程序改动较大,所以一般不建议随便改变模板.
.
.
3.上传组件
文件上传在web application当中是常用的一个组件,有名的是jspupload组件.
不过在spestore system当中我采用了的是axman这位大虾写的upload类,改吧
改吧做成可以写文件系统和写数据库的组件.上面我们提到文件系统不能写,
于是就往oracle库里面写,当然我们也限制了客户上传文件的大小.否则客户上传个很大的文件
把你的server给撑死.做上传组件的时候有几点可以作为心得提一下.
a.使用LONG RAW 作为存储文件的类型,是可变长二进制数据,最大长度是2GB,注意long 和long raw
不能同时共存,而且一个表中有且只能有1个这样的字段.
b.通过rs.getBytes("LongRaw field")读取流的时候,必须放在第一位读取,也就是所谓的提前读取,不能放在其
它字段 读取语句背后.
c.不应在客户端调用script检查客户上传文件大小,这个可能因安全机制受限客户端.而应在server多处理限制,
但要防止全部读完再加以限制,这样因客户传一个大的文件系统,导致服务器的崩溃.
.
.
4.多线程
我们需要对用户上传的excel文件做数据验证,数据收集,并将正确数据更新到其它表中.
现在我们的excel文件已经存在数据库中,所以我们的做上述动作之前需要把文件先从
表中读取出来,而且必须锁定这条记录,在我们做处理的同时,客户或者其它程序不能对
改记录进行修改.
在了解我们的需求之后,现在我们选取能够实现的技术.解析文件夹中的excel文件,oracle
有api可以调用处理,但是对于已经存在数据库中的二进制文件,现在我还没有找到如何处理
,所以我们选用JAVA的来处理excel文件,另外因为这个动作时在后台自动进行的,所以
我们又的使用java的多线程这个特性来处理.
使用多线程的时候我们需要考虑的是
a.不能频繁的创建销毁线程,这样对平台系统开销太大,
b.线程数不能太多.不能超过操作系统所能支持的线程数.
c.1个线程处理1条记录
d.当无数据需要处理的时候,程序能自动销毁线程至最小值,并且能使之休眠,而不占用系统CPU时间片.
基于这几点要求设计了一个功能较为简单的线程池组件来处理这些事务,详细设计可以参看其它分类中的
线程池组件2的实现.
另外oracle提供基于行的锁定,我们采取类似SQL
SELECT * FROM UPLOAD_FILE WHERE ID=? AND OPERATE_STATE = 0 FOR UPDATE NOWAIT
这样for update nowait以后,只要有其它访问动作,在其它访问的应用程序端都会有提示信息.从而根本就不能
对改记录进行read or update or del 操作.
从现在系统的运行的角度来看,这样的一个线程池可以基本满足功能需要.
但是现在看来,这种设计存在一定风险.
一是客户的AS服务器还装载其它为客户服务的应用程序,在线程池处理大数据量的动作时,会大量而且
是较长时间在用CPU时间片,对其它应用程序和操作系统影响较大.
二是AS服务器在客户环境宕机和重启的几率远比数据库的要大.
重构的一种建议把处理excel文件的java文件load进入数据库,在oracle中使用schedule和queue
配合内部的java程序来处理数据.也就是完全在数据库端处理需要的事务,这个是我暂时能想到的最好
方法.
.
以上个人心得,不当之处,欢迎各位同仁拍砖.