做一个好的社区论坛一直是我的理想,BBS-CS从1.0到现在的5.0用了2年时间,5.0在技术上、性能上都已经基本稳定,届此想对BBS-CS的开发思想、技术做一个说明。
在2000年的时候,我的个人网站“爱情工作室”就是使用我自己的写的论坛,当时是用PHP,功能上比较简单,主要是为了网站使用,后来我想把社区论坛单独拿出来,并且爱情工作室网站也只剩下了社区这一部分,所以就开始用PHP按照网易社区结构写了BBS-CS PHP 1.0的版本,后来这个版本一直没有更新,但JSP版BBS-CS 1.0到3.0的数据结构都是从PHP版本发展来的,2000年底我开始用JAVA,2001年就写了BBS-CS1.0,后来出了2.0,1.0、2.0的安装都不是很方便,并且SQL都是在JSP中,结构不好,2002年我写了BBS-CS3.0,此时数据库操作已经用JavaBean来封装,但是3.0的性能非常不好,2003年初我写了4.0,4.0的结构已经发生了完全的变化,主要是适应多种数据库和数据库访问均衡处理,性能大大增强,并且BBS-CS定名为“天乙社区”,今年下半年我写了5.0,5.0采用了Struts的框架,国际化内核,同时支持集群运行,全文检索等等。
有人可能会拿BBS-CS和Jive来比较,觉得BBS-CS是小儿科,但我想BBS-CS的设计模式虽然没有Jive那么复杂,但是在国际化、实用性、性能等方面并不差。
一、数据库设计
BBS-CS从4.0开始,数据库结构发生了根本的变化,主要是对数据表作了负载均衡的处理,即一个功能不是使用一张表,而是使用多张同样结构的表,比如存放帖子的表有20张,这样做的目的是为了将数据库的查询压力分散到不同表中,其实道理很简单,如果一张表中存放100万条记录,和100张表,每个表存放1万条记录,查询效率是完全不一样的。具体程序中,比如一个版区的帖子往那个表中插,是由算法来实现的,算法会保证某个版区的帖子只会往某一个表中插入。
二、分页处理
BBS-CS4.0和5.0都是支持多数据库的,现在支持的数据库有Mysql、Oracle和SQL Server,在分页处理上确实要花一些功夫,以前我看过很多关于分页的技术资料,处理分页的方法主要是有几个:1、用JDBC的本身特性,将数据全部取出,然后根据页码,每页记录数,对查询出的数据集的数据滚动,这个方法比较简单、通用,但是性能极差,如果一个百万级的数据表,将耗费巨大的系统资源,甚至宕机;2、和第一种比较类似,但不是查出所有数据,只查出数据的主键,对主键滚动,然后根据主键再次查找相对应的数据,产生集合,这种方法也是EJB中实体Bean查询数据的方法,但依然存在性能问题,因为数据过多的时候主键数据集也很大,而来用主键插找数据的是后又进行了多次数据库的执行操作,性能降低。在多种分页方法比较之后,BBS-CS还是决定采用数据自身特有的SQL语句来进行分页,比如Mysql使用limit,Oracle使用rownum,SQL Server使用Top,分页类是一个抽象类,每种数据库的分页实现方法都去继承这个抽象类,然后用一个工厂方法根据系统配置文件来产生分页类的实例,采用这样的分页方法,能都达到最佳的分页查询效率。
三、系统配置文件
BBS-CS5.0的系统配置文件用了一个XML文件,在4.0的时候,系统的配置文件是采用properties文件来解决,后来我觉得properties的文件还是有很大的局限性,比如,不方便进行有数据库结构的数据进行配置,后来觉得XML文件是一个绝佳的方案,难怪现在很多产品的配置文件都是XML的:),对于XML文件的解析,BBS-CS采用了jdom,jdom就是java+dom(详细资料http://www.jdom.org),一个很方便的处理XML的软件包,在BBS-CS种对jdom的运用也不复杂,主要是用来解析bbscs.xml这个配置文件。系统解析bbscs.xml文件后,将这些系统信息保存在静态变量中,以供系统其他程序随时调用。
四、国际化与资源文件
JAVA本身就是国际化的内部采用了Unicode的编码格式,而Struts的框架,更方便了国际化的应用,Struts会根据浏览器的Locale,自动调取相应的properties资源文件,在BBS-CS就是定义的app.peoperties文件,BBS-CS只定义了中文的资源包,即app_zh_CN.properties文件,当然只要将这个文件翻译成日文、韩文等等其他国家文字,即可实现BBS-CS多语言浏览。当然只有浏览多语言是不行,数据的保存也必须是通用的格式,BBS-CS采用了UTF-8的编码格式的保存数据,以解决多语言的问题,关于Unicode、UTF-8编码格式的资料、原理大家可以在网上查找资料,我在这里不多做讲解了。
五、编码问题
在(四)中讲了国际化问题,但是如果不作处理,对中文显示处理都会有问题,要对app_zh_CN.propertie进行native2ascii的转换,这个命令是在jdk/bin下的,之后我们要做一个Servlet的过滤器,对所有的request对象进行编码的转换,com.laoer.bbscs.servlet.EncodingFilter就是BBS-CS的过滤器,它对request的编码格式进行了处理,定义为了UTF-8的编码格式。以前网上在看到过的一些文章上说,采用Servlet过滤器会有性能的下降,在我使用的感觉上来说,问题倒不是很大。
六、集群与Session处理
BBS-CS5.0设计的时候考虑到了集群的应用,因为随着系统访问量和数据的不断增长,单台服务器是很难支撑的,所以要求系统能够用多台服务器来运行,跨服务器的Session就是一个很大的问题,大家都知道Session是生存与一个应用中的,跨应用,Session必然不能共享,现在JSP容器,包括Weblogic、Resin、Tomcat都可以进行集群应用,但是配制起来可能比较复杂,所以BBS-CS实现了自己的集群运用方案。实现的原理比较简单,主要是涉及了网络编程,在JAVA中,对象只要implements了java.io.Serializable这个接口,即可实现串行化,便可以在网络中传输,BBS-CS就是把需要在网络中传输的Session对象进行串行化,在多个服务器之间进行通讯,以达到服务器之间的Session同步,同时对于几台服务器的访问是负载均衡的。
Session实现,BBS-CS在单服务器配制下是采用了应用的Session,而在机群方式下,是建立了自己的Session列表,Session是一个静态的HashTable,每个用户在登陆的时候会产生一个随机的sid,这个sid就是HashTable的key,而value则是一个HasMap,保存需要的对象。系统在运行期间会根据配置文件的Session超时时间定时对超时的Session进行清理。
七、静态变量与线程运用
为了减少对数据库的访问,系统很多地方使用了静态变量来储存数据,比如,版区列表和信息是系统需要频繁访问的,如果每次都从数据库中读取,消耗是很大的,BBS-CS采用的方法是,一次性将数据库读出,放在一个静态的列表里(HashTable),以后再访问则从静态列表中取,而不是从数据库中取,如果版区信息发生变化,只要刷新这个静态变量就行了。
通常在B/S结构下,系统的定时操作是比较困难的,因为B/S结构的软件是浏览器事件驱动的模型,而不是服务器事件驱动,在Unix/Linux下,通常是写一个脚本,然后用Crontab来跑,在win下可能就要用VB/VC/Delphi来写一个定时程序了。BBS-CS必须要做到跨品台和通用性,而线程和Sevlet提供很好的方法,一个web应用,可以在启动的时候按顺序的执行Servlet程序(在web.xml文件中定义),在Servlet中就可以启动一个线程,这个线程定时执行、休眠,便可以达到定时运行程序的目的,在BBS-CS中,清除超时Session、游客等等都是采用了线程定时执行的方式。
posted on 2006-07-14 08:47
保尔任 阅读(838)
评论(0) 编辑 收藏 所属分类:
open source