BlazeDS + ActiveMQ: незаметное отключение клиента Flex от темы длительного пользования не удаляет его из ActiveMQ - PullRequest
1 голос
/ 03 июля 2011

Я пытаюсь заставить настольное приложение на основе Flex использовать сообщения из темы ActiveMQ с длительной подпиской, используя мост JMS BlazeDS. Основной сценарий выглядит следующим образом:

  1. Сообщения создаются другими производителями в теме, на которую подписан клиент Flex.

  2. Клиент Flex может время от времени выходить в автономный режим, но он должен получать все пропущенные сообщения, находясь в автономном режиме, когда он снова подключается к BlazeDS. (Конечно, клиент Flex соединяется с одним и тем же идентификатором клиента каждый раз).

  3. Можно не гарантировать, что клиент Flex будет корректно завершен.

Все работает нормально, если я явно отключаю своего потребителя на стороне Flex, вызывая disconnect() - я делаю это в обработчике выхода приложения. Однако, из-за # 3 выше, не гарантируется, что disconnect() вызывается все время. Когда клиент Flex завершает работу без вызова disconnect(), создается впечатление, что подписка «прокси-клиента JMS», который BlazeDS создает и связывает с клиентом Flex, остается активной для ActiveMQ, поэтому ActiveMQ по-прежнему считает, что клиент вошел в систему. приложение Flex запускается в следующий раз, оно не может войти в BlazeDS, поскольку ActiveMQ отказывается от своей подписки, утверждая, что идентификатор клиента уже занят. Почему так и что я могу сделать, чтобы BlazeDS отключил «прокси-клиент JMS» в ActiveMQ, когда его реальный аналог Flex неожиданно завершает работу?

Более подробная информация : некоторая отладка показала, что:

  1. BlazeDS узнает о прекращении работы клиента Flex, поскольку при работе в режиме отладки выводит на консоль несколько исключений. Сообщения следующие:

    [BlazeDS]23:18:13.688 [WARN] Endpoint with id 'my-streaming-amf' is closing the streaming connection to FlexClient with id '71E6466F-D91F-201C-F60A-A6CB52F95D9F' because endpoint encountered a socket write error, possibly due to an unresponsive FlexClient.
    ClientAbortException:  java.net.SocketException: Broken pipe
        at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:319)
        at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:288)
        at org.apache.catalina.connector.Response.flushBuffer(Response.java:542)
        at org.apache.catalina.connector.ResponseFacade.flushBuffer(ResponseFacade.java:279)
        at flex.messaging.endpoints.BaseStreamingHTTPEndpoint.handleFlexClientStreamingOpenRequest(BaseStreamingHTTPEndpoint.java:818)
        at flex.messaging.endpoints.BaseStreamingHTTPEndpoint.serviceStreamingRequest(BaseStreamingHTTPEndpoint.java:1055)
        at flex.messaging.endpoints.BaseStreamingHTTPEndpoint.service(BaseStreamingHTTPEndpoint.java:460)
        at flex.messaging.MessageBrokerServlet.service(MessageBrokerServlet.java:353)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
        at java.lang.Thread.run(Thread.java:680)
    Caused by: java.net.SocketException: Broken pipe
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
        at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:737)
        at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:434)
        at org.apache.coyote.http11.InternalOutputBuffer.flush(InternalOutputBuffer.java:299)
        at org.apache.coyote.http11.Http11Processor.action(Http11Processor.java:963)
        at org.apache.coyote.Response.action(Response.java:183)
        at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:314)
        ... 20 more
    
    [BlazeDS]23:18:13.689 [DEBUG] Streaming thread 'http-8400-1' for endpoint with id 'my-streaming-amf' is releasing connection and returning to the request handler pool.
    [BlazeDS]23:18:13.689 [INFO] Number of streaming clients for FlexSession with id '5BC5E8D604A361BCA673B05AC624CCC1' is 0.
    [BlazeDS]23:18:13.689 [DEBUG] Number of streaming clients for endpoint with id 'my-streaming-amf' is 0.
    

    На этом этапе подписки по-прежнему отображаются в интерфейсе веб-администратора ActiveMQ как активные.

  2. Уничтожение BlazeDS (точнее, сервера Tomcat, на котором он размещен) с помощью kill -9 из консоли заставляет ActiveMQ немедленно понять, что «прокси-клиент JMS» пропал, и он становится автономным на интерфейсе веб-администратора ActiveMQ. Это заставило меня заключить, что BlazeDS явно поддерживает прокси-JMS-клиент, поскольку kill -9 не дает BlazeDS возможности отменить подписку на клиента, но в ActiveMQ он по-прежнему отключается.

Итак, еще раз вопрос: что я могу сделать, чтобы BlazeDS отключил «прокси-клиент JMS» в ActiveMQ, когда его реальный аналог Flex неожиданно завершает работу? Это ошибка в BlazeDS или я просто пропускаю какой-то скрытый параметр конфигурации, который бы заставил его работать?

Информация о версии: BlazeDS 4.0, ActiveMQ 5.5.0, обе недавно загружены сегодня. Я использую сервер Tomcat под ключ BlazeDS, но ActiveMQ устанавливается отдельно, потому что под ключ BlazeDS поставляется только с ActiveMQ 4.1.1. Кстати, та версия ActiveMQ имеет ту же проблему.

1 Ответ

3 голосов
/ 05 июля 2011

Проблема заключается в том, что BlazeDS не может обнаружить, что ваш клиент Flex отключен, вам придется реализовать собственный механизм - я предлагаю использовать сердцебиение, реализованное с помощью обмена сообщениями. Если по истечении определенного промежутка времени от клиента не поступило никакого сообщения, вы можете предположить, что клиент Flex пропал и выполнить отключение (или вы можете использовать механизм тайм-аута сеанса на сервере и выполнить отключение по истечении сеанса).

То, что вы увидели (исключение обнаружено при закрытии потокового канала), недостаточно для 100% уверенности в том, что клиент Flex пропал. Потоковая передача реализована с использованием HTTP-соединения, которое всегда остается открытым (используется для отправки сообщений с сервера) и периодических HTTP-вызовов (инициируемых клиентом для отправки сообщений). В некоторых сетях брандмауэр может решить прервать HTTP-соединение через пару секунд, и вы получите такую ​​же ошибку, как та, которую вы опубликовали. Однако это не означает, что клиент Flex уничтожен - клиент Flex может использовать запасную стратегию и в этом случае переключиться на короткий / длинный опрос. На самом деле это будет ошибка, если BlazeDS автоматически отключит JMS в этом случае.

...