Я пытаюсь заставить настольное приложение на основе Flex использовать сообщения из темы ActiveMQ с длительной подпиской, используя мост JMS BlazeDS. Основной сценарий выглядит следующим образом:
Сообщения создаются другими производителями в теме, на которую подписан клиент Flex.
Клиент Flex может время от времени выходить в автономный режим, но он должен получать все пропущенные сообщения, находясь в автономном режиме, когда он снова подключается к BlazeDS. (Конечно, клиент Flex соединяется с одним и тем же идентификатором клиента каждый раз).
Можно не гарантировать, что клиент Flex будет корректно завершен.
Все работает нормально, если я явно отключаю своего потребителя на стороне Flex, вызывая disconnect()
- я делаю это в обработчике выхода приложения. Однако, из-за # 3 выше, не гарантируется, что disconnect()
вызывается все время. Когда клиент Flex завершает работу без вызова disconnect()
, создается впечатление, что подписка «прокси-клиента JMS», который BlazeDS создает и связывает с клиентом Flex, остается активной для ActiveMQ, поэтому ActiveMQ по-прежнему считает, что клиент вошел в систему. приложение Flex запускается в следующий раз, оно не может войти в BlazeDS, поскольку ActiveMQ отказывается от своей подписки, утверждая, что идентификатор клиента уже занят. Почему так и что я могу сделать, чтобы BlazeDS отключил «прокси-клиент JMS» в ActiveMQ, когда его реальный аналог Flex неожиданно завершает работу?
Более подробная информация : некоторая отладка показала, что:
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 как активные.
Уничтожение 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 имеет ту же проблему.