jjzjj

xml - 如何提高基于 MQ 的批处理应用程序的性能?

coder 2024-06-26 原文

我有一个应用程序,其中消息以每小时 70K XML 的速度不断发送。我们使用这些 XML 消息并将其存储到一个中间队列中。创建中间队列是因为我们需要满足 24 小时内消耗所有消息的 SLA。我们能够在 24 小时内使用 XMLS 并将其加载到内部队列中。将其加载到内部队列后,我们处理 XMLS(解析、应用很少的转换、执行很少的验证)并将数据存储到高度规范化的数据模型中。我知道数据模型会对性能产生巨大影响,不幸的是,我们无法控制数据模型。目前,我们需要 3.5 分钟来处理 2K 消息,这是 Not Acceptable 。我们希望将 2K 消息的时间缩短到 1 分钟。这是我们到目前为止所做的:

1) 适用的索引。
2)使用 XMLBeans 解析 XML(每个 XML 的大小不是很大)
3) 删除了所有不必要的验证、转换等。

该应用程序运行于:
操作系统:RHEL 5.4 64位
平台:JDK 1.6.0_17,64 位
数据库:Oracle 11g R2 64 位(2 节点集群)
外部 MQ:IBM 队列
内部临时存储MQ:JBoss MQ
应用服务器:Jboss 5.1.0.GA(EAP版)

我们使用和处理 XML 消息的顺序非常重要,因此我们无法进行并行处理。

我们还能做些什么来提高性能?

最佳答案

消息传递调整之外的一些建议,因为这似乎不是您的 [主要] 瓶颈:

  • 您提到您将数据存储到高度规范化的数据库中。这总是意味着一个或多个引用数据或 PK 查找,这会创建多个额外的数据库行程以获取此数据。为避免或减少这种情况,请使用所有引用数据创建本地缓存并随时更新缓存。在内存中查找将比访问数据库快得多。
  • 如果您觉得 RAM 不足以缓存所有解码和引用数据,请尝试基于磁盘的缓存(例如,EHCache 将执行 RAM、磁盘或溢出)或轻量级本地数据库(如 HyperSonic 或 H2),它们仍可为您提供更好的查找比去甲骨文旅行还要多倍(除非你在同一台主机上,即使那样......)
  • 最终,如果每条消息都需要多次往返 DB,您可能会受益于将消息处理迁移到 DB 本身,在那里您可以在 PL/SQL 或 Java 中实现该过程。
  • 如果您为处理的一条消息写入数据库涉及多个插入/更新,请确保使用准备好的语句批处理。这将在一次调用中向数据库发送多个插入/更新。
  • 说到准备好的语句,请确保您的 JBoss DataSource configuration对于 Oracle 有 准备语句缓存大小设置为足够高的数字以处理在处理期间创建的所有准备好的语句(而不是默认值为零或无缓存)。
  • 您正在使用的 XML 解析器可能会增加不必要的开销,甚至(或特别是)对于小消息也是如此。如果您正在使用 JAXB,请确保您没有多次(或不必要地多次)重新创建解码器。或者,尝试使用 Pull/Streaming parser .如果您使用的是 DOM 解析器,则所需的额外内存可能会导致大量垃圾回收。
  • 愚蠢的事情,但值得一提的是,如果您为每条消息执行大量日志记录,那将花费您的时间,因此请将其关闭。
  • 使用 JBoss MQ 作为中间缓冲区是优雅的,但它可能不是存储消息以进行延迟处理的最快方式,因为持久性对于各种 JMS 消息类型更加复杂和通用。在这一点上,如果 JBoss MQ 无论如何都持久化到 Oracle,那么自定义持久化过程似乎不太可能更快。如果 JBoss MQ 存储到 HyperSonic(就像默认情况下那样),您仍然可以使用一些自定义代码来胜过 JMS 消息的存储。这也意味着您将需要一种新机制来将消息从 DB 中拉出以进行处理,但与 JMS 存储一样,自定义流程的性能可能优于 JBoss MQ 实现的更通用的过程。
  • 将中间消息存储到 DB 还可以提供更大的查询灵活性,以确定哪些消息不必串行处理。 (例如,可能不需要按顺序处理来自不同客户端的消息)。当然,您也可以使用 JBoss MQ 通过在中间消息中放置适当的 header 来做到这一点。这将允许您通过在多个不同的消息监听器/处理器中使用不同的选择器来并行化。

  • 关于消息传递的一项快速项目.....

    您没有提到是否将消息驱动 bean 与 WebSphere MQ 一起使用,但如果是,在 Inbound Configuration 中有一个设置。叫 pollingInterval 从文档中引用,这意味着:

    如果 session 中的每个消息监听器的队列中都没有合适的消息,则这是每个消息监听器再次尝试从其队列中获取消息之前经过的最大间隔(以毫秒为单位)。如果经常发生 session 中的任何消息监听器都没有可用的合适消息,请考虑增加此属性的值。仅当 TRANSPORT 具有值 BIND 或 CLIENT 时,此属性才相关。

    默认轮询时间 是 5000 毫秒。您当前的消息处理时间是

    (3.5 * 60 * 1000 / 2000)



    = 每条消息 105 毫秒。

    如果您在这里和那里引入 5000 毫秒的暂停,这将严重降低您的吞吐量,因此您可能需要通过测量消息排队时间与您在JBoss 消息监听器。入队时间可以从这些消息头中确定:
  • JMS_IBM_PutDate
  • JMS_IBM_PutTime

  • 总而言之,最好的办法是弄清楚如何并行化。

    祝你好运。

    //尼古拉斯

    关于xml - 如何提高基于 MQ 的批处理应用程序的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6228128/

    有关xml - 如何提高基于 MQ 的批处理应用程序的性能?的更多相关文章

    1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

      我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

    2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

      总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

    3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

      关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

    4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

      给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

    5. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    6. ruby - 将差异补丁应用于字符串/文件 - 2

      对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

    7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

      我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

    8. ruby - 如何指定 Rack 处理程序 - 2

      Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

    9. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

      在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

    10. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

      我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

    随机推荐