Утечка памяти Apache Camel JMSComponent с Tibco JMS

Я наблюдаю очень странную утечку памяти в Camel (2.10.3) при использовании темы Tibco (с использованием библиотеки tibjms 4.4.3). Глядя на дампы кучи, кажется, что потребление памяти — это огромное количество вещей ConcurrentHashMap (сегмент, HashEntry [], блокировки и т. д.).

Я считаю, что происходит то, что обмены, поступающие из темы, никогда не помечаются Camel как «завершенные», и он хранит ссылки на них в памяти. Проблема исчезает, когда я перенаправляю их на '.stop()'.

Я создаю компонент JMS с помощью:

    TibjmsConnectionFactory connectionFactory = new TibjmsConnectionFactory();
    connectionFactory.setServerUrl(properties.getProperty(endpoints.getServerUrl()));
    connectionFactory.setUserName(properties.getProperty(endpoints.getUsername()));
    connectionFactory.setUserPassword(properties.getProperty(endpoints.getPassword()));

    JmsComponent emsComponent = JmsComponent.jmsComponent(connectionFactory);

    return emsComponent;

Зарегистрируйте его в контексте с помощью:

    camelContext.addComponent("positionems", emsComponent);

Затем создали невероятно простой тестовый маршрут, чтобы воспроизвести проблему:

    from("positionems:topic:UK.TOPIC4")
    .to("mock:out");

Что интересно, это заполнит кучу материалом ConcurrentHashMap до тех пор, пока процесс не упадет с ошибками пространства кучи. НО он работает нормально, если я изменю маршрут на:

    from("positionems:topic:UK.TOPIC4")
    .stop();

Согласно javadoc для остановки, он «останавливает продолжение маршрутизации текущего org.apache.camel.Exchange и помечает его как завершенный». - предположительно «помечает его как завершенное» - это то, чего мне не хватает, когда я отправляю его в макет (или даже когда я запускаю свою полную обычную программу, которая ведет себя так же, как отправка ее в макет).

Я пробовал множество вариантов конфигурации маршрута Jms, например:

    from("positionems:topic:UK.TOPIC4?disableReplyTo=true&deliveryPersistent=false")

И я попытался установить маршрут, чтобы никогда не ожидать ответа, но, возможно, я делаю это неправильно:

    from("positionems:topic:UK.TOPIC4")
    .inOnly()         // marked as deprecated?
    .to("mock:out");

Это проблема конкретно с Tibco? Учитывая количество людей, которые используют ActiveMQ без проблем, мне трудно поверить, что я нашел настоящую ошибку в Camel, надеюсь, я делаю что-то действительно просто неправильно!

ИЗМЕНИТЬ

Я протестировал последнюю версию Camel (2.12.1), и она кажется немного лучше (количество сегментов ConcurrentHashMap растет медленнее), но все же это определенно проблема.


person Matt    schedule 17.10.2013    source источник


Ответы (1)


Вы отправляете сообщение на конечную точку "mock:out", которая хранит копию сообщения в памяти. Итак, есть ваша утечка :). Что вы можете сделать, так это либо настроить фиктивную конечную точку, чтобы не сохранять так много сообщений (см. документацию), либо, возможно, лучше отправить сообщение в конечную точку журнала или что-то в этом роде.

В фиктивной документации есть большое красное предупреждение, говорящее о копии в памяти: http://camel.apache.org/mock

person Claus Ibsen    schedule 17.10.2013
comment
Спасибо, Клаус (кстати, большой поклонник твоей работы). Я использую 'mock:out' в этом простом примере, потому что он повторяет проблему, которую я вижу в моем общем приложении (огромное количество одновременных сегментов хеш-карты и возможный сбой пространства кучи). Я считаю, что мы можем иногда использовать фиктивные конечные точки в нашем общем приложении, когда мы хотим «отключить» определенные маршруты, где конечная точка является свойством в файле свойств. Есть ли текстовый эквивалент конечной точки .stop() в DSL? например '.to({{myproperty}})' и 'myproperty=stop'? (или другой безопасный способ завершить маршрут, установив свойство?) - person Matt; 17.10.2013
comment
Вы можете установить свойство на обмене, это то, что делает StopProcessor (например, ‹ /stop › // пометить обмен, чтобы остановить продолжение маршрутизации exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE); - person Claus Ibsen; 17.10.2013
comment
Проверил использование памяти сегодня утром после добавления '?retainFirst=1' в mock-spot ;-) - person Matt; 18.10.2013