论坛首页 Java企业应用论坛

关于系统性能的思考

浏览 27489 次
精华帖 (12) :: 良好帖 (3) :: 新手帖 (7) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-04-24   最后修改:2009-05-07

 在评价一个系统的时候,性能指标是很重要的,那么在当前J2EE的系统开发当中,如何来提高系统的性能呢?我觉得应该从对象管理入手,从对象的生命周期开始。虽然大家可能会说,Java有垃圾收集器,我们的对象的生命周期不需要我们自己管理,但是如果要是真的过分依赖java语言本身的特性,那么我相信,系统的性能肯定好不到哪去。所以,下面就主要从三个方面入手来说一下我的想法。

第一:容器化系统功能性组件

    在每个系统中,我想都会存在功能性的组件,比如当前开发当中的service,这些功能性的服务一般来说都是没有状态的,是可以多用户共享的,这种共享的服务对象,我们也需要将其进行统一的管理,幸运的是目前已经存在很多这样的管理功能性服务的框架或者容器,比如目前比较流行的各种IOC容器,或者是重量级的EJB容器,它们都提供了对系统中各种服务组件的管理。

第二:缓存化业务对象

  在说缓存之前,我不得不说一下面向对象的设计,可能有些人认为,为什么缓存会与面向对象的设计扯上关系,其实这就是缓存的关键。首先设想一下,如果开发系统的过程中,都是采用面向过程,面向数据库的思维编程,每一次业务操作,我们都是调用通过数据库操作来完成,这其实就是POEAA中的事务脚本,只适合一些简单的系统的开发,或者一个项目中,比较简单模块的开发,对于复杂的模块,更好的方式就是采用面向对象的方法来进行开发。

  好了,说到了面向对象的设计问题,至于这个问题已经有很多书籍以及很多人讨论了很多年了,就我个人来说,我觉得采用DDD建模是目前比较适合的一种方式。DDD中涉及到得每种模式或者说是每一种模型元素对于缓存设计来说都是很重要的,下面我说说我的想法:

 首先我说一下关于聚合的问题,为什么说聚合对于缓存非常重要呢?这其实涉及到了一种控制访问的问题,一个聚合根控制了对整个聚合的访问,要想访问聚合里的对象必须要通过聚合的根。

 好了,我们以一个实例来说话,比如一个论坛的设计,论坛中有Forum以及ForumState对象,Forum对象是聚合的根,是一个实体模型,而ForumState是一个值对象,并且是属于Forum这个聚合根的子对象,我们把ForumState对象从Forum对象分离出来,好处主要有两个,从事务的角度来说,当我们更新ForumState对象的时候,不用锁住Forum对象,从缓存设计的角度来说,当我们更新ForumState对象的时候不用刷新Forum对象的缓存,因为Forum不是经常改变的,所以不必要因为经常改变属性的改变而改变。那么具体怎么来设计呢?我们可以这样做,在ForumState对象中设置一个状态位,表示它的状态是否已经改变,当Forum状态发生改变,比如有人创建新的帖子或者回复了帖子后,我们可以设置这个状态位为true,表示状态已经改变,这样当再次从缓存中取得Forum时,查看状态位,如果发现已经变化了,那么就重新从数据库加载ForumState。当然要想达到这种效果,我们一定要设计好聚合,所有对子对象的访问都要通过聚合的根,比如所有对ForumState对象的访问都要经过Forum对象,并且要保证所有的数据库操作,都首先从统一的缓冲入口进行,这样保证了整个系统中用的是同一个缓存,大家操作的所有对象都是同一个缓存中的对象。所以这里也给出了一条对象设计的提示,将经常变化的熟悉和不经常变化的属性分开,并且将经常变化的属性独立出去,作为聚合根的 一个子对象,这样做到变和不变分离,不仅有利于高内聚,而且有利于事务的控制和缓存的更新。

 

 

 

<!--EndFragment-->

   上面是关于Repository在对象建模中的作用,下面我也说说关于工厂的作用,既然是工厂,那么它肯定要生产东西出来,但是它不能随便乱生产,它生产出来的应该是整个聚合的根,并且要保证这个聚合的不变量受到保护,这样通过工厂提供一个集中的模型创建的访问点,也方便了控制访问。要设计一个好的工厂,我们首先需要设计一个好的对象模型,分辨出合理的聚合,这样工厂才会发挥真正的效力。

    最后既然说到了缓存,还有一点需要注意,那就是这个缓存的范围,我这里说的缓存是全局的缓存,是一个application级别的缓存。我个人是比较反对在Httpsession中保存大量数据的,这样当用户增多的情况下,比如会浪费很多的内存,浪费性能。所以我们更应该需要的是全局的缓存,这样底层的缓冲框架我们还可以采用分布式的缓存系统,这样以来我们的系统在集群环境下也免去了一些session failover的开销。这其实也是一种SNA架构的思想。

第三:数据库系统优化

 数据库在我们大多数的系统开发中都会涉及到,这方面的优化,主要是基于一些索引等的优化。

    最后,我想说的就是我们应该尽量采用一种面向对象的方式来开发我们的系统,而不是过分的依赖数据库来编程,在系统开发当中,我们操作具体的模型对象,而我们的模型对象由存储在缓存中,尽量减少对数据库的访问操作,从而提升系统的性能。

 

 

 总结上面所述,要想提高系统的性能,我们面临的难题就是对象建模,只有我们针对自己的具体的业务有了合理的对象模型后,我们才能有针对性的对业务对象进行缓存,从而使得缓存的效果最大化,提高系统的性能。

<!--EndFragment-->

   发表时间:2009-04-24  
楼主考虑的完全正确。
不过有一点,随着业务逻辑的递增,项目需求的递增,那么包括你所说的缓存机制和数据优化的方法也会相对复杂起来。所以我觉得"软"+"硬"一起配合才增生效。
"软:"就是从技术角度出发,根据项目需求而指定一套优化方案,譬如:
利用cache的缓存机智。缓存一些静态或动态文件,缓存一起相关对象。等等。可以对性能的提升有很大的帮助。目前的缓存框架也不少。不过问题也随之而来,就是怎样才能把缓存机制独立出来,配合业务逻辑而更有效、更灵活的运用起来。再一个问题就是,无论怎么缓存最终如果超越了应用服务器的指定内存空间,最后不但效率没有提升相对来说会内存益出。所以,内存最终建立在应用服务器上,而应用服务器是建立在实施服务器上。那就是所谓的“硬”了。
"硬"件的配置也同样重要。如果一个网站要做在线聊天,大量并发,大量吞吐的情况的下不但要提升服务器的配置,必要的话要做服务器集群。
  所以我的最终观点是:缓存必然要做,但不能泛滥的做。数据库必然要优化但要根据需求优化,并不是所有的优化都会有效。
4 请登录后投票
   发表时间:2009-04-24  
要提高性能,最关键的是客户端和服务器的合理分工.
现在啥事情都扔给App服务器去干,最后不慢才怪.
把界面方面的事情扔给客户端,后台只提供数据服务,自然性能就高了.
光限制在服务器上折腾,是不能从根本上解决问题的.
光说缓存的问题,就有4个地方的缓存,客户断的,Web服务器的,App服务器的,Db 服务器的.
楼主的思路还是局限在一个App Server上想把问题搞定,这是不够的.
2 请登录后投票
   发表时间:2009-04-24  
liujunsong 写道
要提高性能,最关键的是客户端和服务器的合理分工.
现在啥事情都扔给App服务器去干,最后不慢才怪.
把界面方面的事情扔给客户端,后台只提供数据服务,自然性能就高了.
光限制在服务器上折腾,是不能从根本上解决问题的.
光说缓存的问题,就有4个地方的缓存,客户断的,Web服务器的,App服务器的,Db 服务器的.
楼主的思路还是局限在一个App Server上想把问题搞定,这是不够的.


Web服务器的,App服务器的,Db 服务器的 你这三个 都是基于服务器的。
客户端的缓存只可以减少一些服务器断的东西,但客户端所占用的比例不大。如图片,静态文件等等。
真正意义上还是以优化服务器,优化数据库。服务器性能跟不上,客户端在缓存、再人性化、再优化话有啥用。
0 请登录后投票
   发表时间:2009-04-24  
恩,上面两位说的都有道理,我这里想说的就是缓存要配合业务对象建模来使用,如果采用面向过程的开发,系统没有一个合理的对象模型,那么缓存的作用就不大。如果要说缓存的位置,那太多了,cpu也有高速缓存的,JVM也有缓存的,DB也有缓存的等等,所以结合自己的业务模型来做适合自己的业务的缓存才是真正适合自己的。并且对于缓存,我觉得全局application缓存会比较好,session中尽量少保存数据。

对于shuai45兄弟说的,很认同,软件的伸缩性可以从两个层面进行,分别是水平伸缩性和垂直伸缩性,水平伸缩从软件设计高度来考虑,而垂直伸缩从硬件的角度来考虑。

对于liujunsong兄弟说的,也有道理,客户端的缓存确实也很重要,比如我们可以通过javascript,json来将客户的状态先保存到客户单浏览器进程中,比如我知道一个公司就采取了这种方式,新建,修改和删除操作首先缓存到客户端,当最后用户真正提交的时候,在通过AJAX异步的将缓存刷新到服务器端。

1 请登录后投票
   发表时间:2009-04-24  
既要提高性能,又要考虑开发效率。架构问题是一门很有研究的学问
0 请登录后投票
   发表时间:2009-04-24  
狂放不羁 写道
恩,上面两位说的都有道理,我这里想说的就是缓存要配合业务对象建模来使用,如果采用面向过程的开发,系统没有一个合理的对象模型,那么缓存的作用就不大。如果要说缓存的位置,那太多了,cpu也有高速缓存的,JVM也有缓存的,DB也有缓存的等等,所以结合自己的业务模型来做适合自己的业务的缓存才是真正适合自己的。并且对于缓存,我觉得全局application缓存会比较好,session中尽量少保存数据。

对于shuai45兄弟说的,很认同,软件的伸缩性可以从两个层面进行,分别是水平伸缩性和垂直伸缩性,水平伸缩从软件设计高度来考虑,而垂直伸缩从硬件的角度来考虑。

对于liujunsong兄弟说的,也有道理,客户端的缓存确实也很重要,比如我们可以通过javascript,json来将客户的状态先保存到客户单浏览器进程中,比如我知道一个公司就采取了这种方式,新建,修改和删除操作首先缓存到客户端,当最后用户真正提交的时候,在通过AJAX异步的将缓存刷新到服务器端。


“我觉得全局application缓存会比较好,session中尽量少保存数据。”
目前有很多缓存框架。OSCACHE就非常不错。我没做过大项目,基本都是数据库能解决的就用数据库。
实在解决不了 或者性能存在一些问题 就通过程序 上解决。不过这样做 并不好,完全的被动。所以 一个项目要从设计上就考虑优化,而且可扩展。
这样的经验 实在太少。希望LZ把你的开发经验分享一下。
0 请登录后投票
   发表时间:2009-04-24   最后修改:2009-04-24
shuai45 写道
“我觉得全局application缓存会比较好,session中尽量少保存数据。”
目前有很多缓存框架。OSCACHE就非常不错。我没做过大项目,基本都是数据库能解决的就用数据库。
实在解决不了 或者性能存在一些问题 就通过程序 上解决。不过这样做 并不好,完全的被动。所以 一个项目要从设计上就考虑优化,而且可扩展。
这样的经验 实在太少。希望LZ把你的开发经验分享一下。


对于如何设计一个扩展的业务对象模型,我目前也处于探索中,但是我敢肯定的就是设计对象模型是一定要划分出一个边界,然后设计为一个聚合,这样整个对象模型由不同的聚合来构成,并且访问聚合内部的对象都要通过聚合根来控制。这样提供一个全局的访问控制点,便于维护和管理。并且我们设计聚合的时候,一定要区分出根对象中哪些属性是经常变化的,哪些不是经常变化,这样我们可以把经常变化的属性独立出来,作为一个值对象。这样通过对对象的细粒度的设计,我们可以更容易控制我们的缓存。所以我觉得对象生命周期很重要,这就设计到了DDD中的工厂和仓库两个模式,我目前的设计中,我是通过工厂来控制对象生命周期的起始,并且保证对象创建出来的聚合根式满足系统不变量的约束的,那么对象创建以后,其它的生命周期交给仓库管理。仓库(repository)管理对象创建以后的生命周期,我觉得这个时候就要使用缓存来管理了,我们要想得到领域对象,只能从一个地方来获得,那就是仓库,而仓库首先通过一个全局的缓存中去获得对象,如果缓存中没有就从数据库或者其它持久性数据源得到对象,然后放到缓存中,这样系统中的所有对对象的访问,都需要经过统一的地方:仓库。当系统中发生了引起领域对象状态变化的操作以后,我们可以清空缓存中的对象或者只清空领域对象的一部分,比如分离出来的状态。

最后使用全局的缓冲还有一个好处,那就是集群环境下面,因为我们可以把全局缓冲通过一个分布式的缓冲透明的替换,这样减少了不同节点之间同步session,以及session failover的开销,这其实就有点SNA的味道了。呵呵。



不知道您有没有读过:<<领域驱动设计>>这本书,这本书我觉得非常好,如果没看过,推荐您看看。这里面详细简介了如何开发一个针对于自己当前业务状态的对象模型。
0 请登录后投票
   发表时间:2009-04-25  
人讲究性能,机器也讲究性能.人和机器一样,性能无非就受两点影响1.先天因素 2.后天培养
先天因素我们无法改变,人就长成那样了或者机器就那个配置了,这种情况没啥办法.
后天培养倒是可以提高一点性能,但是提高的有限度.就好比你没有办法让手机跑ORACLE一样,
架构和性能绝对是唱反调的.人为了道德要穿衣服,但是穿上了越好的衣服性能也就受越大的影响(最起码时间上没有不穿的快).

技术可以提高性能,池话,负载均衡,分布式都可以提高性能,但是这些都有瓶颈.这就好比人的药物治疗,不治本.

业务设计才是提高性能的王道.业务是一个系统的灵魂,就好比是人类的DNA.改造DNA 进行业务的深度分析才能从根本上提高性能.
4 请登录后投票
   发表时间:2009-04-27  
狂放不羁 写道
shuai45 写道
“我觉得全局application缓存会比较好,session中尽量少保存数据。”
目前有很多缓存框架。OSCACHE就非常不错。我没做过大项目,基本都是数据库能解决的就用数据库。
实在解决不了 或者性能存在一些问题 就通过程序 上解决。不过这样做 并不好,完全的被动。所以 一个项目要从设计上就考虑优化,而且可扩展。
这样的经验 实在太少。希望LZ把你的开发经验分享一下。


对于如何设计一个扩展的业务对象模型,我目前也处于探索中,但是我敢肯定的就是设计对象模型是一定要划分出一个边界,然后设计为一个聚合,这样整个对象模型由不同的聚合来构成,并且访问聚合内部的对象都要通过聚合根来控制。这样提供一个全局的访问控制点,便于维护和管理。并且我们设计聚合的时候,一定要区分出根对象中哪些属性是经常变化的,哪些不是经常变化,这样我们可以把经常变化的属性独立出来,作为一个值对象。这样通过对对象的细粒度的设计,我们可以更容易控制我们的缓存。所以我觉得对象生命周期很重要,这就设计到了DDD中的工厂和仓库两个模式,我目前的设计中,我是通过工厂来控制对象生命周期的起始,并且保证对象创建出来的聚合根式满足系统不变量的约束的,那么对象创建以后,其它的生命周期交给仓库管理。仓库(repository)管理对象创建以后的生命周期,我觉得这个时候就要使用缓存来管理了,我们要想得到领域对象,只能从一个地方来获得,那就是仓库,而仓库首先通过一个全局的缓存中去获得对象,如果缓存中没有就从数据库或者其它持久性数据源得到对象,然后放到缓存中,这样系统中的所有对对象的访问,都需要经过统一的地方:仓库。当系统中发生了引起领域对象状态变化的操作以后,我们可以清空缓存中的对象或者只清空领域对象的一部分,比如分离出来的状态。

最后使用全局的缓冲还有一个好处,那就是集群环境下面,因为我们可以把全局缓冲通过一个分布式的缓冲透明的替换,这样减少了不同节点之间同步session,以及session failover的开销,这其实就有点SNA的味道了。呵呵。



不知道您有没有读过:<<领域驱动设计>>这本书,这本书我觉得非常好,如果没看过,推荐您看看。这里面详细简介了如何开发一个针对于自己当前业务状态的对象模型。

听楼主的意思,我感觉是 设计模式+CHCHE的组合呢。就是把缓存的意思设定在设计模式的基础上。如果这样的话,缓存的意思感觉存在性不大。重点的是项目的整个设计。看来还是以设计为主。可扩展、高性能在是主要,至于技术实现 是次要。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics