Thursday, 27 September 2018

Introducing Servlet 4.0 Server Push

Posted by Naveen Katiyar On 06:32 No comments
In this article, We would be talking about Server Push Technology which was actually part of HTTP/2 spec.
Most important feature of Servlet 4.0 due to HTTP/2 is the implementation of the server push capability. The concept behind this technique is that if the client/browser requests a certain resource, the server assumes in advance, that some other related resources also may be requested  soon. Because of this assumption, it pushes them into cache(called 'cache push') before they are actually needed.For example, it is very much likely that when a Web page is loaded, it may eventually request a CSS file or some image. The server proactively starts pushing the bytes of these assets simultaneously without the need for the client to make an explicit request.

Servlet 4.0 Server Push

Servlet 4.0 is part of JAVA EE 8 and hence it would require JAVA 9+ along with Spring 5.x. Tomcat 9 supports HTTP/2 but it must be configured to use TLS. Tomcat 9 would be available only in Spring Boot 2.1.0  but it has not released yet and hence we would be using milestone version in our article.

Enable TLS support in Spring boot is just a matter of few properties in application.properties.Just use below ones to enable it:

#enable/diable https
server.ssl.enabled=true
server.ssl.key-store: classpath:keystore.jks
server.ssl.key-store-password: tomcatssl
server.ssl.keyStoreType: JKS
server.ssl.keyAlias: tomcatssl
server.port=8443

In case, you are not aware of how to generate keystore.jks, please follow this link

To enable http2 support in tomcat, below property needs to be added.
server.http2.enabled=true


After configuring our Server with TLS, we are good to go for exposing our endpoint which would be powered by HTTP/2 Push Technology.

@GetMapping(path = "/serviceWithPush")
public String serviceWithPush(HttpServletRequest request,PushBuilder pushBuilder) {
if (null != pushBuilder) {
    pushBuilder.path("resources/OnlineJavaPapers.png")
       .push();
}
return "index";
}

We will also configure another endpoint similar to above which would basically use traditional pull technology and will try to figure out the difference on client browser.

@GetMapping(path = "/serviceWithoutPush")
    public String serviceWithoutPush() {
       return "index";
    }

Using firefox devtool we can confirm that for serviceWithPush endpoint only one request was initiated from broswer:


Whereas when we call serviceWithoutPush then there would be two requests which would be triggered.


To conclude, Server Push technology combined with proper caching technique, we can greatly enhance page load time and responsiveness of our website.

Sample code for this can be found here.

Wednesday, 26 September 2018

Introducing Spring Webflux

Posted by Naveen Katiyar On 06:21 1 comment
In this article we are going to discuss on different choices which are provided by Spring 5 for Reactive and Async Concurrency model.I quite strongly believe, before we embrace something new, we should be aware of the differences between choices and how it connects to what we have been already doing. In my previous articles on this topic, I have tried to explain what we already have regarding concurrency model and how concurrency model has changed in Spring over the years with several updates in Servlet API.I would strongly recommend to read my previous articles on this topic, so that this article will make more sense.

Let’s try to figure out what was the reason to provide two different non blocking stacks in Spring 5.Basically Spring 5 provides  following two stacks for doing things in Async and non-blocking way:
  1. Spring MVC (Servlet Stack)
  2. Spring Webflux(Reactive Stack)

Spring MVC(Servlet Stack)

With the introduction of Servlet 3.1, Spring MVC could achieve non-blocking behavior.But as Servlet API contains several interfaces which are still blocking(may be because of support for backward compatibility),there was always chance of accidently using blocking API in application which was intended to be developed as Non-blocking.In such scenario,usage of blocking API will certainly bring down the application sooner or later. Let’s discuss one of the such scenario with below code snippet:

void onWritePossible(){
 try{
    //some logic here
 }catch(Exception e){
    response.sendError(500); ----> sendError() is a blocking API
 }
}

To explain above in Spring MVC context, using container managed error page is blocking.Let’s take a look at below code on my repo-


@Controller
public class MyErrorController implements ErrorController {
   @RequestMapping(path = "/error")
   public String greeting() {
      return "myerror";
   }
   @Override
   public String getErrorPath() {
      return "/error";
   }
}
Whenever some error occurs in a Spring application, container would invoke /error page and ‘myerror’ page would be rendered in a blocking way. Off course, we have ways to handle such things but are definitely error prone. To summarize, this is error prone, because application has access to Servlet Object, which has both blocking and non-blocking operations as shown below:

Online Java Papers : Spring Webflux

                                                        Flow Of Events

Online Java Papers : Spring Webflux                                                
                                                
So even though, we have ways in Spring 5 MVC to write completely non blocking code, The need was felt to have a stack in which there are no chances by which underlying blocking API’s could be used which means Servlet API is not directly exposed to application.This brings us to introduce Spring Reactive stack i.e. Spring Webflux.


Spring Webflux(Reactive Stack)

Spring webflux is a completely non-blocking reactive framework and it is indeed different than what we have in Spring MVC.  So,what does it take to not block in Spring webflux:

  • Event Loop at the core.
  • Event driven architecture,message passing
  • Means to compose async logic through Reactive Streams API
  • Backpressure

As we can see in below diag, Spring Webflux does not directly use Servlet instead use Spring Web API which include Reactor Streams.                                     

                                           Online Java Papers : Spring Webflux

Purpose of this tutorial series is to demonstrate the evolution of Servlet/Spring from blocking to Non-blocking paradigm, So I am not going in details of Spring Webflux in this tutorial.But still I am going to introduce a sample Spring boot application using Spring webflux.

One point which we should notice in above diagram is that Spring webflux is Servlet Container agnostic. Spring Webflux works on Servlet Container and also on Netty through Reactor Netty Project.

In my Spring boot application, I have a dependency of Webflux as spring-boot-starter-webflux and at server startup it says that application is ready with Netty.

[reactor-http-nio-1] 18:33 BlockingNettyContext: Started HttpServer on /0:0:0:0:0:0:0:0:8080
[restartedMain] 18:33 NettyWebServer: Netty started on port(s): 8080

In same application, if we use dependency to spring-boot-starter-web then logs would be printed as below:
[restartedMain] 23:56 TomcatWebServer: Tomcat started on port(s): 8080 (http) with context path ''

So without any code change, we can run Spring Webflux application as Spring MVC application.But vice-versa is not true as Spring MVC application could be using HttpServletRequest/Response which are not available in Spring Webflux runtime.

I have created same type of service which we used in earlier article using webflux as below:

@GetMapping(value = "/reactiveService")
public Mono<String> reactiveService(){
   logger.debug("reactiveService Request processing started");
   return webClient.get().uri("/sleep/1000")
          .retrieve().bodyToMono(Boolean.class)
          .doOnNext(response->{ logger.debug("reactive service");})
          .then(Mono.just("reactiveService"));

}

I would leave this for readers to compare the performance between this API and asyncNonBlockingRequestProcessing API as both are using non-blocking paradigm but underlying stack is different for both API’s.

Thank you for reading my article and I hope It would have helped a bit in understanding about reactive in Spring/Servlet context.

Source code for reactiveService could be found below:

Tuesday, 25 September 2018

Servlet 3.1/Spring MVC Non Blocking IO

Posted by Naveen Katiyar On 11:03 3 comments
Servlet 3.0 was released as part of Java EE 6 and made huge changes focused
at ease-of-use.The idea was to leverage the latest language features such as
annotations and generics and modernize how Servlets can be written.One of the
major change was Async Servlets. The web.xml was also made as optional as
possible. Servlet 3.1 released as part of Java EE 7, was an incremental release
focusing on couple of key features including Non-blocking IO.

Non-blocking I/O - Servlet 3.0 (Async Servlets as discussed in previous article)
allowed asynchronous request processing but only traditional I/O was permitted
which is blocking. This can restrict scalability of your applications.
Non-blocking I/O allow to build scalable applications.

Let’s discuss what I mean by above. We have learnt in previous article that in
case of async servlet, we must use non blocking code.So Let’s modify our
earlier MyServlet Code and replace runnable logic as below:-
Let’s revisit the code snippet which we discussed in previous article-

@WebServlet(name="myServlet", urlPatterns={"/asyncprocess"}, asyncSupported=true)
public class MyServlet extends HttpServlet {
   public void doGet(HttpServletRequest request, HttpServletResponse response) {
OutputStream out = response.getOutputStream();
          AsyncContext aCtx = request.startAsync(request, response);
          doAsyncREST(request).thenAccept(json -> {
out.write(json);  ---> Blocking!
ctx.complete();
          });
}
In above code, Container Request Thread is released and work is done in another
thread.So for async Servlet to actually work as expected, we have below requirement:

  1. doAsyncREST() must use Async library to call REST and return CompletableFuture. This  is possible using AsyncHttpClient which we have already used in previous article.
  1. thenAccept() should use async libraries.

But in Servlet 3.0, IO was traditional blocking and hence the thread calling out.write()
will block.
Let’s say, we have to write a huge json back to client.As we are using NIO
connector. OutputStream will first write to buffers and those buffers need to
be emptied by clients(using selector/channel mechanism of NIO). Now, if clients
are on slow network, then out.write() will have to wait till buffers are empty again
as InputStream/OutputStream is blocking.

Above problem of blocking was removed by Servlet 3.1 release by introducing async IO.

Servlet 3.1 Async IO
Let’s discuss this with the help of a code snippet as below:

void doGet(request, response) {
       ServletOutputStream out = response.getOutputStream();
       AsyncContext ctx = request.startAsync();
       out.setWriteListener(new WriteListener() {
           void onWritePossible() {
               while (out.isReady()) {
                   byte[] buffer = readFromSomeSource();
                   if (buffer != null)
                       out.write(buffer); ---> Async Write!
                   else{
                       ctx.complete(); break;
                   }
                 }
               }
           });
       }

In above code, we are making use of Write/Read Listener which were introduced
in 3.1. WriteListener is an interface which has onWritePossible() method which gets
called by Servlet Container. ServletOutputStreamt.isReady() is used to check if it is
possible to write in NIO channel buffers. In case it returns false then it schedules a
call on Servlet Container for onWritePossible() method and at some later point,
onWritePossible() is called on another thread.So, in this way, out.write() never block
for slow client to empty channel buffers.

Non Blocking IO in Spring?

To use this feature of non blocking IO in Spring application, we would need Spring 5
which is has JAVA EE 7 as baseline version. So , our earlier example which is also
mentioned below will execute in completely non blocking mode if we run this code
on Spring 5 MVC,Tomcat 8.5+

@GetMapping(value = "/asyncNonBlockingRequestProcessing")
   public CompletableFuture asyncNonBlockingRequestProcessing(){
           ListenableFuture listenableFuture = getRequest.execute(new AsyncCompletionHandler() {
               @Override
               public String onCompleted(Response response) throws Exception {
                   logger.debug("Async Non Blocking Request processing completed");
                   return "Async Non blocking...";
               }
           });
           return listenableFuture.toCompletableFuture();
   }


By now, we have discussed on how Servlet has evolved along with Spring to

provide complete non-blocking support which mean we can scale our application
with very less number of threads. In Next articles, we would be discussing on
Spring reactive stack(i.e. Spring webflux).One might think that, if Spring MVC is
capable of handling request in Non-blocking way, then why Spring webflux is
released as a separate stack and was it actually needed?
Stay tuned, it would be a interesting read in coming articles.



Server to Servlet/Spring - Servlet Async

Posted by Naveen Katiyar On 06:09 No comments
Server to Servlet/Spring and vice versa(Async Support)
In previous article, we discussed how Servlet Containers has evolved and turned communication between Client to Server into non-blocking paradigm. In this article we would be focusing on the evolution of Java Servlets(and hence Spring) towards non blocking reactive world.
Let’s recall the flow of request when received by NIO connector:
  1. Few threads (1-4 depending on # cores) polling the selector, looking for IO activity on a channel(hence on a connection).
  2. When selector sees IO activity, it calls a handle method on the connection and a thread from pool is allocated to process.
  3. Thread will attempt to read the connection and parse it and for http connection,if the request headers are complete, the thread goes on to call the handling of the request (eventually this gets to the servlet) without waiting for any content.
  4. Once a thread is dispatched to a servlet, it looks to it like the servlet IO is blocking and hence any attempt to read/write data from HttpInputStream/HttpOutputStream should block.But as we are using NIO connector, underneath, the IO operations using HttpInputStream and HttpOutputStream are async with callbacks. Due to blocking nature of Servlet API, it uses a special blocking callback to achieve blocking.
Step 4 above would have clarified more on ‘Simulated Blocking’ term used in previous article.

Challenges Prior to Servlet 3.0
Now coming back to the challenges posed by one thread per request model, we can see that actual request processing which is blocking in nature is done by a thread(we will call it request thread) from pool which is managed by servlet container. In NIO, default thread pool size is 200 which implies that only 200 request can be served concurrently. The problem with synchronous processing of requests is that it resulted in threads (doing heavy-lifting) running for a long time before the response goes out. If this happens at scale, the servlet container eventually runs out of threads - long running threads lead to thread starvation.

This size could be increased to suit any number(with hardware constraints) but then it will also bring the overhead of context switching,cache flush etc. While increasing threads and serving more concurrent request is not a bad idea but in case application requires high concurrency then we need to find some other suitable approach.Let’s read on to better understand the approach of handling more concurrent users without increasing container thread pool size.



Online Java Papers : Servlet Async
                        Server thread is blocked during Http Request Processing
Async Servlets in 3.0  
An async servlet enables an application to process incoming requests in an asynchronous fashion: A given HTTP request thread handles an incoming request and then passes the request to another background thread which in turn will be responsible for processing the request and send the response back to the client. The initial HTTP request thread will return to the HTTP thread pool as soon as it passes the request to the background thread, so it becomes available to process another request.
Online Java Papers : Servlet Async
                Server thread is released during Http Request Processing

Below is a code snippet on how this can be achieved in Servlet 3.0

@WebServlet(name="myServlet", urlPatterns={"/asyncprocess"}, asyncSupported=true) public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) { OutputStream out = response.getOutputStream(); AsyncContext aCtx = request.startAsync(request, response); //process your request in a different thread Runnable runnable = new Runnable() { @Override public void run() { String json ="json string"; out.write(json); ctx.complete(); } }; //use some thread pool executor poolExecutor.submit(runnable); } }

When the asyncSupported attribute is set to true, the response object is not committed on method exit. Calling startAsync() returns an AsyncContext object that caches the request/response object pair. The AsyncContext object is then stored in an application-scoped queue. Without any delay, the doGet() method returns, and the original request thread is recycled. We can configure a Thread Pool Execotor on server startup which will be used to process the request. After a request is processed, you have the option of calling HttpServletResponse.getOutputStream().write(...), and then complete() to commit the response, or calling forward() to direct the flow to a JSP page to be displayed as the result. Note that JSP pages are servlets with an asyncSupported attribute that defaults to false. complete() triggers Servlet container to return the response to the client.

Note: This whole behaviour which is defined above for Servlets can be achieved by returning  callable,DeferredResult or CompletableFuture from Spring Controller.


This approach by itself may solve the problem of HTTP thread pool exhaustion, but will not solve the problem of system resources consumption. After all, another background thread was created for processing the request, so the number of simultaneous active threads will not decrease and the system resource consumption will not be improved.So one might think, This could not be a better evolution on existing stack. Let’s first discuss its implementation in Spring and then will try to figure out in which scenarios this is desired and really scores big on synchronous servlets.

We would be using a Spring Boot  project to expose two endpoints-one blockingRequestProcessing and another asyncBlockingRequestProcessing using async servlet feature.

@GetMapping(value = "/blockingRequestProcessing")
   public String blockingRequestProcessing() {
       logger.debug("Blocking Request processing Triggered");
       String url = "http://localhost:8090/sleep/1000";
       new RestTemplate().getForObject(url, Boolean.TYPE);
       return "blocking...";
   }

   @GetMapping(value = "/asyncBlockingRequestProcessing")
   public CompletableFuture asyncBlockingRequestProcessing(){
       return CompletableFuture.supplyAsync(() -&gt; {
           logger.debug("Async Blocking Request processing Triggered");
           String url = "http://localhost:8090/sleep/1000";
           new RestTemplate().getForObject(url, Boolean.TYPE);
           return "Async blocking...";
       },asyncTaskExecutor);
   }


Both the services above are calling a RestService Endpoint called sleepingService.We can assume that the sleeping service has enough resources and won't be our bottleneck.
Also,I have set the number of Tomcat threads for this service to be 1000.Our service will have only 10 to quickly reproduce scale issues.

Through this setup we want to examine the performance of our blockingRequestProcessing service.

We can see that in blockingRequestProcessing, an external sleeping service is called which would sleep for 1 second. Our service maximum number of Tomcat threads is 10. We can use Jmeter to trigger 20 requests per second for 60 seconds. Overall, while all the Tomcat threads(10 in our case) are busy with processing requests, Tomcat holds the waiting requests in a requests queue. When a thread becomes available, a request is retrieved from the queue and is processed by that thread. If the queue is full, we get a "Connection Refused" error, but since I didn't change the default size (10,000 for NIO connector) and we inject only 1200 requests total (20 requests per second for 60 seconds) we won't see that. The client timeout (set in JMeter configuration is 60 seconds). These are the results from JMeter:


Many of the clients got timeouts. Why? JMeter calls 20 requests per second, while our service can process 10 requests every 1 second so we accumulate 10 requests in the Tomcat requests queue every second. Meaning, at second 60, the requests queue holds at least 600 requests. Can the service process all the requests with 10 threads in 60 seconds (the client timeout)? The answer is no.

Let's run the same test with the same code, but return CompletableFuture(This will hence make use of async servlet as explained above with thread pool executor) instead of String as in asyncBlockingRequestProcessing service.


Everything looks good. All  requests were successful. I even reduced the response time . What happened? As mentioned before, returning Callable releases the Tomcat thread and processing is executed on another thread. The other thread will be managed by the  Spring MVC task executor which we have configured.

We actually improved performance by adding resources i.e number of threads from Executor Thread Pool. Note that the request to sleeping-service is still blocking, but it is blocking a different thread (Spring MVC executor thread). Now, question arises if we could also have increased performance without using async servlet API and by increasing tomcat max thread configuration for NIO connector? The answer is YES but for specific use cases.


So, Where we could use Servlet 3.0 Async feature?   
Servlet 3.0 async is really useful if the processing request code uses nonblocking API (in our case, we use blocking API to call the other service) as shown in below sample code.

@GetMapping(value = "/asyncNonBlockingRequestProcessing")
   public CompletableFuture asyncNonBlockingRequestProcessing(){
           ListenableFuture listenableFuture = getRequest.execute(new AsyncCompletionHandler() {
               @Override
               public String onCompleted(Response response) throws Exception {
                   logger.debug("Async Non Blocking Request processing completed");
                   return "Async Non blocking...";
               }
           });
           return listenableFuture.toCompletableFuture();
   }

In above code , we are making use AsyncHttpClient which calls sleeping service in non-blocking way. Hence, with use of minimal threads here, we could scale our service to serve many more clients concurrently.

The benefit of releasing Tomcat threads is clear when it comes to a single Tomcat server with a few WARs deployed. For example, if I deploy two services and service1 needs 10 times the resources as service2, Servlet 3.0 async allows us to release the Tomcat threads and maintain a different thread pool in each service as needed.

With this we conclude our discussion on Servlet 3.0 Async feature. We have seen that this feature has changed the way, applications were designed and this would act as a solid foundation for Spring Reactive. Stay Tuned for next article on this!

Source code for this article could be found at: