`

Java Web应用Web层异步化应该考虑的问题

    博客分类:
  • java
阅读更多

        之前做了一个项目,要用到web层的异步化技术,在实际实现中,遇到了很多问题,作为教训简单罗列下。

        1、app 容器/J2EE框架对异步的支持

        在tomcat5、jboss4的时候,每一个请求都用了一个app容器线程来执行,app线程必须一直处理完或者等待别的线程处理完,才能拿着请求的链接把结果写回到客户端。如果你想这个时候释放掉app容器线程,让它去做别的事情,你自己启动线程去处理完逻辑后把结果写回,是不可能的。

        但是等servlet 3规范出来后,这种方式就变得可行了。也就是你可以把容器线程和连接分离了,在app容器线程启动异步servlet后,把连接丢给别的线程(我们叫做业务工作线程)就好了,容器线程使命完成,可以处理下一个请求了。业务工作线程,可以等自己处理完后,通过连接把结果输出给前端,然后close掉连接就好了。这个要tomcat7及以后支持,可以参考个小例子

        当然,这个点上,只要选择合适的框架和容器版本,调调api就可以了。

        2、Filter中做的事情谁来处理?

        从1的描述看,容器线程早早的完成了使命,运行完了,但是业务逻辑还没有处理完。而通常filter是容器线程执行,如果在filter里边做了一些事情,如权限检查、日志、session处理等,有些是在业务逻辑执行前执行一次就行,业务逻辑执行后是不需要再处理什么东西的,这种是不受影响的。而有些资源控制如流控的、openSessionInView,则是在业务执行前处理一部分,业务执行完之后再处理一部分,这部分就需要调整,要么从Filter中迁出来,放到业务逻辑前后;要么Filter执行一部分,释放资源部分从filter迁出来,在业务执行线程中执行,等业务执行完了释放。

        不过这里需要注意,如果初始化资源部分在Filter里边,释放资源在业务线程中的方式下,如果初始化资源后、启动业务线程之前出现异常可能导致一些资源释放不了。

        3、如果使用了ThreadLocal呢?

        如果有人钟爱ThreadLocal,在Filter或者业务线程执行的代码的别的部分,丢了些数据到ThreadLocal中,在业务处理过程中要用到。这种情况下,就需要ThreadLocal数据的传递了,从容器线程传递到业务线程。

        不过这个不是所有数据都传递,如果你知道连BigDecimal里边都在用ThreadLocal的话、ReentrantReadLock都在用ThreadLocal的话,你大概就理解了为什么不是所有。所以要显式的传递了,即从容器线程get出来,再set到业务工作线程。

        4、如果还使用了动态代理?

        比如有人想监控部分servlet或如webwork的action的时候,看执行时间等信息,用动态代理统一管理,而这代理又是在业务逻辑线程启动前,遇到了如同filter一样的问题,参照filter的问题改造吧!

        5、如果你用了一些web框架,而这些框架并不支持异步方式?

        我能说恭喜你么,如果以上2、3、4条提到的代码你都可以控制,你还可以玩下去,而这个web框架你控制不了,里边无数的坑等你跳,他的一对fiter怎么处理,如果它基于filter还做了扩展?只能搞懂框架,把以上提到的2-4改一把了。。。。

        6、如果你的系统在线上跑的很稳定了,你是做改造,改造完之后还但是有很多问题需要长时间beta

        如果你把异步化改造的结果直接合进主干,大家一起跑,有问题处理,忽略此条。
        如果你需要长时间单机beta,又要考虑每次别人的新需求、日常上线,你要合并他们的代码进你分支,然后回归,然后上线beta。那合并代码和回归绝逼有可能搞死人,工作量之大,超出想象。这种情况下,你可以考虑同步异步一起支持。如果入口少,代码实现业务方,但是如果入口多呢?一个个改也不是人干的,自己通过asm通过maven插件打包后动态修改Servet/Action的继承体系,加个支持异步的基类?喔,是不是已经离原来要解决的问题越来越远了?

        

    

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics