- 浏览: 175382 次
- 性别:
- 来自: 苏州
文章分类
- 全部博客 (87)
- Android (7)
- J2EE (34)
- JavaScript (6)
- CSS (1)
- Scala (0)
- WEB (5)
- Ruby (1)
- J2EE Netbeans JDK (1)
- Maven (2)
- AndroidMenuTest (0)
- ExtJS (1)
- MyBatis (4)
- iBatis (3)
- Quartz (1)
- JavaABC (3)
- HTML (1)
- JQuery (2)
- mysql (3)
- Linux (2)
- windows (1)
- ant (2)
- jboss (1)
- eclipse (1)
- junit (1)
- nginx (1)
- Google (0)
- git (2)
- python (1)
- kafka (1)
- sqlserver (1)
- jdk8+ (1)
参考 : How to avoid huge transactions with CMP Entity Beans on JBoss
By default, CMP Entity Beans on JBoss are set to require a transaction. Also by default, any time you touch any session or entity bean, your request thread takes out a lock on that entire object, even if you are only reading it and not updating it. Lastly, also by default, JBoss will make sure that for any given entity, there is only one instance of that entity in memory at a time.
All of these defaults have serious implications. For one, it implies that anything other than a toy application will likely become a de-facto, single-threaded application. Imagine, for example, that you have an earthquake tracking application. Your application might have an Entity Bean called Earthquake. After getting under way with the application, you realize there are different kinds of earthquake: tectonic, volcanic, and man-made. These don’t merit having a full-on Earthquake subclass of their own, but maybe you want to model the types as a new Entity called EarthquakeType so that the application can be data-driven and new types can be added later without changing code. The vast majority (~90%) of earthquakes are tectonic, so most of what you ever display to a user will be “tectonic”.
So, you might have a web page that displays the last 40 earthquakes in descending chronological order in a table and also a count of how many different types. This could lead to innocent code like, say:
foreach (Earthquake earthquake : earthquakes){
typeSum[earthquake.getType().getId()]++;
}
The moment you call earthquake.getType() for the first earthquake in the list, you will lock the “tectonic” instance of the EarthquakeType Entity bean. This means that every other thread executing in the same JVM (if configured the default JBoss way) will most likely block (who doesn’t need to know what the earthquake type is, after all?) until this thread is done displaying its page. Even worse, if this thread is holding a lock that some other thread needs, and that other thread is holding a lock that this thread needs, then you have a deadlock. All of this in spite of the fact that actually updating an EarthquakeType is extremely rare because they are read-mostly.
A telltale sign that you are having this problem is seeing stack traces like this one:
org.jboss.util.deadlock.ApplicationDeadlockException: Application deadlock detected, resource=org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock@290df5c3, bean=
…snip…
at org.jboss.util.deadlock.DeadlockDetector.deadlockDetection(DeadlockDetector.java:69)
at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.waitForTx(QueuedPessimisticEJBLock.java:292)
at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.doSchedule(QueuedPessimisticEJBLock.java:230)
…snip.
At first, it’s tempting to fume at JBoss for having such conservative default settings. I know I did this morning as I was learning more about the details. But the fact is that they really have no choice. The application container has no idea that EarthquakeType is read-mostly. It doesn’t know if you will read it at the beginning of the request and then modify it 300 milliseconds later at the end of the request. So, it is forced to loop absolutely everything you touch into a giant transaction unless you tell it otherwise.
Now, the “telling it otherwise” is where things start to get tricky. Here, I really do think that JBoss hasn’t done us any favors. It’s a multi-step process to making sure you maximize your throughput and minimize deadlocks. If you do some steps but don’t do others, then nothing will change and you won’t know why.
So, here are the steps…
1) Mark all your read-only methods on Entity beans as such. This is where most people start, probably because it’s the kind of advice that pops to the top of Google searches. However, taking this step is a necessary but not sufficient condition for breaking down these huge transactions and their locks. You still have to follow step 2 and step 3.
To mark a method as read-only, you need to add the “<read-only>true</read-only>” element to its “entity” entry in jboss.xml:
<entity>
<ejb-name>Earthquake</ejb-name>
...
<method-attributes>
<method>
<method-name>getType</method-name>
<read-only>true</read-only>
</method>
...
If you are using XDoclet, then you can accomplish the same thing by adding an annotation:
/*
* @jboss.method-attributes read-only="true"
*/
2) Configure the container to use a lock manager that gives a damn about read-only methods.
Even though you’ve now marked your read-only methods as read-only, the default lock manager (QueuedPessimisticEJBLock) doesn’t actually do anything useful with this information. This fact is buried about half of the way down this lengthy page: http://docs.jboss.org/jbossas/jboss4guide/r2/html/ch5.chapter.html.
To take full advantage of your shiny, new read-only methods, you have to change the configuration for your entity beans to instead use the SimpleReadWriteEJBLock lock manager. This is a two step process. First, create a new container configuration that extends the default one in jboss.xml:
<container-configurations>
<container-configuration extends=“Standard CMP 2.x EntityBean”>
<container-name>DeadlockAvoidingConfiguration</container-name>
<locking-policy>org.jboss.ejb.plugins.lock.SimpleReadWriteEJBLock</locking-policy>
</container-configuration>
</container-configurations>
If you are using XDoclet, you can put the same entry in a file called “jboss-container.xml” and XDoclet will merge them together.
Next, you have to explicitly tell every entity bean to use this container configuration instead of the default one. You do this by adding an entry to the entity entries in jboss.xml:
<entity>
<ejb-name>Earthquake</ejb-name>
…
<configuration-name>DeadlockAvoidingConfiguration</configuration-name>
…
Or, again, if you are using XDoclet then add an annotation to the top of your class:
@jboss.container-configuration name = “DeadlockAvoidingConfiguration”
3) Deal with the read-only fallout
This doesn’t all come for free. Specifically, a common (though not OO-friendly) practice when dealing with one-to-many relationships between entity EJBs is to have a getter that returns a Collection and have client code simply add and remove things from that collection. But, once you’ve marked that getter as read only, then if you try to manipulate the returned Collection it will throw an exception. To fix this, you have to create “adder” and “remover” methods for that relationship.
For example, let’s say we wanted to keep track of witness reports of an Earthquake. You might add a WitnessReport class to the system and a relationship called Earthquake.getWitnessReports() that returns a Collection of WitnessReports. When a new witness sends in a report, then you might have code that does this:
anEarthquake.getWitnessReports().add(aNewWitnessReport);
That code works fine if “getWitnessReports()” is left to its default settings, but blows up with an exception saying your CMR collection is read only if you’ve marked “getWitnessReports()” as read only. What you need to do is add a new method to Earthquake, like so:
public void addWitnessReport(WitnessReport record){
Collection existingReports = this.getWitnessReports();
Collection newReports = new ArrayList(existingReports.size() + 1);
newReports.addAll(existingReports);
newReports.add(record);
this.setWitnessReports(newReports);
}
When this method is invoked, the lock manager will take out a lock and remember to write the changes back to the data store. It’s not pretty, but it does get the job done and saves a great deal of performance elsewhere in the application.
So that’s it. Now you have a faster application that is less deadlock prone. Enjoy the time you save by going out and having a beer right now.
p.s. though I haven’t tested this, apparently all of the above doesn’t work in EJB 3.0 on JBoss
2014-05-23 11:06:32,475 ERROR [org.jboss.ejb.plugins.LogInterceptor] TransactionRolledbackException in method: public abstract com.spokesoft.component.sla.SlaDetails com.spokesoft.component.sla.ejb.Sla.getSlaDetails() throws java.rmi.RemoteException, causedBy: org.jboss.util.deadlock.ApplicationDeadlockException: Application deadlock detected, resource=org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock@a74da8, bean=SlaBean, id=[org:AWSUK],[id:102], refs=2, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=BEMABC0RFMA3/505839, BranchQual=, localId=505839], synched=Thread[http-0.0.0.0-80-29,5,jboss], timeout=5000, queue=[], holder=TransactionImpl:XidImpl[FormatId=257, GlobalId=BEMABC0RFMA3/505826, BranchQual=, localId=505826], waitingResource=org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock@1db76e2, bean=CalendarBean, id=[org:AWSUK],[id:102], refs=2, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=BEMABC0RFMA3/505826, BranchQual=, localId=505826], synched=null, timeout=5000, queue=[TXLOCK waitingTx=TransactionImpl:XidImpl[FormatId=257, GlobalId=BEMABC0RFMA3/505839, BranchQual=, localId=505839] id=0 thread=Thread[http-0.0.0.0-80-21,5,jboss] queued=true], waitingResourceHolder=TransactionImpl:XidImpl[FormatId=257, GlobalId=BEMABC0RFMA3/505826, BranchQual=, localId=505826] at org.jboss.util.deadlock.DeadlockDetector.deadlockDetection(DeadlockDetector.java:69) at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.waitForTx(QueuedPessimisticEJBLock.java:292) at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.doSchedule(QueuedPessimisticEJBLock.java:230) at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.schedule(QueuedPessimisticEJBLock.java:194) ...
By default, CMP Entity Beans on JBoss are set to require a transaction. Also by default, any time you touch any session or entity bean, your request thread takes out a lock on that entire object, even if you are only reading it and not updating it. Lastly, also by default, JBoss will make sure that for any given entity, there is only one instance of that entity in memory at a time.
All of these defaults have serious implications. For one, it implies that anything other than a toy application will likely become a de-facto, single-threaded application. Imagine, for example, that you have an earthquake tracking application. Your application might have an Entity Bean called Earthquake. After getting under way with the application, you realize there are different kinds of earthquake: tectonic, volcanic, and man-made. These don’t merit having a full-on Earthquake subclass of their own, but maybe you want to model the types as a new Entity called EarthquakeType so that the application can be data-driven and new types can be added later without changing code. The vast majority (~90%) of earthquakes are tectonic, so most of what you ever display to a user will be “tectonic”.
So, you might have a web page that displays the last 40 earthquakes in descending chronological order in a table and also a count of how many different types. This could lead to innocent code like, say:
foreach (Earthquake earthquake : earthquakes){
typeSum[earthquake.getType().getId()]++;
}
The moment you call earthquake.getType() for the first earthquake in the list, you will lock the “tectonic” instance of the EarthquakeType Entity bean. This means that every other thread executing in the same JVM (if configured the default JBoss way) will most likely block (who doesn’t need to know what the earthquake type is, after all?) until this thread is done displaying its page. Even worse, if this thread is holding a lock that some other thread needs, and that other thread is holding a lock that this thread needs, then you have a deadlock. All of this in spite of the fact that actually updating an EarthquakeType is extremely rare because they are read-mostly.
A telltale sign that you are having this problem is seeing stack traces like this one:
org.jboss.util.deadlock.ApplicationDeadlockException: Application deadlock detected, resource=org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock@290df5c3, bean=
…snip…
at org.jboss.util.deadlock.DeadlockDetector.deadlockDetection(DeadlockDetector.java:69)
at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.waitForTx(QueuedPessimisticEJBLock.java:292)
at org.jboss.ejb.plugins.lock.QueuedPessimisticEJBLock.doSchedule(QueuedPessimisticEJBLock.java:230)
…snip.
At first, it’s tempting to fume at JBoss for having such conservative default settings. I know I did this morning as I was learning more about the details. But the fact is that they really have no choice. The application container has no idea that EarthquakeType is read-mostly. It doesn’t know if you will read it at the beginning of the request and then modify it 300 milliseconds later at the end of the request. So, it is forced to loop absolutely everything you touch into a giant transaction unless you tell it otherwise.
Now, the “telling it otherwise” is where things start to get tricky. Here, I really do think that JBoss hasn’t done us any favors. It’s a multi-step process to making sure you maximize your throughput and minimize deadlocks. If you do some steps but don’t do others, then nothing will change and you won’t know why.
So, here are the steps…
1) Mark all your read-only methods on Entity beans as such. This is where most people start, probably because it’s the kind of advice that pops to the top of Google searches. However, taking this step is a necessary but not sufficient condition for breaking down these huge transactions and their locks. You still have to follow step 2 and step 3.
To mark a method as read-only, you need to add the “<read-only>true</read-only>” element to its “entity” entry in jboss.xml:
<entity>
<ejb-name>Earthquake</ejb-name>
...
<method-attributes>
<method>
<method-name>getType</method-name>
<read-only>true</read-only>
</method>
...
If you are using XDoclet, then you can accomplish the same thing by adding an annotation:
/*
* @jboss.method-attributes read-only="true"
*/
2) Configure the container to use a lock manager that gives a damn about read-only methods.
Even though you’ve now marked your read-only methods as read-only, the default lock manager (QueuedPessimisticEJBLock) doesn’t actually do anything useful with this information. This fact is buried about half of the way down this lengthy page: http://docs.jboss.org/jbossas/jboss4guide/r2/html/ch5.chapter.html.
To take full advantage of your shiny, new read-only methods, you have to change the configuration for your entity beans to instead use the SimpleReadWriteEJBLock lock manager. This is a two step process. First, create a new container configuration that extends the default one in jboss.xml:
<container-configurations>
<container-configuration extends=“Standard CMP 2.x EntityBean”>
<container-name>DeadlockAvoidingConfiguration</container-name>
<locking-policy>org.jboss.ejb.plugins.lock.SimpleReadWriteEJBLock</locking-policy>
</container-configuration>
</container-configurations>
If you are using XDoclet, you can put the same entry in a file called “jboss-container.xml” and XDoclet will merge them together.
Next, you have to explicitly tell every entity bean to use this container configuration instead of the default one. You do this by adding an entry to the entity entries in jboss.xml:
<entity>
<ejb-name>Earthquake</ejb-name>
…
<configuration-name>DeadlockAvoidingConfiguration</configuration-name>
…
Or, again, if you are using XDoclet then add an annotation to the top of your class:
@jboss.container-configuration name = “DeadlockAvoidingConfiguration”
3) Deal with the read-only fallout
This doesn’t all come for free. Specifically, a common (though not OO-friendly) practice when dealing with one-to-many relationships between entity EJBs is to have a getter that returns a Collection and have client code simply add and remove things from that collection. But, once you’ve marked that getter as read only, then if you try to manipulate the returned Collection it will throw an exception. To fix this, you have to create “adder” and “remover” methods for that relationship.
For example, let’s say we wanted to keep track of witness reports of an Earthquake. You might add a WitnessReport class to the system and a relationship called Earthquake.getWitnessReports() that returns a Collection of WitnessReports. When a new witness sends in a report, then you might have code that does this:
anEarthquake.getWitnessReports().add(aNewWitnessReport);
That code works fine if “getWitnessReports()” is left to its default settings, but blows up with an exception saying your CMR collection is read only if you’ve marked “getWitnessReports()” as read only. What you need to do is add a new method to Earthquake, like so:
public void addWitnessReport(WitnessReport record){
Collection existingReports = this.getWitnessReports();
Collection newReports = new ArrayList(existingReports.size() + 1);
newReports.addAll(existingReports);
newReports.add(record);
this.setWitnessReports(newReports);
}
When this method is invoked, the lock manager will take out a lock and remember to write the changes back to the data store. It’s not pretty, but it does get the job done and saves a great deal of performance elsewhere in the application.
So that’s it. Now you have a faster application that is less deadlock prone. Enjoy the time you save by going out and having a beer right now.
p.s. though I haven’t tested this, apparently all of the above doesn’t work in EJB 3.0 on JBoss
发表评论
-
日志过滤小工具
2020-01-06 20:15 4521.从全量日志中截断部 ... -
GC参考手册
2017-11-09 14:12 549英文版原文:GC Tuning: In Practice 垃圾 ... -
IDENTITY_INSERT 设置为 OFF 时无法指定插入自增ID
2017-02-15 16:10 660IDENTITY_INSERT 设置为 OFF 时,无法指定I ... -
运行时Exception:Wrong return type in function
2015-11-17 21:31 1524D:\Soft\jdk1.7.0_79\bin\java ... -
Java中的常量:如何避免反模式
2015-10-20 20:41 449参考http://www.importnew.com/1670 ... -
java Socket通信小栗子
2015-09-14 09:25 614server端: package com.test.soc ... -
MyBatis 自动生成xml文件
2015-03-12 11:22 3798package com.test.mybatis; ... -
Java mail test
2015-02-12 11:03 1304mail局域网Exchange服务器测试代码,仅限发送到dom ... -
Java Concurrency / Multithreading Tutorial
2014-10-28 09:35 703Java Concurrency / Multithreadi ... -
Comparison method violates its general contract!
2014-10-22 17:24 959jdk1.6升级到1.7后Comparator有null的参数 ... -
JDK1.7 不兼容compare方法
2014-10-21 16:20 787java.lang.IllegalArgumentExcept ... -
Unknown Source的出现及解决
2014-06-18 10:03 929http://www.2cto.com/kf/201103/8 ... -
Java Date相关处理
2014-02-26 14:35 6061.获取UTC时间: Calendar c ... -
Error listenerStart
2013-12-11 19:25 728INFO: Deploying web applicati ... -
Error configuring application listener of class org.springframework.web.context.
2013-12-07 18:54 38181如果Eclipse的BuildPath里面不缺jar包并且在 ... -
iReport字体报错“JRFontNotFoundException”
2013-10-11 11:08 12796net.sf.jasperreports.engine.uti ... -
Eclipse里Jboss的配置
2013-07-15 17:41 9591.\WorkSpace\.metadata\.plugins ... -
Ant安装使用入门
2013-07-04 14:03 568下载Ant之后,增加环境变量1.ANT_HOME=xx/xx/ ... -
javaSystem获取系统信息
2013-03-27 16:30 807public static void main(Strin ... -
设计模式学习笔记
2013-03-22 18:01 839简单工厂,策略模式,单一职责,开放封闭,依赖倒转 装饰模式,代 ...
相关推荐
基于springboot大学生就业信息管理系统源码数据库文档.zip
基于java的驾校收支管理可视化平台的开题报告
时间序列 原木 间隔5秒钟 20241120
毕业设计&课设_基于 Vue 的电影在线预订与管理系统:后台 Java(SSM)代码,为毕业设计项目.zip
基于springboot课件通中小学教学课件共享平台源码数据库文档.zip
基于java的网上购物商城的开题报告
Delphi人脸检测与识别Demo1fdef-main.zip
基于java的咖啡在线销售系统的开题报告
基于java的自助医疗服务系统的开题报告.docx
内容概要:本文档全面介绍了Visual Basic(VB)编程语言的基础知识和高级应用。首先概述了VB的基本特性和开发环境,随后详细讲述了VB的数据类型、变量、运算符、控制结构、数组、过程与函数、变量作用域等内容。接着介绍了窗体设计、控件使用、菜单与工具栏的设计,文件操作、数据库访问等关键知识点。最后讨论了VB的学习方法、发展历史及其在桌面应用、Web应用、数据库应用、游戏开发和自动化脚本编写等领域的广泛应用前景。 适合人群:初学者和中级程序员,尤其是希望快速掌握Windows桌面应用开发的人群。 使用场景及目标:①掌握VB的基础语法和开发环境;②学会使用VB创建复杂的用户界面和功能完整的应用程序;③理解数据库操作、文件管理和网络编程等高级主题。 其他说明:Visual Basic是一种简单易学且功能强大的编程语言,尤其适合用于开发Windows桌面应用。文中不仅覆盖了基础知识,还包括了大量的实用案例和技术细节,帮助读者快速提升编程技能。
基于java的疫情期间高校防控系统开题报告.docx
基于springboot+vue社区老年人帮扶系统源码数据库文档.zip
基于java的超市商品管理系统的开题报告.docx
基于SpringBoot房屋买卖平台源码数据库文档.zip
xdu限通院23微处理器系统与应用大作业(两只老虎),适应于汇编语言keil软件,
<项目介绍> - 新闻类网站系统,基于SSM(Spring、Spring MVC、MyBatis)+MySQL开发,高分成品毕业设计,附带往届论文 - 不懂运行,下载完可以私聊问,可远程教学 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 --------
基于java的学生网上请假系统的开题报告.docx
社会经济繁荣发展的今天,电子商务得到了飞速发展,网上交易越来越彰显出其独特的优越性,在人们的日常生活中,出现了各种类型的交易网站。其中一个就是车辆易主交易网站,它是一个服务于用户买卖二手车辆的交易网站,为用户提供了平等互利、方便快捷的网上交易平台,通过这一类型的网站,用户可自由出售和购买车辆。 本课题主要根据车辆本身的特性,充分发挥互联网的特点与优势,构建一个以二手车辆为商品、基于互联网平台的车辆易主业务交易管理系统,并根据车辆易主业务交易管理系统的应用需求,进行需求分析,进而对网站系统作规划设计。采用IDEA为运行平台,以SSH为框架,运用HTML语言、JSP技术、MySql数据库、JSP与后台数据库链接等关键技术建设二手车网上交易系统,构建车辆易主交易系统的会员注册与登录,网站首页展示、用户发布商品车辆,用户求购商品车辆,分页浏览、购物系统、用户后台管理、管理员用户后台管理等功能,并使这些功能得以实现并更好为用户服务。网站整体构建完成且测试成功后,用户可以进入网站进行注册、登录,登录后,用户可以在网站上发布自己的闲置车辆或者寻找想要购买的车辆,还可以收藏车辆,管理发布和收藏的车辆,
SQLite3的向量扩展库,windows dll,版本0.1.5
基于C++实现(控制台)商品库存管理系统