Java OpenCSV+;JMS/MDB行为&x2B;性能问题
我有一个在Glassfish 4.1下运行的web应用程序,它包含两个需要JMS/MDB的特性。 尤其是在使用JMS/MDB生成报告方面,我遇到了一些问题,即从表中获取数据并将其转储到文件中 这就是发生的情况,我有一个JMS/MDB消息,它在Oracle数据库中执行两个任务,在表中得到最终结果后,我希望从该表中获得一个csv报告(通常是30M+记录) 因此,在JMS/MDB中,生成报告时会发生以下情况:Java OpenCSV+;JMS/MDB行为&x2B;性能问题,java,glassfish,jms,message-driven-bean,opencsv,Java,Glassfish,Jms,Message Driven Bean,Opencsv,我有一个在Glassfish 4.1下运行的web应用程序,它包含两个需要JMS/MDB的特性。 尤其是在使用JMS/MDB生成报告方面,我遇到了一些问题,即从表中获取数据并将其转储到文件中 这就是发生的情况,我有一个JMS/MDB消息,它在Oracle数据库中执行两个任务,在表中得到最终结果后,我希望从该表中获得一个csv报告(通常是30M+记录) 因此,在JMS/MDB中,生成报告时会发生以下情况: public boolean handleReportContent() { Co
public boolean handleReportContent() {
Connection conn = null;
try {
System.out.println("Handling report content... " + new Date());
conn = DriverManager.getConnection(data.getUrl(), data.getUsername(), data.getPassword());
int reportLine = 1;
String sql = "SELECT FIELD_NAME, VALUE_A, VALUE_B, DIFFERENCE FROM " + data.getDbTableName() + " WHERE SET_PK IN ( SELECT DISTINCT SET_PK FROM " + data.getDbTableName() + " WHERE IS_VALID=? )";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setBoolean(1, false);
ResultSet rs = ps.executeQuery();
List<ReportLine> lst = new ArrayList<>();
int columns = data.getLstFormats().size();
int size = 0;
int linesDone = 0;
while (rs.next()) {
ReportLine rl = new ReportLine(reportLine, rs.getString("FIELD_NAME"), rs.getString("VALUE_A"), rs.getString("VALUE_B"), rs.getString("DIFFERENCE"));
lst.add(rl);
linesDone = columns * (reportLine - 1);
size++;
if ((size - linesDone) == columns) {
reportLine++;
if (lst.size() > 4000) {
appendReportContentNew(lst);
lst.clear();
}
}
}
if (lst.size() > 0) {
appendReportContentNew(lst);
lst.clear();
}
ps.close();
conn.close();
return true;
} catch (Exception e) {
System.out.println("exception handling report content new: " + e.toString());
return false;
}
因此,我正在从结果集中收集所有数据,并转储到CSVWriter。此操作对于相同的20分钟,只写入了7k行
但是同样的方法,如果我在JMS/MDB之外使用它,它有一个难以置信的不同,就在开始的4分钟内,它在文件中写了3百万行。
在同样的20分钟内,它生成了一个500Mb+的文件
显然,如果我想提高性能,使用OpenCSV是目前为止最好的选择,我的问题是为什么它在JMS/MDB中的性能不一样?
如果不可能,是否有任何可能的解决方案以任何其他方式改进同一任务
我感谢您在这方面提供的反馈和帮助,我正在努力理解JMS/MDB内外的行为/性能不同的原因
**
编辑:
**
因此,如果在
generator中执行相同的方法,handleReportContent()
,deployGenerator()。如果我等待该方法中的所有内容,并使这个bean中的文件JobProcessorBean
更快。我只是想弄清楚这个行为为什么会这样执行。在bean上添加@TransactionAttribute(不受支持)
注释可能会解决这个问题(正如您的评论所指出的那样)
为什么会这样?因为如果不在消息驱动bean上放置任何事务性注释,默认值将变成@TransactionAttribute(必需)
(因此bean所做的一切都由事务管理器监督)。显然,这会减慢速度。消息驱动bean上的@TransactionAttribute
注释是什么?如何在MDB之外调用您的HandlerReportContentV2
方法?@MaDa我有一个类JobProcessorBean
,它有以下注释:@MessageDriven(activationConfig={@ActivationConfigProperty(propertyName=“destinationType”,propertyValue=“javax.jms.Queue”),@ActivationConfigProperty(propertyName=“destinationLookup”,propertyValue=“MessageQueue”)}
此bean注入另一个bean,我在其中调用deploy()
方法
在部署的bean中使用,我有这些结果。如果复制相同的方法并在不同的bean中运行,我会得到不同的结果。我将添加这部分代码。尝试添加@TransactionAttribute(不受支持)
,查看这是否对性能有影响。另外,请查看将文件直接保存到web应用程序文件夹中的其他问题。@MaDa会的,我会告诉您是否有任何不同。@MaDa解决了这个问题,它在MDB中执行相同的操作。可以用您以前的示例回答这个问题。@t、 所以我可以接受。谢谢你的时间和帮助。:)
public void appendReportContentNew(List<ReportLine> lst) {
File f = new File(data.getJobFilenamePath());
try {
if (!f.exists()) {
f.createNewFile();
}
FileWriter fw = new FileWriter(data.getJobFilenamePath(), true);
BufferedWriter bw = new BufferedWriter(fw);
for (ReportLine rl : lst) {
String rID = "R" + rl.getLine();
String fieldName = rl.getFieldName();
String rline = rID + "," + fieldName + "," + rl.getValue1() + "," + rl.getValue2() + "," + rl.getDifference();
bw.append(rline);
bw.append("\n");
}
bw.close();
} catch (IOException e) {
System.out.println("exception appending report content: " + e.toString());
}
public boolean handleReportContentv2() {
Connection conn = null;
try {
FileWriter fw = new FileWriter(data.getJobFilenamePath(), true);
System.out.println("Handling report content v2... " + new Date());
conn = DriverManager.getConnection(data.getUrl(), data.getUsername(), data.getPassword());
String sql = "SELECT NLINE, FIELD_NAME, VALUE_A, VALUE_B, DIFFERENCE FROM " + data.getDbTableName() + " WHERE SET_PK IN ( SELECT DISTINCT SET_PK FROM " + data.getDbTableName() + " WHERE IS_VALID=? )";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setBoolean(1, false);
ps.setFetchSize(500);
ResultSet rs = ps.executeQuery();
BufferedWriter out = new BufferedWriter(fw);
CSVWriter writer = new CSVWriter(out, ',', CSVWriter.NO_QUOTE_CHARACTER);
writer.writeAll(rs, false);
fw.close();
writer.close();
rs.close();
ps.close();
conn.close();
return true;
} catch (Exception e) {
System.out.println("exception handling report content v2: " + e.toString());
return false;
}
}
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "MessageQueue")})
public class JobProcessorBean implements MessageListener {
private static final int TYPE_A_ID = 0;
private static final int TYPE_B_ID = 1;
@Inject
JobDao jobsDao;
@Inject
private AsyncReport generator;
public JobProcessorBean() {
}
@Override
public void onMessage(Message message) {
int jobId = -1;
ObjectMessage msg = (ObjectMessage) message;
try {
boolean valid = true;
JobWrapper jobw = (JobWrapper) msg.getObject();
jobId = jobw.getJob().getJobId().intValue();
switch (jobw.getJob().getJobTypeId().getJobTypeId().intValue()) {
case TYPE_A_ID:
jobsDao.updateJobStatus(jobId, 0);
valid = processTask1(jobw);
if(valid) {
jobsDao.updateJobFileName(jobId, generator.getData().getJobFilename());
System.out.println(":: :: JOBW FileName :: "+generator.getData().getJobFilename());
jobsDao.updateJobStatus(jobId, 0);
}
else {
System.out.println("error...");
jobsDao.updateJobStatus(jobId, 1);
}
**boolean validfile = handleReportContentv2();**
if(!validfile) {
System.out.println("error file...");
jobsDao.updateJobStatus(jobId, 1);
}
break;
case TYPE_B_ID:
(...)
}
if(valid) {
jobsDao.updateJobStatus(jobw.getJob().getJobId().intValue(), 2); //updated to complete
}
System.out.println("***********---------Finished JOB " + jobId + "-----------****************");
System.out.println();
jobw = null;
} catch (JMSException ex) {
Logger.getLogger(JobProcessorBean.class.getName()).log(Level.SEVERE, null, ex);
jobsDao.updateJobStatus(jobId, 1);
} catch (Exception ex) {
Logger.getLogger(JobProcessorBean.class.getName()).log(Level.SEVERE, null, ex);
jobsDao.updateJobStatus(jobId, 1);
} finally {
msg = null;
}
}
private boolean processTask1(JobWrapper jobw) throws Exception {
boolean valid = true;
jobsDao.updateJobStatus(jobw.getJob().getJobId().intValue(), 0);
generator.setData(jobw.getData());
valid = generator.deployGenerator();
if(!valid) return false;
jobsDao.updateJobParameters(jobw.getJob().getJobId().intValue(),new ReportContent());
Logger.getLogger(JobProcessorBean.class.getName()).log(Level.INFO, null, "Job Finished");
return true;
}