【问题标题】:Huge performance issue using camel routes in karaf在卡拉夫使用骆驼路线存在巨大的性能问题
【发布时间】:2013-08-01 17:33:00
【问题描述】:

我对 karaf 有一个棘手的问题,并且尝试了一整天来解决它,我需要您的见解。问题来了:

我有骆驼路线(纯 java DSL),从 2 个来源获取数据,处理它们,然后将结果发送到 redis - 作为独立应用程序使用时(使用 Main 类和命令行“java -jar myjar.jar”),数据在不到 20 分钟内处理和保存 - 在同一台机器上将它们作为捆绑包(实际上是另一个功能的一部分)使用时,需要大约10个小时

编辑:我忘了补充:我使用骆驼 2.1.0 和 karaf 2.3.2

现在,我们正在将我们的 SI 重构为 karaf 功能,因此很遗憾,仅保留独立应用程序是不可能的。

我尝试使用 karaf java 内存选项,使用集群(我失败:d)使用 SEDA 和线程池,用 seda 替换所有直接路由,但没有成功。一个 dev:create-dump 显示了很多

thread #38 - Split" Id=166 BLOCKED on java.lang.Class@56d1396f owned by "Camel (camelRedisProvisioning)

这可能是 karaf 中的 split 和 parallelProcessing 的问题吗?独立应用确实显示出更多的 CPU 活动。

这是我的骆驼路线

//start with a quartz and a cron tab
from("quartz://provisioning/topOffersStart?cron=" + cronValue.replace(' ',  '+')).multicast()
        .parallelProcessing().to("direct:prodDAO", "direct:thesaurus");

//get from two sources and process
from("direct:prodDAO").bean(ProductsDAO.class)
.setHeader("_type", constant(TopExport.PRODUCT_TOP))
.setHeader("topOffer", constant("topOffer"))
.to("direct:topOffers");

from("direct:thesaurus")
.to(thesaurusUri).unmarshal(csv).bean(ThesaurusConverter.class, "convert")
.setHeader("_type", constant(TopExport.CATEGORY_TOP))
.setHeader("topOffer", constant("topOffer"))
.to("direct:topOffers");


//processing  
from("direct:topOffers").choice()
        .when(isCategory)
            .to("direct:topOffersThesaurus")
        .otherwise()
            .when(isProduct)
                .to("direct:topOffersProducts")
            .otherwise()
                .log(LoggingLevel.ERROR, "${header[_type]} is not valid !")
            .endChoice()
        .endChoice()
    .end();

from("direct:topOffersThesaurus")
//here is where I think the problem comes
        .split(body()).parallelProcessing().streaming()
        .bean(someprocessing)
        .to("direct:toRedis");

from("direct:topOffersProducts")
//here is where I think the problem comes
        .split(body()).parallelProcessing().streaming()
        .bean(someprocessing)
        .to("direct:toRedis");

//save into redis
from("direct:toRedis")
        .setHeader("CamelRedis.Key", simple("provisioning:${header[_topID]}"))
        .setHeader("CamelRedis.Command", constant("SETEX"))
        .setHeader("CamelRedis.Timeout", constant("90000"))//25h
        .setHeader("CamelRedis.Value", simple("${body}"))
.to("spring-redis://?redisTemplate=#provisioningRedisTemplateStringSerializer");

注意:发送到 direct:topOffers[products|thesaurus] 的正文是 pojo 的列表(同一类)

感谢任何可以提供帮助的人

编辑: 我想我把它缩小到 jaxb 的僵局。事实上,在我的路线中,我多次调用调用 Web 服务的 java 客户端。使用 karaf 时,线程被阻塞: java.lang.Thread.State: BLOCKED (on object monitor) at com.sun.xml.bind.v2.runtime.reflect.opt.AccessorInjector.prepare(AccessorInjector.java:78)

进一步向下堆栈跟踪,我们看到用于转换对象中的 xml 的解组方法,我们怀疑我怀疑的那 2 行

final JAXBContext context = JAXBContext.newInstance(clazz.getPackage().getName());
final Unmarshaller um = context.createUnmarshaller();

我删除了final,没有改进。也许与 karaf 使用的 jaxb 有关?我不使用捆绑软件安装任何 jaxb impl

【问题讨论】:

  • 您是否尝试过分析应用程序,看看它在做什么。我怀疑它增加了 OGSi 模块层的开销,并且通常有办法将其关闭。 (当然是为 iPOJO 准备的)
  • 嗨,“osgi 开销”是什么意思?根据这个stackoverflow.com/questions/6241757/…,几乎没有
  • 也许它是特定于 iPOJO 的。无论如何,我建议您对应用程序进行概要分析。
  • 使用 jconsole 监控 karaf 和独立应用程序,我看不出有什么不同,除了在 karaf 上运行时线程更多(与 split 对应的线程也更经常处于阻塞状态) 和更少的 CPU 使用率。但我不是分析专家,可能我错过了什么
  • 您需要进行 CPU 和内存分析,例如至少是 VisualVM。你是对的,jconsole 不应该向你展示太多。

标签: java apache-camel apache-karaf


【解决方案1】:

成功了! 如上所示,它确实与我的 web 服务客户端中 jaxb 上下文的死锁有关。 我做了什么 : - 通过删除 Marshaller/Unmarshaller 对象上的 final 关键字来重构该客户端的旧代码(我认为死锁来自那里,即使它在独立运行时是完全相同的代码) - 基于包实例化上下文,并且仅一次。 我必须承认 OSGI 的 Classloader 问题让我在办公桌上敲了几个小时,但感谢 Why can't JAXB find my jaxb.index when running inside Apache Felix?,我设法解决了这个问题

当然,我的线程现在正在休眠而不是阻塞,但现在我在不到 30 分钟的时间内处理了我的数据,所以这对我来说已经足够了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2019-06-15
    • 1970-01-01
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多