第5 页 共15页« 首页...«34567»...末页 »

用普通的java bean 做conversation scope内的组件会有这么大的性能问题,那么用ejb会怎么样呢?我今天特意做了一个测试,还是在那台开发机上,还是用那个 supplierSearchAction, 所做的变更,只是把SupplierSearchAction由普通的java bean变成了ejb。我在用ejb,普通conversation scope的java bean, 和page scope的 java bean分别测试了十次,最后的统计结果显示在conversation内ejb的性能还是要高于普通java bean的。conversation pojo 用时 5秒, conversation ejb 用时 3 秒, page pojo 用时 1 秒。在conversation内,ejb比pojo快40%, 而page scope内的pojo比前两者分别快 5 倍和 3倍。虽然还不清楚,为什么在conversation内ejb会比pojo性能要好,但在这一前提下,我们知道,如果非要写conversation内的组件,ejb将是更好的选择

Share/Save/Bookmark

近半年的项目实践让我们注意到了seam2.0.2的conversation的性能问题。测试人员抱怨系统速度慢的时候,我们一开始以为是由于数据库查询导致的性能问题。但是经过各方面排查,我们发现一个不做数据库操作的简单页面,就算是按照前文《优化richfaces,给seam提速》操作后,同样会很慢。于是我们开始怀疑起 seam本身了。一个无意中的试验发现,我把一个以前放在conversation scope内的组件换成 page scope后,速度一下子提高了五六倍。今天通过对日志的分细,证实了我的感觉。
我写了一个timefilter,记下服务器从接到http request到生成后http response后总共花掉了多少时间。被测试的action是一个普通的java bean,共有二十多个property, 里面有一个业务方法。在不改变其它代码,只改变这个java类前的annotation, 把 scope 从conversation改成page后,测试十次,page scope时要比conversation时快5到10倍!这个测试结果确实是非常地让我惊讶!conversation scope的组件到底有什么特殊的呢?

为了能够观查到seam内部的运作情况,我把org.jboss的log设成debug级别的,现在点一下页面,一个post->redirect->get,在使用page scope时会产生 1 万多行日志,而conversation scope时居然会产生 近 3 万条日志!光从这个日志的数目就可以看到 conversation 在背后不只是做了一点点工作呀!再仔细对比两者的日志,会发现,conversation scope里会多出许多处理事件的日志:instantiating Seam component: org.jboss.seam.core.events 。这句日志在conversation时出现了 3630次,而 page scope时只出现了 1464次。conversation的日志里多出了大量如下日志:

2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.preRemoveVariable.supplierSearchAction.supplierName
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.postRemoveVariable.supplierSearchAction.supplierName
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.preRemoveVariable.supplierSearchAction.employee
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.postRemoveVariable.supplierSearchAction.employee
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.preRemoveVariable.supplierSearchAction.state
2008-06-24 14:23:32,592 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
2008-06-24 14:23:32,593 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.postRemoveVariable.supplierSearchAction.state

从日志中可以看出seam 处理了大量的 org.jboss.seam.preRemoveVariable 和 org.jboss.seam.postRemoveVariable 事件,类似的事件还有 org.jboss.seam.preSetVariable 和 org.jboss.seam.postSetVariable。Seam疯狂地为conversation scope里的组件里的property 都产生了一遍这些事件。更可怕的是,并不是处理一遍,而是会处理很多遍,在我的这个测试的例子中,它处理了47遍! 这一算,1 action * 30 properties * 2 events * N times * M event listners,不是一个小数目呀,在我这个没有event observer的例子中,N = 47, 会有 1 * 30 * 2 * 47 * 1 = 2847 次操作!通过日志还可以看出 把 supplierSearchAction的所有的properties走一遍事件,要花掉 208ms, 那么 47 次这样的操作,需要 47 * 208 = 9682ms ! 9秒多的时间,绝对不是一下小数目,改成page scope后快,就快在这里。(208 / 30) * 47 = 326ms,每个bean的property, 在这个例子中消耗掉了 0.3秒时间,好昂贵呀。幸好我们公司的服务器比较牛,能够把这个差距的绝对值缩到很小,但是,这无疑是一种对CPU的浪费。

这样看来,conversation是不能乱用的,不能随便把个组件就置成conversation scope的,能把逻辑用page scope, event scope, stateless scope搞定,就尽量不要用conversation。如果有多个页面交互等操作,适合于用conversation的,那也要尽量减少 conversation scope内组件的 properties, 把 conversation 内的组件做成功能明确单一的最好。

其实,我的项目中把 supplierSearchAction放在conversation scope里就是不必要的,因为search动作都是在一个页面内完成的,用 page scope就足够了。不仅如此,还把页面上的很多输入框等通过绑定,直接绑定到conversation scope的组件上。以后再用seam的时候,一定要小心使用conversation scope了。也期待着seam的新版本能把conversation scope的组件性能提高!

Share/Save/Bookmark

公司历时近半年的java项目终于于上周上线了。在项目经理到来之前,我们在技术选型上动摇了很久,struts, struts2 ,spring mvc, grails等都试用过一些,基本上选定了struts2。项目经理到位后,他最终选定了seam这个非常新的技术,于是这近半年来,我们可以算得上是尝试吃螃蟹的人了。无论过程怎么样,最终还是完成了任务,让程序成功上线了,这至少可以说明seam已经合格了。
影响一个项目的因素非常的多,单从技术的角度来说,seam给我们带来的好处还是要更多一些的。这些好处有些是jsf提供的,有一些则是seam的发明。JSF表单里的数据到对象的绑定,减少了手动从request里解析出请求值的复杂度。richfaces能够让我们非常轻松地完成简单的ajax效果。seam的组件机制和上下文机制,让我们可以更轻松地组织后台的代码。如果没有jsf和seam,我想我们应该也能按时完成项目,但是会更累一些,多写很多代码。
使用seam,也要付出代价的。首先是对html精细控制不容易,客户有时的一些对于界面的需求不是很容易实现。其次是性能问题。处理一个复杂的页面,我的开发机上,居然要用十几秒钟的时间。好在最后部署在服务器上的时候能够经受得起性能测试,否则,后面的性能调优也是一件痛苦的事。
到目前为止,在网上能找到的关于seam的资料,依旧还是很少的,在缺少前人经验的基础上,完全的摸索,难免会走一些弯路。经过我们的努力,我们已经将一些做的不好不对的地方改正,但是还有一些问题,已经来不及修正,存在于现在的代码中。头经常会问,如果现在我们回头再做,我们还会用seam吗?我们会怎么使用seam?这个一言两语难以回答。但至少我们不会再写出一开始那种代码了。我们已经为吃螃蟹付出了代价,如果是下一个项目,不出意外, 我们还是会用seam,只是下一次会用得更好,更快。

Share/Save/Bookmark

Seam使用了richfaces做为jsf的组件库。richfaces的功能确实不错,但是性能上存在一些问题。一些简单的页面,用firefox打 开,YSlow插件都显示花掉了数秒时间。通过 firebug和YSlow插件,可以看到,打开页面的时候,浏览器会向发起很多请求,以下载javascript和css,而且这些文件的体积还不是很 少。减少请求次数,减小传输数据量,可以一定程序上改善客户端体验的性能。查阅richfaces的文档,终于找到了解决方法。

原来richfaces的默认方式是按需添下载js和css,更改它的一些参数,可以让它变成全部下载。方法是在web.xml里添加以下内容:

    <context-param>
        <param-name>org.ajax4jsf.COMPRESS_SCRIPT</param-name>
        <param-value>false</param-value>
    </context-param>
 
    <context-param>
        <param-name>org.richfaces.LoadScriptStrategy</param-name>
        <param-value>ALL</param-value>
    </context-param>
 
    <context-param>
        <param-name>org.richfaces.LoadStyleStrategy</param-name>
        <param-value>ALL</param-value>
    </context-param>

org.richfaces.LoadScriptStrategy参数让richfaces生成的页面里引用到所有js和css,并且是合并压缩过的版 本。因已经是压缩过的了,不需要再让ajax4jsf再压缩了,所以把org.ajax4jsf.COMPRESS_SCRIPT设成false。这样设 置过后,打开页面时发现,测览器这回只会下载两个js和一个css了,速度确有所提升。

另外,richfaces的rich:calendar组件不知道为什么,每次生成都会花掉很多时间。在我的开发机上,一个页面里如果添加一个rich: calendar,就会使页面生成时间多加一秒。看来richfaces还有很多要改进的地方。JSF的post->redirect-> get的方式(参看这篇文章)也是使用户体验慢的一个原因,但是这个JSF的一个基本的设计,难以改变。我很讨厌这种方式。再在回头看来,seam是不错,但是 seam把自己绑定在jsf上真是一大失误!

Share/Save/Bookmark

概述

为了优化jboss的性能,对jboss服务器做了如下改动。

  1. 设置jvm 参数
  2. 安装jboss-native
  3. 降低jboss输出日志的等级
  4. 起用了jboss内的tomcat对传输数据的压缩功能
  5. 使用ehcache做hibernate的二级缓存

下面就以上的各改动做详细说明,为了表述方便<jboss>代表jboss的安装目录:

设置 jvm 参数

编辑<jboss>/bin/run.conf,  在文件的底部找到对参数JAVA_OPTS进行设置的地方。这个参数会最后传到jvm里。其中

  1. -Xms512m 代表jvm最少用 512m内存
  2. -Xmx1024m 代表jvm最多使用 1024m内存

修改这个两参数,给jvm分配适当的内存,一般为服务器的3/4内存量,推荐至少使用4G内存。
另外添加两个参数 -XX:+UseParallelGC -XX:+UseParallelOldGC 这两个让服务并行回收内存空间。修改完成后,大致为 JAVA_OPTS = “-Xms4096m -Xmx8192m -XX:+UseParallelGC -XX:+UseParallelOldGC -Dsum…….

安装jbossNative

jboss的web container使用的 apache tomcat (http://www.apache.org)。 apache tomcat 有一个扩展包,使tomcat可以通过 java native interface 使用 apache portable runtime (APR),而APR则是大名顶顶的apache httpd 网络服务器的运行时环境。用了这个扩展之后,就使得tomcat可以借助于apache httpd的力量,性能得以提升,尤其是处理静态文件时效率更高。Jboss native,实际上就是tomcat的这个native的扩展,只不过被jboss又添进了一些为了和jboss更好协作而加进去的东西。
要安装jboss native, 按以下步骤进行

  1. 请到jboss的网站上下载,地址是 http://www.jboss.org/jbossweb/downloads/jboss-native/?action=a&windowstate=maximized, 依据服务器环境选择合适的版本。 目前我们用的版本是JBoss Native 2.0.4 Linux x86
  2. 解压下载后的压缩包到某个目录,比如 jbossNative目录
  3. 将jbossNative/bin/META-INF/bin/linux2/x86/openssl 复制到<jboss>/bin
  4. 在<jboss>/bin目录里建一个文件夹,名为 native
  5. 把jbossNative/bin/META-INF/lib/linux2/x86/ 目录下所有内容复制到上一步建好的<jboss>/bin/native目录下


降低jboss输出日志的等级

打开 <jboss>/server/default/conf/jboss-log4j.xml ,这是一个log4j的配置文件。log4j的详细配置说明请参看  http://logging.apache.org/log4j/1.2/index.html  。日志输出的太多,会导致服务器性能降低,所以减少不必要的日志输出。方法大体如下:

  1. 找到 name=”org.jboss” 的category 元素,设置里面的priority元素为 <priority value=”INFO” />
  2. 建一个新的category,内容为 <category name=”javax.faces”><priority value=”INFO” /></category>


log4j 还能够将不同的日志输入到不同的地方,为了以后维护方便,应该将不同 category的日志输入到不同的文件里。详细方法参看上面的网站里的说明。

起用了jboss内的tomcat对传输数据的压缩功能

合同管理里用了大量的javascript css等,为了减少传输时间,可以起用压缩功能。方法是:

  1. 打开<jboss>/server/default/deploy/jboss-web.deployer/server.xml
  2. 找到 protocol=”HTTP/1.1″的 Connector元素,添加属性 URIEncoding=”utf-8″ compression=”on” compressionMinSize=”2048″ noCompressionUserAgents=”gozilla, traviata” compressableMimeType=”text/html,text/xml,text/javascript, text/css, text/plain,application/xhtml+xml,application/x-javascript,application/javascript,text/xhtml”

添加完后类似于:
<Connector port=”8080″ address=”${jboss.bind.address}”   
maxThreads=”250″ maxHttpHeaderSize=”8192″
emptySessionPath=”true” protocol=”HTTP/1.1″
enableLookups=”false” redirectPort=”8443″ acceptCount=”100″
connectionTimeout=”20000″ disableUploadTimeout=”true” URIEncoding=”utf-8″ compression=”on” compressionMinSize=”2048″ noCompressionUserAgents=”gozilla, traviata” compressableMimeType=”text/html,text/xml,text/javascript, text/css, text/plain,application/xhtml+xml,application/x-javascript,application/javascript,text/xhtml”/>


使用ehcache做hibernate的二级缓存

起用二级缓存,可以大大提高hibernate的运行效率。

  1. 到http://ehcache.sourceforge.net/ 网站下载 ehcache-1.4.1.tgz
  2. 解压到某个目录,例如ehcache目录
  3. 复制 ehcache/ehcache-1.4.1/ehcache-1.4.1.jar, ehcache/ehcache-1.4.1/lib/backport-util-concurrent-3.0.jar和 ehcache/ehcache-1.4.1/lib/jsr107cache-1.0.jar到 <jboss>/server/default/lib目录

Share/Save/Bookmark


第5 页 共15页« 首页...«34567»...末页 »
© 2007 涂0实验室 | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress