Вещание для подмножества подписчиков в Atmosphere

Что я пытаюсь сделать: иметь возможность подписаться пользователями на несколько разных «чатов» и использовать обратный AJAX/comet для отправки сообщений из чата всем, кто вошел в эту комнату. (немного сложнее, но это аналогичный вариант использования).

Что я делаю: использую Grails с JMS и атмосферой. Когда сообщение отправлено, я использую JMS для отправки объекта сообщения, полученного службой Grails, который затем передается на URL-адрес атмосферы (т.е. атмосфера/сообщения).

Очевидно, что JMS немного избыточен, но я мог бы использовать его, чтобы помочь мне отфильтровать, кто должен получить сообщение, хотя на самом деле это не похоже на то, что это сработает (учитывая, что подписчик в основном является одноэлементной службой...).

В любом случае, что мне нужно сделать, так это отправить сообщение правильному подмножеству людей, слушающих атмосферу/сообщения. Здесь идеально подойдет URL-адрес типа RESTful (например, атмосфера/сообщения/*, где * — идентификатор комнаты), однако я понятия не имею, как это сделать с атмосферой.

Любые идеи / предложения о том, как я могу достичь того, чего хочу? Здесь нет ничего конкретного, поэтому не стесняйтесь предлагать практически все, что угодно. Я даже думал (основываясь на ответе на другой вопрос), например, если бы я мог сделать что-то вроде отправки сообщений на сервер Node.js и обработать обратную часть AJAX/comet.


person NRaf    schedule 26.08.2011    source источник
comment
К вашему сведению: этот метод обычно называется Comet (в отличие от обратного ajax). .   -  person OverZealous    schedule 26.08.2011


Ответы (3)


Если я правильно понимаю ваши требования, должно работать следующее (код jax-rs + scala):

1) Все, кто хочет получать сообщения из чата, регистрируются в нем:

@GET
@Path(choose/a/path)
def register(@QueryParam("chatroomId") chatroomId: Broadcaster) {
  // alternatively, the Suspend annotation can be used
  new SuspendResponse.SuspendResponseBuilder[String]()
          .resumeOnBroadcast(false).broadcaster(chatroomId).scope(SCOPE.REQUEST)
          .period(suspendTimeout, TimeUnit.MINUTES)
          .addListener(new AtmosphereEventsLogger()).build
}

2) Чтобы отправить сообщение всем зарегистрированным пользователям, вызовите следующий метод:

@POST
@Broadcast
@Path(choose/a/path/{chatroomId})
def broadcast(@PathParam("chatroomId") id: String) {
  // first find your broadcaster with the BroadcasterFactory
  BroadcasterFactory.getDefault().lookupAll() // or maybe there is a find by id?
  broadcaster = ...
  broadcaster.broadcast(<your message>)
}

Я также рекомендую прочитать технический документ по атмосфере, взглянуть на список рассылки и на Блог Жан-Франсуа Аркана.

Надеюсь, это поможет.

person Christian    schedule 26.08.2011

Существует неправильное понимание концепции кометы. Это просто еще одна реализация публикации/подписки. Если у вас несколько чатов, то вам нужно иметь несколько «тем», то есть несколько каналов, на которые пользователь может зарегистрироваться. Например.:

broadcaster['/atmosphere/chatRoom1'].broadcast('Hello world!')

broadcaster['/atmosphere/chatRoom2'].broadcast('Hello world!')

Поэтому я бы посоветовал вам создать несколько каналов и не фильтровать вручную набор пользователей, которые должны получать сообщения (что определенно не следует делать). Вам не нужно ничего создавать на стороне сервера по этому поводу, так как пользователь будет просто регистрироваться на определенном канале и получать сообщения, которые кто-либо в него вкладывает.

person Chris    schedule 26.08.2011
comment
Значит, эти каналы можно генерировать динамически? Например, мне не нужно иметь дескриптор для каждого канала? Это метод на сервере, в котором мне нужно записать ответ, который получит клиент, подписанный на этот канал. Для этого мне нужен обработчик для этого канала. Что мне, возможно, нужно, так это иметь возможность иметь своего рода метод обработчика подстановочных знаков (т.е. серверировать все каналы в форме «/atmosphere/chatRoomX», где X = идентификатор комнаты чата). - person NRaf; 26.08.2011

Я бы рекомендовал вам создать AtmosphereHandler для одного URL-адреса, такого как /atmosphere/chat-room, а затем использовать AtmosphereResource и связать с ним BroadcastFilter, скажем, назовите его ChatRoomBroadcastFilter.

Всякий раз, когда пользователь подписывается на новую комнату чата, на сервер будет отправлено сообщение (от клиента), сообщающее серверу о подписке. После подписки сохраните список пользователей ‹> привязок комнаты чата где-нибудь на сервере.

Всякий раз, когда сообщение транслируется, транслируйте его с идентификатором комнаты чата. В ChatRoomBroadcastFilter (вам, вероятно, нужно сделать это PerRequestBroacastFilter) распространять сообщение пользователю, только если пользователь подписался на комнату чата. Я не уверен, что это проясняет ситуацию. Если вам нужен пример кода, пожалуйста, укажите в комментариях. Я поставлю это, но на это нужно время, поэтому сейчас не буду ;).

person Sharique Abdullah    schedule 25.09.2012