[SpringBoot] El uso y expansión de solicitudes asincrónicas


La diferencia entre solicitud asincrónica y llamada asincrónica

  • Los escenarios de uso de los dos son diferentes. Solicitudes asíncronas se utilizan para resolverlos 并发请求对服务器造成的压力, 提高对请求的吞吐量y llamadas asíncronas se utilizan 做一些非主线流程且不需要实时计算和响应的任务, por ejemplo, para sincronizar los registros a Kafka para el análisis de registro.
  • Las solicitudes asincrónicas son posibles 一直等待response响应的y los resultados deben devolverse al cliente; mientras que las llamadas asincrónicas, a menudo 会马上返回给客户端响应completamos la solicitud completa. En cuanto a la llamada asincrónica, el fondo de la tarea se ejecuta lentamente por sí mismo y al cliente no le importa.

Prefacio

Solicitud síncrona Solicitud
Inserte la descripción de la imagen aquí
asíncrona
Inserte la descripción de la imagen aquí
Características:

  • 先释放容器分配给请求的线程与相关资源, reduce la carga en el sistema y libera la solicitud del hilo asignado por el contenedor, la respuesta se retrasará.后台耗时处理完成(例如长时间的运算)时再对客户端进行响应。
  • En una palabra: aumente el rendimiento del servidor de las solicitudes de los clientes
  • ( 实际生产上我们用的比较少, Si la cantidad de solicitudes simultáneas es grande 通过nginx把请求负载到集群服务的各个节点上来分摊请求压力, por supuesto, estaremos bien 通过消息队列来做请求的缓冲).

Implementación de solicitud asincrónica

1. Forma de servlet para lograr una solicitud asincrónica

    @RequestMapping(value = "/email/servletReq", method = RequestMethod.GET)
    public void servletReq(HttpServletRequest request, HttpServletResponse response) {
    
    
        AsyncContext asyncContext = request.startAsync();
        //设置监听器:可设置其开始、完成、异常、超时等事件的回调处理
        asyncContext.addListener(new AsyncListener() {
    
    
            @Override
            public void onTimeout(AsyncEvent event) throws IOException {
    
    
                System.out.println("超时了...");
                //做一些超时后的相关操作...
            }

            @Override
            public void onStartAsync(AsyncEvent event) throws IOException {
    
    
                System.out.println("线程开始");
            }

            @Override
            public void onError(AsyncEvent event) throws IOException {
    
    
                System.out.println("发生错误:" + event.getThrowable());
            }

            @Override
            public void onComplete(AsyncEvent event) throws IOException {
    
    
                System.out.println("执行完成");
                //这里可以做一些清理资源的操作...
            }
        });
        
        //设置超时时间
        asyncContext.setTimeout(20000);
        asyncContext.start(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                try {
    
    
                    Thread.sleep(10000);
                    System.out.println("内部线程:" + Thread.currentThread().getName());
                    asyncContext.getResponse().setCharacterEncoding("utf-8");
                    asyncContext.getResponse().setContentType("text/html;charset=UTF-8");
                    asyncContext.getResponse().getWriter().println("这是异步的请求返回");
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                    System.out.println("异常:" + e);
                }
                //异步请求完成通知
                //此时整个请求才完成
                asyncContext.complete();
            }
        });
        //此时之类 request的线程连接已经释放了
        System.out.println("主线程:" + Thread.currentThread().getName());
    }

2.Callable

Los parámetros devueltos por el controlador用Callable包裹即可

Puede heredar la clase WebMvcConfigurerAdapter / implementar la interfaz WebMvcConfigurer (se recomienda SpringBoot2.0) para establecer el grupo de subprocesos predeterminado y el procesamiento del tiempo de espera

La interfaz utiliza Callable para decorar los parámetros de retorno.

    @RequestMapping(value = "/email/callableReq", method = RequestMethod.GET)
    @ResponseBody
    public Callable<String> callableReq() {
    
    
        System.out.println("外部线程:" + Thread.currentThread().getName());
        return new Callable<String>() {
    
    
            @Override
            public String call() throws Exception {
    
    
                Thread.sleep(10000);
                System.out.println("内部线程:" + Thread.currentThread().getName());
                return "callable!";
            }
        };
    }

La clase de configuración establece el grupo de subprocesos predeterminado y el manejo del tiempo de espera

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
    
    @Resource
    private ThreadPoolTaskExecutor myThreadPoolTaskExecutor;

    @Override
    public void configureAsyncSupport(final AsyncSupportConfigurer configurer) {
    
    
        //处理 callable超时
        configurer.setDefaultTimeout(60 * 1000);
        configurer.setTaskExecutor(myThreadPoolTaskExecutor);
        configurer.registerCallableInterceptors(timeoutCallableProcessingInterceptor());
    }

    @Bean
    public TimeoutCallableProcessingInterceptor timeoutCallableProcessingInterceptor() {
    
    
        return new TimeoutCallableProcessingInterceptor();
    }
}

3.WebAsyncTask

将Controller返回的参数用WebAsyncTask包裹De manera similar al uso invocable, puede, también puede configurar uno para WebAsyncTask 超时回调, puede lograr el procesamiento del tiempo de espera

Puede heredar la clase WebMvcConfigurerAdapter / implementar la interfaz WebMvcConfigurer (se recomienda SpringBoot2.0) para establecer el grupo de subprocesos predeterminado y el procesamiento del tiempo de espera

    @RequestMapping(value = "/email/webAsyncReq", method = RequestMethod.GET)
    @ResponseBody
    public WebAsyncTask<String> webAsyncReq() {
    
    
        System.out.println("外部线程:" + Thread.currentThread().getName());
        Callable<String> result = () -> {
    
    
            System.out.println("内部线程开始:" + Thread.currentThread().getName());
            try {
    
    
                TimeUnit.SECONDS.sleep(4);
            } catch (Exception e) {
    
    
                    e.printStackTrace();
            }
            logger.info("副线程返回");
            System.out.println("内部线程返回:" + Thread.currentThread().getName());
            return "success";
        };
        
        
        WebAsyncTask<String> wat = new WebAsyncTask<String>(3000L, result);
        wat.onTimeout(new Callable<String>() {
    
    
            @Override
            public String call() throws Exception {
    
    
                return "超时";
            }
        });
        return wat;
    }

4.Resultado diferido

DeferredResult puede hacer frente a algunos de 相对复杂一些的业务逻辑los la mayoría de los que es importante 可以在另一个线程里面进行业务处理及返回, nos podemos comunicar entre dos hilos sin ninguna relación .

Puede heredar la clase WebMvcConfigurerAdapter / implementar la interfaz WebMvcConfigurer (se recomienda SpringBoot2.0) para establecer el grupo de subprocesos predeterminado y el procesamiento del tiempo de espera

@RequestMapping(value = "/email/deferredResultReq", method = RequestMethod.GET)
    @ResponseBody
    public DeferredResult<String> deferredResultReq() {
    
    
        System.out.println("外部线程:" + Thread.currentThread().getName());
        //设置超时时间
        DeferredResult<String> result = new DeferredResult<String>(60 * 1000L);
        //处理超时事件 采用委托机制
        result.onTimeout(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("DeferredResult超时");
                result.setResult("超时了!");
            }
        });
        result.onCompletion(new Runnable() {
    
    

            @Override
            public void run() {
    
    
                //完成后
                System.out.println("调用完成");
            }
        });

        myThreadPoolTaskExecutor.execute(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                //处理业务逻辑
                System.out.println("内部线程:" + Thread.currentThread().getName());
                //返回结果
                result.setResult("DeferredResult!!");
            }
        });
        return result;
    }

Supongo que te gusta

Origin blog.csdn.net/qq877728715/article/details/111556998
Recomendado
Clasificación