Springboot | 20th: Asynchronous requests for asynchronous development

Source: Internet
Author: User
Tags exception handling file upload progress bar set time
Objective

About web开发 the relevant knowledge points, the follow-up will be added to continue to write. such as webService services, and 发邮件 so on, these generally do not feel completely belong to web开发 the aspect, and now webService as an interface to provide services to the opportunity should be relatively small. So this chapter begins by explaining some of the points of knowledge that will be used in the asynchronous development process. This section explains the relevant knowledge points for asynchronous requests.

    • A little knowledge
      • What is an asynchronous request
      • Native Asynchronous Request API description
    • Servlet-style implementation of asynchronous requests
    • Spring Way to implement asynchronous requests
      • Callable
        • Usage
        • Timeout, custom thread settings
      • Deferredresult
      • Webasynctask
    • Resources
    • Summarize
    • At last
    • Cliché
A little bit of knowledge what is asynchronous request

Servlet 3.0Previously, the request was processed in such a Servlet way that Thread-Per-Request each Http request was handled by one thread from beginning to end. If a request requires IO operations, such as accessing a database, invoking a third-party service interface, and so on, the corresponding thread will wait for the ****io operation to complete synchronously , and the IO operation is very slow . So at this point the thread does not immediately release back to the thread pool for later use, which can lead to serious performance problems in the event of an increasing concurrency. The request flow is roughly:

Servlet3.0after publishing, a new feature is provided: processing requests asynchronously . You can release a container to the requested thread and related resources, lighten the system burden, release the request for the thread allocated by the container, and its response will be deferred , and then respond to the client when the time-consuming processing is complete (for example, a long operation). The request process is:

Servlet 3.0after that, we can HttpServletRequest get AsyncContext an object from the object that forms the context of the asynchronous processing, and the Request Response object can be obtained from it. AsyncContextyou can path from the current line to another thread, complete the processing of the request in a new thread, and return the result to the client, and the initial thread can return to the container thread pool to handle more requests. Thus, the process of path the request from one thread to another is the Servlet 3.0 asynchronous processing in.

Say a few more words:

With the Spring5 release, a responsive web framework is provided: Spring WebFlux . After that, you may not need Servlet container support. Here is the comparison chart:

On the left is the traditional frame based, the Servlet Spring Web MVC right is the 5.0 version of the newly introduced framework based on, Reactive Streams Spring WebFlux from top to bottom is Router Functions,webflux, REACTIVE STREAMS three new components.

It remains to be seen for the future. It's time to get to know it Spring5 .

Native Asynchronous Request API description

Before writing the actual code, let's take a look at some of the invocation instructions for the API for asynchronous requests.

    • Get Asynccontext: HttpServletRequest gets from object.
AsyncContext asyncContext = request.startAsync();
    • Set listener: Can set its start, completion, exception, timeout and other events callback processing

The interface code for its listener:

public interface AsyncListener extends EventListener {    void onComplete(AsyncEvent event) throws IOException;    void onTimeout(AsyncEvent event) throws IOException;    void onError(AsyncEvent event) throws IOException;    void onStartAsync(AsyncEvent event) throws IOException;}

Description

    1. Onstartasync: Called when an asynchronous thread starts
    2. OnError: Called when an asynchronous thread is faulted
    3. OnTimeOut: Asynchronous thread execution timeout call
    4. OnComplete: Called when asynchronous execution is complete

In general, we will return to the front-end corresponding prompt when the timeout or exception, such as timeout, please request again and so on, according to the business to customize the return. At the same time, when the asynchronous call is complete, some cleanup work or other related operations are generally required.

It is important to note that the listener's method only works if the listener is added before the call, request.startAsync AsyncContext onStartAsync and startAsync does not exist before the call, AsyncContext so the first call startAsync is not captured by the method in the listener onStartAsync . The method will only work if the timeout is restarted onStartAsync .

    • Set time-out: by setTimeout method setting, unit: milliseconds.

Be sure to set the timeout time , not indefinitely wait, otherwise, and the normal request is the same.

Servlet-style implementation of asynchronous requests

As mentioned earlier, an object can be HttpServletRequest obtained from AsyncContext an object that forms the context of the asynchronous processing. So, let's do the actual operation.

0. Write a simple control layer

/** * Asynchronous request using servlet mode * @author okong * */@Slf4j @restcontrollerpublic class Servletcontroller {@RequestMapping (" /servlet/orig ") public void Todo (HttpServletRequest request, httpservletresponse response) throws Exception        {//Here comes a dormant thread.sleep (100);    Response.getwriter (). println ("This is the" normal "request return"); } @RequestMapping ("/servlet/async") public void Todoasync (HttpServletRequest request, HTTPSERVLETRESP        Onse response) {Asynccontext Asynccontext = Request.startasync (); Asynccontext.addlistener (New Asynclistener () {@Override public void OnTimeOut (Asynceven                T event) throws IOException {Log.info ("timed out:"); Do some related actions after timeout} @Override public void Onstartasync (AsyncEvent event) throws I            oexception {//TODO auto-generated Method stub log.info ("Thread Start");                        }@Override public void OnError (AsyncEvent event) throws IOException {Log.info ("error occurred:", Event.gett            Hrowable ());                } @Override public void OnComplete (AsyncEvent event) throws IOException {                Log.info ("execution complete");        Here you can do some cleanup of resources});        Set timeout time asynccontext.settimeout (200); You can also make asynchronous calls without using Start//New Thread (new Runnable () {////@Override//public void RU                N () {//write business logic////}//}). Start ();                    Asynccontext.start (New Runnable () {@Override public void run () {try {                    Thread.Sleep (100);                    Log.info ("Internal thread:" + thread.currentthread (). GetName ());                    Asynccontext.getresponse (). setcharacterencoding ("Utf-8"); Asynccontext.getresponse (). SetcoNtenttype ("Text/html;charset=utf-8");                Asynccontext.getresponse (). Getwriter (). println ("This is the" asynchronous "request Return");                } catch (Exception e) {log.error ("exception:", E);                }//Asynchronous request completion notification//At this time the entire request is complete//You can actually use this feature to push multiple messages to hang the connection.            Asynccontext.complete ();        }        });    At this point the request thread connection has already freed Log.info ("Thread:" + thread.currentthread (). GetName ()); }}

Note: When you request asynchronously, you can leverage ThreadPoolExecutor a custom thread pool.

1. Start the application and check the console output to see if it is in the same thread. At the same time, the wait time can be set, and then the timeout callback method is called. You can try it yourself.

2018-08-15 23:03:04.082  INFO 6732 --- [nio-8080-exec-1] c.l.l.s.controller.ServletController     : 线程:http-nio-8080-exec-12018-08-15 23:03:04.183  INFO 6732 --- [nio-8080-exec-2] c.l.l.s.controller.ServletController     : 内部线程:http-nio-8080-exec-22018-08-15 23:03:04.190  INFO 6732 --- [nio-8080-exec-3] c.l.l.s.controller.ServletController     : 执行完成

When using a filter, you need to join asyncSupported as a true configuration to turn on asynchronous request support.

@WebServlet(urlPatterns = "/okong", asyncSupported = true )  public  class AsyncServlet extends HttpServlet ...

In fact, we can use the non-execution asyncContext.complete() method when the request does not end this feature, you can do a simple file upload progress bar and other functions. However, note that the request is timed out and needs to be set to time out.

Spring Way to implement asynchronous requests

In Spring , there are several ways to implement asynchronous requests, such as callable , DeferredResult or WebAsyncTask . Each usage is slightly different and can be selected in different ways depending on the business scenario. Here are some of the most common uses

Callable

Using a simple, directly returned parameter is wrapped in a layer callable .

Usage
    @RequestMapping("/callable")    public Callable<String> callable() {        log.info("外部线程:" + Thread.currentThread().getName());        return new Callable<String>() {            @Override            public String call() throws Exception {                log.info("内部线程:" + Thread.currentThread().getName());                return "callable!";            }        };    }

Console output:

2018-08-15 23:32:22.317  INFO 15740 --- [nio-8080-exec-2] c.l.l.s.controller.SpringController      : 外部线程:http-nio-8080-exec-22018-08-15 23:32:22.323  INFO 15740 --- [      MvcAsync1] c.l.l.s.controller.SpringController      : 内部线程:MvcAsync1
Timeout, custom thread settings

From the console, you can see that the asynchronous response thread is using a thread named: MvcAsync1 . The first time we visited, MvcAsync2 it was. With the default setting, new threads are created indefinitely to handle asynchronous requests, so a thread pool and time-out are required to be configured normally.

Write a configuration class:CustomAsyncPool.java

@Configurationpublic class Customasyncpool extends webmvcconfigureradapter{/** * Configure the thread pool * @return */@Be An (name = "Asyncpooltaskexecutor") public threadpooltaskexecutor Getasyncthreadpooltaskexecutor () {Threadpoolta        Skexecutor taskexecutor = new Threadpooltaskexecutor ();        Taskexecutor.setcorepoolsize (20);        Taskexecutor.setmaxpoolsize (200);        Taskexecutor.setqueuecapacity (25);        Taskexecutor.setkeepaliveseconds (200);        Taskexecutor.setthreadnameprefix ("callable-"); The thread pool's processing strategy for rejecting a task (which is available on a wireless path) currently only supports AbortPolicy, Callerrunspolicy; The default is the latter Taskexecutor.setrejectedexecutionhandler (new        Threadpoolexecutor.callerrunspolicy ());        Taskexecutor.initialize ();    return taskexecutor;        } @Override public void Configureasyncsupport (final asyncsupportconfigurer configurer) {//Processing callable Timeout        Configurer.setdefaulttimeout (60*1000);        Configurer.registercallableinterceptors (Timeoutinterceptor ()); ConFigurer.settaskexecutor (Getasyncthreadpooltaskexecutor ());    } @Bean Public Timeoutcallableprocessor timeoutinterceptor () {return new timeoutcallableprocessor (); }    }

To customize a timeout exception handling class:CustomAsyncRequestTimeoutException.java

/** * 自定义超时异常类 * @author oKong * */public class CustomAsyncRequestTimeoutException extends RuntimeException {    /**     *      */    private static final long serialVersionUID = 8754629185999484614L;    public CustomAsyncRequestTimeoutException(String uri){        super(uri);    }}

At the same time, the unified exception processing to join the CustomAsyncRequestTimeoutException processing of the class, so there is a unified configuration.

After that, you can see that a custom thread pool has been used, and the timeout can be simulated by itself:

2018-08-15 23:48:29.022  INFO 16060 --- [nio-8080-exec-1] c.l.l.s.controller.SpringController      : 外部线程:http-nio-8080-exec-12018-08-15 23:48:29.032  INFO 16060 --- [     oKong-1] c.l.l.s.controller.SpringController      : 内部线程:oKong-1
Deferredresult

Compared to callable , Deferredresult can handle some relatively complex business logic, most of which can be processed and returned in another thread. Can communicate between two completely unrelated threads.

/** * thread pool */public static Executorservice Fixed_thread_pool = Executors.newfixedthreadpool (30); @RequestMapping ("/deferredresult") public deferredresult<string> Deferredresult () {log.info ("external thread:" + thre        Ad.currentthread (). GetName ());        Set timeout time deferredresult<string> result = new deferredresult<string> (60*1000l);                The processing timeout event takes the delegate mechanism Result.ontimeout (new Runnable () {@Override public void run () {                Log.error ("Deferredresult timeout");            Result.setresult ("Timed out!");        }        });                Result.oncompletion (New Runnable () {@Override public void run () {//after completion            Log.info ("Call complete");        }        });                Fixed_thread_pool.execute (New Runnable () {@Override public void run () { Process business logic log.info ("Internal thread:" + thread.currentthread (). GetName ());                Returns the result Result.setresult ("deferredresult!!");        }        });    return result; }

Console output:

2018-08-15 23:52:27.841  INFO 12984 --- [nio-8080-exec-2] c.l.l.s.controller.SpringController      : 外部线程:http-nio-8080-exec-22018-08-15 23:52:27.843  INFO 12984 --- [pool-1-thread-1] c.l.l.s.controller.SpringController      : 内部线程:pool-1-thread-12018-08-15 23:52:27.872  INFO 12984 --- [nio-8080-exec-2] c.l.l.s.controller.SpringController      : 调用完成

Note: Remember to call the next method when returning results setResult .

Off-topic: the DeferredResult ability to implement some long-connected functions, such as when an operation is asynchronous, we can save this DeferredResult object, when the asynchronous notification back, we are retrieving the DeferredResult object, and then the setResult result will be. Improve performance.

Webasynctask

The use method is similar, just WebAsyncTask return directly. Think is the same way, more details hope the great God answer!

  @RequestMapping ("/webasynctask") public webasynctask<string> Webasynctask () {log        . info ("External thread:" + thread.currentthread (). GetName ()); webasynctask<string> result = new Webasynctask<string> (60*1000l, New callable<string> () {@Ov Erride public String Call () throws Exception {log.info ("Internal thread:" + thread.currentthread (). GetName                ());            return "Webasynctask!!!";        }        }); Result.ontimeout (New callable<string> () {@Override public String call () throws Ex            ception {//TODO auto-generated Method stub return "Webasynctask timeout!!!";        }        }); Result.oncompletion (New Runnable () {@Override public void run () {//timeout after            This method is also executed log.info ("Webasynctask execution End");        }        });    return result; }

Console output:

2018-08-15 23:55:02.568  INFO 2864 --- [nio-8080-exec-1] c.l.l.s.controller.SpringController      : 外部线程:http-nio-8080-exec-12018-08-15 23:55:02.587  INFO 2864 --- [          oKong-1] c.l.l.s.controller.SpringController      : 内部线程:oKong-12018-08-15 23:55:02.615  INFO 2864 --- [nio-8080-exec-2] c.l.l.s.controller.SpringController      : WebAsyncTask执行结束
Resources
    1. 52266905
    2. docs.spring.io/spring/docs/4.3.18.release/spring-framework-reference/htmlsingle/#mvc-ann-async
Summarize

This chapter is mainly about 异步请求 the use and related configuration, such as timeouts, anomalies and other processing. When setting up an asynchronous request, remember to set the time-out. It is important to note that the throughput of the service is increased, the 异步请求 number of requests processed per unit of time is increased, and the processing efficiency is not speeded up. . In the next section, we'll talk about using @Async asynchronous invocation-related knowledge.

At last

At present, many big guys on the internet have a SpringBoot series of tutorials, if there is a similar, please forgive me. This article is the author in front of the computer word knocking, each step is his own practice. If there is something wrong in the text, also hope to put forward, thank you.

Cliché
    • Personal QQ:499452441
    • Public Number:lqdevOps

Personal blog: http://blog.lqdev.cn

Complete Example: github.com/xie19900123/spring-boot-learning/tree/master/chapter-20

Original Address:/HTTP

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.