Новое в Jetty - ожидание данных ответа с продолжениями, исключение ASYNCSTARTED - PullRequest
1 голос
/ 08 марта 2012

Я работаю на небольшом прокси-сервере, который управляет группой соединений tcp-ip, которые запускаются в цикле селектора.Внешняя служба связывается с прокси-сервером через http-сервер, встроенный в прокси-сервер, и эти запросы проходят через весь сокет, а затем возвращают ответ из этого сокета в ответ на исходный http-запрос.

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

Awesome system diagram

Я совершенно новичок в использовании Java для http любого, поэтому я решил использовать Jetty и настроитьпростой обработчик запросов в качестве примера Hello World.Использование thread.sleep предотвращает одновременные запросы, а продолжения, насколько я могу судить, требуют запуска событий.Я бы предпочел, чтобы запросы проверяли хэш время от времени, а не вызывали событие подключения каждый раз, когда сокет помещает ответ в хэш, если только события не будут сгенерированы по идентификатору запроса или чему-то еще.Это не кажется практичным, если много трафика.

Cliffs:

  • Как заставить обработчик (или сервлет, если мне нужно зайти так далеко) ждатьнемного или периодически, пока данные становятся доступными, не блокируя все остальное?
  • Есть ли лучший способ сделать так, чтобы запрос http знал о данных, которые он должен возвращать в качестве ответа?
  • Этот дизайн плохи если да, то какова альтернатива?

РЕДАКТИРОВАТЬ:

Вот мой первый удар по проблеме.Это прекрасно работает, когда HTTP-запрос указывает на идентификатор, который соответствует подключенному клиенту TCP.Если идентификатор не соответствует подключенному клиенту, Jetty сходит с ума, зацикливается и снова и снова выдает следующее исключение.Я ожидаю, что произойдет запрос на тайм-аут, поскольку он не может найти никаких сообщений в сборщике.

Mar 8, 2012 2:39:08 PM APIRequestHandler doPost
INFO: json: {"state": "255", "m": "set", "id": "00:00:00:00:00:06", "rid": "84955228696f11e1aa04c42c033c8bd7", "sid": "XXXXX"}
2012-03-08 14:39:08.526:WARN:oejs.ServletHandler:/
java.lang.IllegalStateException: ASYNCSTARTED,initial
    at org.eclipse.jetty.server.AsyncContinuation.suspend(AsyncContinuation.java:365)
    at org.eclipse.jetty.server.AsyncContinuation.suspend(AsyncContinuation.java:959)
    at APIRequestHandler.doPost(APIRequestHandler.java:72)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:594)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:485)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:412)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
    at org.eclipse.jetty.server.Server.handle(Server.java:351)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:900)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:954)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:857)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:76)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:609)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:45)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534)
    at java.lang.Thread.run(Thread.java:680)

Сервлет:

public void doPost(HttpServletRequest req, HttpServletResponse res)
        throws java.io.IOException
    {
    String rid = req.getParameter("rid");
    String msg = req.getParameter("json");
    String id = req.getParameter("id");

    // Send to tcp-ip channel
    APIMessage m = new APIMessage();
    m.rid = rid;
    m.id = id;
    m.json = msg + "\r\n";
    queue.add(m);
    this.selector.wakeup();

    Continuation cc = ContinuationSupport.getContinuation(req);

    res.setContentType("text/plain");
    res.getWriter().println("Request: "+rid+"\tstart:\t"+new Date());
    res.getWriter().flush();
    int elapsed = 0;
    String responseStr = "";
    boolean timeoutHappened = true;
    while(elapsed<this.timeout) // say 50 millis
    {
        if(collector.containsKey(rid)){
            responseStr = collector.get(rid);
            collector.remove(rid);
            timeoutHappened = false;
            break;
        }
        cc.setTimeout(10); // sleep 10 millis
        cc.suspend();
    }

    if(!timeoutHappened)
    {
        logger.info("--->API http request found response in collector!");
        logger.info("Respose: "+responseStr);
    }
    else // timed out
    {
        logger.info("--->API http request timed out!");
    }

    res.getWriter().println("Request: "+rid+"\tend:\t"+new Date());
    if(cc.isInitial()!=true) {cc.complete();}
}

1 Ответ

0 голосов
/ 08 марта 2012

Я бы начал с того, что посмотрим на то, что у нас в пристани для уже проксирования.

http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java

Если это не относится к тому, что вы пытаетесь сделать, оно по крайней мере получитвы начали.

Вы можете легко запустить этот встроенный сервлет с помощью класса в тестах этого пакета:

http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AsyncProxyServer.java

удачи

...