Search code examples
proxyjettyjetty-9

How is it that Jetty AsyncProxyServlet does not mark all the requests as asyncStarted?


My team is maintaining an API management proxy based on jetty-9 AsyncProxyServlet

<jetty.version>9.4.30.v20200611</jetty.version>

Our current goal is to provide SLO monitors based on prometheus metrics

So far we have implemented our counters using a custom AsyncListener

Here is the listener code

@AllArgsConstructor
class AccessLogAsyncListener implements AsyncListener {

    private final AccessLogger accessLogger;

    @Override
    public void onComplete(final AsyncEvent event) {
        accessLogger.log(event.getSuppliedRequest(), event.getSuppliedResponse(), ProxyRequestStatus.SUCCESS);
    }

    @Override
    public void onTimeout(final AsyncEvent event) {
        accessLogger.log(event.getSuppliedRequest(), event.getSuppliedResponse(), ProxyRequestStatus.TIMEOUT);
    }

    @Override
    public void onError(final AsyncEvent event) {
        accessLogger.log(event.getSuppliedRequest(), event.getSuppliedResponse(), ProxyRequestStatus.ERROR);
    }

    @Override
    public void onStartAsync(final AsyncEvent event) {
    }

}

A dedicated counter being incremented based on the request status

The listener is added in a servlet filter using the following code

    @Override
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
        chain.doFilter(request, response);
        if (request.isAsyncStarted()) {
            request.getAsyncContext().addListener(accessLogAsyncListener);
        } else {
            accessLogger.log(request, response, ProxyRequestStatus.UNKNOWN);
        }
    }

When the workload starts hitting around 2k req / 30s, we get a pretty fair amount of counters being incremented for the UNKNOWN status (meaning that the request as not been marked as asyncStarted). With 4k req / 30s the ratio is around 13-15%.

My question being: What is the underlying mechanism that makes Jetty decide when to mark or not mark a request as async started ?

My guess is that there is a threshold value defined somewhere that triggers this behaviour to kick in. Can someone give us some insights on the topic ?

As an additional question, what would be the correct way of deducing a status (similar to what is done in the complete, error or timeout callbacks) if the request has not been started async ?


Solution

  • Never mind, I figured it out.

    Requests not marked as async are actually requests that did not pass the filter chain for a legitimate reason (wrong or missing API key)

    Passed the filter chain all requests are effectively handled asynchronously.