鹰翔宇空

学习和生活

BlogJava 首页 新随笔 联系 聚合 管理
  110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks
原文摘自:http://forum.javaeye.com/viewtopic.php?t=17501&postdays=0&postorder=asc&start=0

文章时间: 2005-12-11 12:15:26    标题: 引用回复 将这个帖子加入我的Blog

hongliang 写道:
那这么说来,假设Hibernate在第一秒拿到叻数据库连接,这个连接不还是持续15秒么?


如果是网络传输速度导致load页面需要15秒,那么时间消耗在网络传输上,本身页面执行时间很短。

如果不是网络传输速度导致load页面需要15秒,那说明什么?说明这个页面的程序执行了15秒!为什么一个页面程序需要执行这么久呢?说明这个页面的数据库查询非常耗时!(纯内存操作都是ms级别的,如果都10多秒了,瓶颈只可能是数据库操作) 如果数据库查询需要15秒,请问你就算不用OpenSessionInView,你不是一样需要打开数据库连接长达15秒吗?
文章时间: 2005-12-11 12:32:42    标题: 引用回复 将这个帖子加入我的Blog

我明白robbin你的意思,我说的情况就是网络传输导致的15秒。本身页面执行的时间,比如freemarker渲染一下模板,这个速度是非常快的,没问题,可是我的疑问就在于如果网络传输狠慢,会不会影响到数据库连接。

假设WebWork+Hibernate+FreeMarker架构模型是这样的

Request
|
|---other filters...
|
|---OpenSessionInView Filter
|
|-----WebWork Controller
|
|---Action
|
|---FreeMarker Result(对response.getWriter()做process()操作)
|
|
|---OpenSessionInView Filter
|
|---other filters...
|
Request


这里有两种情况。

一是页面缓冲区足够大,足够一次性容纳所有的页面,这样渲染页面就会一次性进入缓冲区,然后返回到OpenSessionInView Filter,关闭Session,数据库连接返回池中,一切OK。

第二种情况我是重点想讨论的,也是我的疑虑所在。那就是假如这个页面比较大,超出叻页面缓冲区的大小,那么渲染页面时,就拿FreeMarker/Velocity这样的模板语言来说,它执行process/merge方法,往servlet的response writer/outputStream里面写东西,写着写着,发现写不动叻,是缓冲区满叻,而这个writer/outputStream,正是服务器同用户之间建立的socket请求,于是底层代码开始先向用户传输一部分页面,传好后,又有叻新的缓冲区,FreeMarker/Velocity的方法又能向缓冲区里写东西叻。而传输页面这个过程,又耗费叻几秒钟的时间,就导致叻数据库连接被占用叻狠长的时间。

可能我描述的是错误的,希望robbin指正!:)
文章时间: 2005-12-11 13:07:27    标题: 引用回复 将这个帖子加入我的Blog

我觉得这个问题归根结底就是AppServer究竟会如何实现页面输出。那么必然和具体的应用服务器实现有关系。那么至于每个AppServer究竟会怎样去实现,我就不得而知了。起码大家可以研究一下Tomcat源代码看看tomcat是如何实现的。

confluence采用的就是Hibernate/Spring/Webwork架构,OpenSessionInView,以confluence这么广的使用,好像也没有听过这方面的问题投诉。
文章时间: 2005-12-11 18:26:22    标题: 引用回复 将这个帖子加入我的Blog

我写了一个简单的webapp在Tomcat5.5.12上面做了一个小测试。在JSP页面里面循环1万次输出字符串,程序在远程服务器上面运行,网络是ADSL宽带,filter确实被阻塞了20秒左右。然后我另外开了一个flashget去下载服务器上的大文件,模拟网络速度比较慢的环境,filter被阻塞了50秒左右。分别做了三次测试。另外当页面下载过程中直接点击浏览器stop按钮,则JSP执行被打断,filter立刻解除阻塞,被执行完毕。

结论证明,使用OpenSessionInView的时候,如果render的页面数据量非常大,并且客户端网络速度很慢的情况下,由于页面的输出时间过程很长,确实会造成filter被长时间阻塞。对于OpenSessionInViewFilter来说,就会造成数据库连接被保持很长的时间,才能被关闭。

不过,对于Spring的OpenSessionInViewFilter来说,虽然数据库连接被保持了过长的时间,但是并没有锁定数据库资源,特别是事务资源。因为Spring的事务是通过TransactionInterceptor来实现的,在MVC结构中,当最后一个业务bean被调用结束以后,Transaction就已经被提交了。此后,虽然数据库连接还保持中,但是数据库资源没有锁定问题。

完整的调用示意图:

request -> (OpenSessionInViewFilter打开Session) -> ServletDispatcher -> Action -> (打开Connection,启动事务) -> spring bean -> another spring bean -> (提交事务) -> bean执行完毕,返回Action -> render view(JSP/Template) -> (OpenSessionInViewFilter关闭Session和Connection)
文章时间: 2005-12-11 22:44:45    标题: 引用回复 将这个帖子加入我的Blog

robbin的分析很透彻,对于最后一点,我稍有疑问。

引用:

对于Spring的OpenSessionInViewFilter来说,虽然数据库连接被保持了过长的时间,但是并没有锁定数据库资源,特别是事务资源。


其实我认为数据库连接被保持过长时间有时候会有很大的问题。尤其是对于采用数据连接池的情况,如果你的数据库连接一直被保持,那么这个资源就未被释放。假设说这个数据连接池的最大连接数为15,我感觉很容易造成数据库的连接不够用。

不清楚底层的实现是如何做的,或许我的疑问有些多虑。
文章时间: 2005-12-11 22:51:56    标题: 引用回复 将这个帖子加入我的Blog

downpour 写道:
robbin的分析很透彻,对于最后一点,我稍有疑问。

引用:

对于Spring的OpenSessionInViewFilter来说,虽然数据库连接被保持了过长的时间,但是并没有锁定数据库资源,特别是事务资源。


其实我认为数据库连接被保持过长时间有时候会有很大的问题。尤其是对于采用数据连接池的情况,如果你的数据库连接一直被保持,那么这个资源就未被释放。假设说这个数据连接池的最大连接数为15,我感觉很容易造成数据库的连接不够用。

不清楚底层的实现是如何做的,或许我的疑问有些多虑。


按道理来说,数据库连接应该尽早被释放,以缓解数据库资源的压力,延迟很久才释放,确实会导致需要更多的数据库连接。这个就只能扩大连接池数量,增加数据库最大允许连接数来解决了。

此外,Session被延迟很久释放,那么Session占用的一级缓存也会占用比较长时间,这意味着会无谓消耗更多的JVM内存。

因此,OpenSessionInView虽然确实方便,但是大家还是慎用吧。对于那些页面渲染速度很慢,拨号连接用户数量过多的网站就最好不要使用。
文章时间: 2005-12-14 10:22:24    标题: 引用回复 将这个帖子加入我的Blog

引用:
因此,OpenSessionInView虽然确实方便,但是大家还是慎用吧。对于那些页面渲染速度很慢,拨号连接用户数量过多的网站就最好不要使用。

确切的应该是大并发用户量的情况吧。这个问题一直都存在,在1年多前我和robbin争论中就提出来了过。hibernate2的代码可以看到session是和connection紧密耦合的(Hibernate3没看过)。但hibernate大部分被用于并发用户可预见的intranet应用,所以问题也不是很大。如果并发用户多,对connection pool资源, opensession in view在hibernate中使用会构成较大压力。如果jboss j2ee5 server采用hibernate作为ejb3实现,没有做修正的话,同样的问题也会存在于jboss j2ee5 server中。


上一次由Charlesxp于2005-12-14 周三, 上午10:25修改,总共修改了2次
文章时间: 2005-12-14 10:22:33    标题: 引用回复 将这个帖子加入我的Blog

hongliang 写道:
几天没来,居然变精华叻。。。本来我也想做一下robbin的那个测试,结果这几天忙于其它事,一直没时间。看来OpenSessionInView果然有这个问题,这也是我一直担心的,看来真是应叻那句话,“如果一件事可能出错,那它一定会出错”。。。

不过,如果不用OpenSessionInView,我还真一下子就找不到北叻,从学Hibernate开始就一直在OpenSessionInView的熏陶下长大。。。-_-b

Robbin有什么好的办法能够在不使用OpenSessionInView的情况下比较好的处理页面吗?


在dao中对要render的集合强制初始化。
文章时间: 2005-12-14 10:51:52    标题: 引用回复 将这个帖子加入我的Blog

hongliang 写道:
是不是像这样?

foo.getBars()


Hibernate.initialize(foo.getBars);
posted on 2006-02-10 09:52 TrampEagle 阅读(1474) 评论(0)  编辑  收藏 所属分类: hibernateSpring

只有注册用户登录后才能发表评论。


网站导航: