每个客户端的Java EE AsyncContext

时间:2017-01-14 23:52:09

标签: java servlets java-ee asynchronous long-polling

我正在为长时间运行的进程使用异步servlet,并在客户端实现了长轮询,因此它可以显示进度并在完成时通知客户端。我实现了一个通知程序servlet,通过自定义EventNotify类手动插入会话ID,手动排序哪些客户端获取了哪些消息。如果getEventId()与eventid不同,我们将“IGNORE”发送到客户端,客户端手动忽略该消息。 notifyPeers自动向所有客户端发送通知。如果许多长时间运行的作业正在运行,这可能会变得非常嘈杂。有没有办法让notifyPeers只发送通知给AsyncContext注册的客户端? 提前谢谢!

@Singleton
public class Notifier {
    private final Queue<AsyncContext> peers = new ConcurrentLinkedQueue();
    private final HashMap<AsyncContext, String> acsessionmap = new HashMap<AsyncContext, String>();

    public void notifyPeers(@Observes EventNotify evn) {
        for (AsyncContext ac : peers) {
            try {
                String aceventid = acsessionmap.get(ac);
                final ServletOutputStream os = ac.getResponse().getOutputStream();
                if (Util.equals(aceventid, evn.getSessd())) {
                    os.println(evn.getSessid() + ": " + evn.getMessage());
                } else {
                    os.println("IGNORE");
                }
                ac.complete();
            } catch (IOException ex) {
            } finally {
                peers.remove(ac);
            }
        }
    }

public void addAsyncContext(final AsyncContext ac, String sessid) 
    ...
    acsessionmap.put(ac,sessid);
    peers.add(ac);

1 个答案:

答案 0 :(得分:0)

这是一个解决方案。 摆脱@Singleton是行不通的,因为AsyncContexts已停止&#34;连接&#34;一点都没 什么工作是保持单身和摆脱队列同行。相反,维护一个hashmap:

private final HashMap<String, AsyncContext> sessionacmap = new HashMap<String, AsyncContext>();

sessionacmap.put(sessid, ac);

而不是对等循环:

    for (AsyncContext ac : peers) {

只拉取asynccontext并对其采取行动:

    AsyncContext ac = sessionacmap.get(evn.getEventid());
    if (ac==null) return;
    try {
        final ServletOutputStream os = ac.getResponse().getOutputStream();
    ....

结果是,只有与该作业相关的事件才会通知请求特定作业的客户端。根本没有噪音,应该很好地扩展。 Websockets也应该工作,但在我们的特定情况下,我们遇到了websockets的负载平衡器问题。