Async Context does not accept simultaneous requests

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Async Context does not accept simultaneous requests

Valery Dubrava
This post was updated on .
I solve the prolem.
I tried to create context for accepting many simultaneous requests by using AsyncServelet/Continuation. But the all requests to one context are queued. I will provide some code blocks for introducing into the problem. Please, help me with this issue. Maybe I understand something wrong and use this technology to the wrong way? A simple spring xml config for JettyServer:
    <bean name="jettyThreadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">
        <property name="name" value="jettyThreadPool" />
        <property name="minThreads" value="10" />
        <property name="maxThreads" value="100" />
    </bean>

    <bean name="jettyConnector" class="org.eclipse.jetty.server.nio.SelectChannelConnector">
        <property name="host" value="0.0.0.0" />
        <property name="port" value="8080" />
        <!-- The number of thread dedicated to accepting incoming connections. <= 2*processors -->
        <property name="acceptors" value="4" />
        <!-- Number of connection requests that can be queued up before the operating system starts to send rejections. -->
        <property name="acceptQueueSize" value="20" />
        <property name="resolveNames" value="false" />
        <property name="threadPool" ref="jettyThreadPool" />
    </bean>

    <bean name="server" class="org.eclipse.jetty.server.Server">
        <property name="connectors">
            <array>
                <ref bean="jettyConnector" />
            </array>
        </property>
        <property name="handler">
            <bean class="org.eclipse.jetty.server.handler.HandlerCollection">
                <property name="handlers">
                    <array>
                        <bean class="org.eclipse.jetty.server.handler.ContextHandler">
                            <property name="contextPath" value="/check" />
                            <property name="handler">
                                <bean class="com.oak.handlers.AsyncCheckHandler" />
                            </property>
                        </bean>
                    </array>
                </property>
            </bean>
        </property>
    </bean>
The AsyncCheckHandler is only for testing. In future it will make request to remote resources which takes several seconds. That why I call a sleep with 5 seconds interval.
public class AsyncCheckHandler extends AbstractHandler {
    @Override
    public void handle(String target, final Request baseRequest, final HttpServletRequest req,
            final HttpServletResponse rsp) throws IOException, ServletException
    {
        final AsyncContext context = req.startAsync(req, rsp);
        context.start(new Runnable() {
            @Override
            public void run()
            {
                try {
                    Date date = new Date();
                    Thread.sleep(5000L);
                    context.getResponse().getWriter().print("Request date " + date + ", " +
                                                                    "" + Thread.currentThread().getName());
                    baseRequest.setHandled(true);
                } catch (InterruptedException | IOException e) {
                    e.printStackTrace();
                } finally {
                    context.complete();
                }
            }
        });
    }
}
And main class is very simple:
        ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");

        Server server = (Server) context.getBean("server");
        try {
            server.start();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
When I run it and make several parallel requests to http://localhost:8080/check each of this requests is suspended until previous was done. That is the problem for me. I expected that after it returns from handler it will be ready to accept new requests to this context. Also I've tried the same thing with ServletContext and with Continuation. Jetty version is 8.1.9.v20130131, spring is 3.2.1.RELEASE. Java 1.7.0_13 I've tried this on windows7 and debian.
Reply | Threaded
Open this post in threaded view
|

Re: Async Context does not accept simultaneous requests

Joakim Erdfelt-9
        <!-- Number of connection requests that can be queued up before the operating system starts to send rejections. -->
        <property name="acceptQueueSize" value="1" />

Change that, bump it up to 20 or so.

--
Joakim Erdfelt <[hidden email]>
Developer advice, services and support
from the Jetty & CometD experts


On Fri, Mar 8, 2013 at 12:20 PM, Valery Dubrava <[hidden email]> wrote:
I tried to create context for accepting many simultaneous requests by using AsyncServelet/Continuation. But the all requests to one context are queued. I will provide some code blocks for introducing into the problem. Please, help me with this issue. Maybe I understand something wrong and use this technology to the wrong way? A simple spring xml config for JettyServer:
    <bean name="jettyThreadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">
        <property name="name" value="jettyThreadPool" />
        <property name="minThreads" value="10" />
        <property name="maxThreads" value="100" />
    </bean>

    <bean name="jettyConnector" class="org.eclipse.jetty.server.nio.SelectChannelConnector">
        <property name="host" value="0.0.0.0" />
        <property name="port" value="8080" />
        <!-- The number of thread dedicated to accepting incoming connections. <= 2*processors -->
        <property name="acceptors" value="4" />
        <!-- Number of connection requests that can be queued up before the operating system starts to send rejections. -->
        <property name="acceptQueueSize" value="1" />
        <property name="resolveNames" value="false" />
        <property name="threadPool" ref="jettyThreadPool" />
    </bean>

    <bean name="server" class="org.eclipse.jetty.server.Server">
        <property name="connectors">
            <array>
                <ref bean="jettyConnector" />
            </array>
        </property>
        <property name="handler">
            <bean class="org.eclipse.jetty.server.handler.HandlerCollection">
                <property name="handlers">
                    <array>
                        <bean class="org.eclipse.jetty.server.handler.ContextHandler">
                            <property name="contextPath" value="/check" />
                            <property name="handler">
                                <bean class="com.oak.handlers.AsyncCheckHandler" />
                            </property>
                        </bean>
                    </array>
                </property>
            </bean>
        </property>
    </bean>
The AsyncCheckHandler is only for testing. In future it will make request to remote resources which takes several seconds. That why I call a sleep with 5 seconds interval.
public class AsyncCheckHandler extends AbstractHandler {
    @Override
    public void handle(String target, final Request baseRequest, final HttpServletRequest req,
            final HttpServletResponse rsp) throws IOException, ServletException
    {
        final AsyncContext context = req.startAsync(req, rsp);
        context.start(new Runnable() {
            @Override
            public void run()
            {
                try {
                    Date date = new Date();
                    Thread.sleep(5000L);
                    context.getResponse().getWriter().print("Request date " + date + ", " +
                                                                    "" + Thread.currentThread().getName());
                    baseRequest.setHandled(true);
                } catch (InterruptedException | IOException e) {
                    e.printStackTrace();
                } finally {
                    context.complete();
                }
            }
        });
    }
}
And main class is very simple:
        ApplicationContext context = new ClassPathXmlApplicationContext("context.xml");

        Server server = (Server) context.getBean("server");
        try {
            server.start();
            server.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
When I run it and make several parallel requests to http://localhost:8080/check each of this requests is suspended until previous was done. That is the problem for me. I expected that after it returns from handler it will be ready to accept new requests to this context. Also I've tried the same thing with ServletContext and with Continuation. Jetty version is 8.1.9.v20130131, spring is 3.2.1.RELEASE. Java 1.7.0_13 I've tried this on windows7 and debian.

View this message in context: Async Context does not accept simultaneous requests
Sent from the Jetty Support mailing list archive at Nabble.com.

Reply | Threaded
Open this post in threaded view
|

Re: Async Context does not accept simultaneous requests

Valery Dubrava
I tried to do it, but it is not a soluting. Nothing changes =(
Thank you for ansewer in any case!
Reply | Threaded
Open this post in threaded view
|

Re: Async Context does not accept simultaneous requests

Valery Dubrava
In reply to this post by Valery Dubrava
I've found something like workaround. I've added different queries to each test request and they had been handled in parallel. But why it is not work when I use exactly the same URL? It's a common case for me.
Reply | Threaded
Open this post in threaded view
|

Re: Async Context does not accept simultaneous requests

Valery Dubrava
In reply to this post by Valery Dubrava
The root of the problem was the chrome browser, which I use for testing. It doesn't create new one connection to the same URL =(