• springboot async异步处理方案


    springboot提供了两种异步处理方案,一是传统同步web处理加异步service层,二是异步web处理框架webFlux。

    一、传统同步web处理加异步service层

    使用流程:在springboot application启动类上添加@EnableAsync注解。在service层类或方法上添加@Async注解,同时在异步方法所在的service层类上添加@Component或@service 等注解,该方法必须返回AsyncResult或CompletableFuture、ListenableFuture、Future之一,然后controller层通过@Autowired自动注入service类并使用异步类。

    controller和service层代码如下:

    1. @RestController
    2. public class UserCtroller {
    3. @Autowired
    4. UserService userService;
    5. @RequestMapping( "/n/{name}")
    6. @ResponseBody
    7. public User getUserByName(@PathVariable String name){
    8. AsyncResult> user = userService.getUserByName( name );
    9. try{
    10. return user.get().isEmpty() ? null: user.get().get() ;
    11. } catch (ExecutionException e) {
    12. return null;
    13. }
    14. }
    15. @RequestMapping( "/l")
    16. @ResponseBody
    17. public List getAll(){
    18. return userService.getAll();
    19. }
    20. }
    1. @Service
    2. public class UserServiceImpl implements UserService {
    3. List users = Arrays.asList(
    4. new User( "a", 20 , "aaaa"),
    5. new User( "b", 20 , "aaaa"),
    6. new User( "c", 20 , "aaaa")
    7. );
    8. @Override
    9. @Async
    10. public AsyncResult> getUserByName(String name){
    11. Optional user = users.stream().filter( (u) -> Objects.equals( u.getName(), name ) ).findFirst();
    12. return new AsyncResult<>( user );
    13. }
    14. @Override
    15. @Async
    16. public List getAll(){
    17. return users;
    18. }
    19. }

    在service的 getUserByName方法内置断点,执行监控调用堆栈,结果如下。可以看出spring采用AOP的方式将@Async的注解的方法封装为异步执行。

    1. getUserByName:26, UserServiceImpl (com.alun.serviceasync)
    2. invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
    3. invoke:77, NativeMethodAccessorImpl (jdk.internal.reflect)
    4. invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
    5. invoke:568, Method (java.lang.reflect)
    6. invokeJoinpointUsingReflection:344, AopUtils (org.springframework.aop.support)
    7. invokeJoinpoint:198, ReflectiveMethodInvocation (org.springframework.aop.framework)
    8. proceed:163, ReflectiveMethodInvocation (org.springframework.aop.framework)
    9. lambda$invoke$0:115, AsyncExecutionInterceptor (org.springframework.aop.interceptor)
    10. call:-1, AsyncExecutionInterceptor$$Lambda$778/0x0000000800fb3710 (org.springframework.aop.interceptor)
    11. run$$$capture:264, FutureTask (java.util.concurrent)
    12. run:-1, FutureTask (java.util.concurrent)
    13. - 异步堆栈跟踪
    14. :132, FutureTask (java.util.concurrent)
    15. :44, ListenableFutureTask (org.springframework.util.concurrent)
    16. submitListenable:412, ThreadPoolTaskExecutor (org.springframework.scheduling.concurrent)
    17. doSubmit:286, AsyncExecutionAspectSupport (org.springframework.aop.interceptor)
    18. invoke:129, AsyncExecutionInterceptor (org.springframework.aop.interceptor)
    19. proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
    20. invoke:215, JdkDynamicAopProxy (org.springframework.aop.framework)
    21. getUserByName:-1, $Proxy50 (jdk.proxy2)
    22. getUserByName:27, UserCtroller (com.alun.serviceasync)

    使用数据库事务时一定要注意:在Async方法上标注@Transactional,事务无效。 在Async方法调用的方法上标注@Transactional 有效。

    Springboot中使用@Async实现异步处理及注意事项  这篇文章总结的不错,值得大家参考。

    二、异步web处理框架webFlux

    spring5提供了webFlux异步处理框架,提高系统吞吐量和伸缩性,以 Reactor为核心,基于Servlet3.1规范实现,即从servlet线程就以异步方式处理请求。springboot提供了TomcatReactiveWebServerFactory、NettyReactiveWebServerFactory、UndertowReactiveWebServerFactory、JettyReactiveWebServerFactory四种ReactiveWebServer实现。默认使用容器是 Netty,Netty 是高性能的 NIO 框架。

    controller层的方法需要返回Mono或Flux,service代码不需要改动。如:

    1. @RestController
    2. public class UserCtroller {
    3. @Autowired
    4. UserService userService;
    5. @RequestMapping( "/n/{name}")
    6. public Mono getUserByName( @PathVariable String name){
    7. return userService.getUserByName( name );
    8. }
    9. @RequestMapping( "/l")
    10. public Flux getAll(){
    11. return userService.getAll();
    12. }
    13. }

    SpringWebflux 提供两种编程模式:注解编程模型和函数式编程模型。

    函数式编程模型参见Spring Webflux

    两种方式的gradle文件的配置如下,如需切换server提供方式,可以如下修改:

    web mvc方式配置:

    1. // web
    2. implementation ('org.springframework.boot:spring-boot-starter-web'){
    3. exclude group:'org.springframework.boot', module:'spring-boot-starter-tomcat'
    4. }
    5. implementation 'org.springframework.boot:spring-boot-starter-undertow'

    webFlux方式的配置:

    1. // webflux
    2. implementation ('org.springframework.boot:spring-boot-starter-webflux'){
    3. exclude group:'org.springframework.boot', module:'spring-boot-starter-netty'
    4. }
    5. implementation 'org.springframework.boot:spring-boot-starter-undertow'

  • 相关阅读:
    火爆疯传的 Redis 学习笔记,收藏达到 30W,让你成功上岸!
    基于Restful的WebService
    探索iOS之CoreImage框架
    Error-onnxruntime.capi.onnxruntime_pybind11_state.Fail:
    iPhone 14,要来了
    STM32的IAP讲解
    [SpringMVC笔记] 01-SpringMVC快速入门案例
    【力扣白嫖日记】626.换座位
    【读书笔记】【Effective C++】让自己习惯 C++
    MyBatis Plus详细教程
  • 原文地址:https://blog.csdn.net/Jahson/article/details/127977516