Статьи

Кластеризация вашего приложения Comet с использованием атмосферы

Действительно просто добавить поддержку кластеризации в приложение на основе Comet в Atmosphere и развернуть его внутри любого контейнера сервлетов, поддерживающего Servlet 3.0, Comet или нет. Вы просто должны решить, какую групповую технологию вы хотите использовать, благодаря подключаемому модулю Atmosphere: Shoal или JGroups !

Во-первых, если вы хотите начать работу с Atmosphere, я рекомендую сначала взглянуть на введение атмосферы-cpr (на основе POJO) и атмосферы-ядра (на основе аннотаций / REST). Давайте начнем с примера Chat, написанного против атмосферы-cpr В AtmosphereHandler # OnEvent выглядит как

  if (req.getMethod().equalsIgnoreCase("GET")) {
event.suspend();
Broadcaster bc = event.getBroadcaster();
bc.getBroadcasterConfig().addFilter(new XSSHtmlFilter());
bc.broadcast(event.getAtmosphereConfig().getWebServerName()
+ "**has suspended a connection from "
+ req.getRemoteAddr());
} else if (req.getMethod().equalsIgnoreCase("POST")) {
res.setCharacterEncoding("UTF-8");
String action = req.getParameterValues("action")[0];
String name = req.getParameterValues("name")[0];

if ("login".equals(action)) {
req.getSession().setAttribute("name", name);
event.getBroadcaster().broadcast("System Message from "
+ event.getAtmosphereConfig().getWebServerName() + "**" + name + " has joined.");
res.getWriter().write("success");
res.getWriter().flush();
} else if ("post".equals(action)) {
String message = req.getParameterValues("message")[0];
event.getBroadcaster().broadcast(name + "**" + message);
res.getWriter().write("success");
res.getWriter().flush();
} else {
res.setStatus(422);

res.getWriter().write("success");
res.getWriter().flush();
}
}
return event;
}

 

Приятной особенностью Atmosphere является поддержка Broadcaster . Broadcaster используется для трансляции сообщений между приостановленными ответами, например, для примера чата, каждый раз, когда пользователь вводит новое сообщение, мы используем Broadcaster для трансляции этого сообщения всем другим пользователям. Broadcaster поддерживает BroadcastFilter , который действительно полезен для манипулирования сообщениями до того, как они будут записаны набором приостановленных соединений. Если вы посмотрите на строку 80/81 выше, мы настроим Broadcaster с помощью XSSHtmlFilterчтобы не допустить злонамеренной болтовни, отправьте нам Javascript как сообщение и отправьте этот скрипт обратно другому пользователю. В самом деле, BroadcastFilters весьма полезны, когда пришло время фильтровать / преобразовывать / объединять сообщения или транслировать сообщения другим компонентам, таким как EJB, темы / очереди JMS … или кластер !. Хорошая новость заключается в том, что Atmosphere поддерживает технологию двух кластеров: JGroups и Shoal. Чтобы добавить поддержку кластера в вышеупомянутое приложение чата, все, что нам нужно сделать, это:

 res.setContentType("text/html");
res.addHeader("Cache-Control", "private");
res.addHeader("Pragma", "no-cache");

if (req.getMethod().equalsIgnoreCase("GET")) {
event.suspend();
Broadcaster bc = event.getBroadcaster();
bc.getBroadcasterConfig().addFilter(
new JGroupsFilter(bc, event.getAtmosphereConfig().getWebServerName()));
bc.getBroadcasterConfig().addFilter(new XSSHtmlFilter());

 

Просто нужно добавить XXXFilter, где xxx — это групповая технология, которую вы хотите использовать: ShoalFilter или JGroupsFilter , и все! Просто добавив строку 91, вы создадите кластеризацию вашего приложения атмосферы-cpr, и любой вызов Broadcaster.broadcast достигнет всех экземпляров AtmosphereHandler в одном кластере.

Хм, это было слишком сложно ? ! Давайте теперь воспользуемся атмосферной поддержкой ядра для аннотаций. Пример чата на основе REST от Atmosphere выглядит следующим образом:

 @Path("/chat")
public class ResourceChat {

@Suspend()
@GET
@Produces("text/html")
public String suspend() {
return "";
}

@Broadcast
@Consumes("application/x-www-form-urlencoded")
@POST
@Produces("text/html")
@BroadcastFilter({XSSHtmlFilter.class,JsonpFilter.class})
public String publishMessage(MultivaluedMap form) {
String action = form.getFirst("action");
String name = form.getFirst("name");

if ("login".equals(action)) {
return ("System Message" + "__" + name + " has joined.");
} else if ("post".equals(action)) {
return name + "__" + form.getFirst("message");
} else {
throw new WebApplicationException(422);
}
}
}

 

Чтобы добавить поддержку кластеризации, нам просто нужно аннотировать метод, который передает сообщение, например:

@Broadcast
@Consumes("application/x-www-form-urlencoded")
@POST
@Produces("text/html")
@BroadcastFilter({XSSHtmlFilter.class,JsonpFilter.class})
@Cluster(
name="chat",
value=ShoalFilter.class
)
public String publishMessage(MultivaluedMap form) {
String action = form.getFirst("action");
String name = form.getFirst("name");

if ("login".equals(action)) {
return ("System Message" + "__" + name + " has joined.");
} else if ("post".equals(action)) {
return name + "__" + form.getFirst("message");
} else {
throw new WebApplicationException(422);
}
}
}

 

Это оно!. Просто аннотируя правильный метод, Atmosphere обеспечит правильную настройку Shoal / JGroups, чтобы каждая трансляция была доступна внутри кластера.

По любым вопросам или для загрузки приведенного выше примера перейдите на наш основной сайт и воспользуйтесь нашим форумом Nabble (подписка не требуется) или подпишитесь на нас в Twitter и разместите там свои вопросы!

С http://weblogs.java.net/blog/jfarcand