WebFlux 服务编排使用优势详解

作者:六七十三 时间:2021-11-27 07:48:45 

WebFlux服务编排

WebFlux 服务编排是指使用 WebFlux 框架来编排多个异步服务的执行顺序和数据流动,从而构建出一个完整的、基于事件驱动的响应式应用程序。

WebFlux服务编排的优势如下:

  • 高性能:WebFlux基于响应式编程模型,可以使用少量的线程处理大量的请求,从而提高系统的并发能力和吞吐量。

  • 异步处理:WebFlux可以异步处理请求和响应,避免线程的阻塞和等待,提高系统的并发能力和性能。

  • 高可靠性:WebFlux基于事件驱动的编程模型,可以更好地处理错误和异常,从而提高系统的可靠性和稳定性。

  • 简洁清晰:WebFlux的代码简洁清晰,可以使用函数式编程风格来编写业务逻辑,提高代码的可读性和可维护性。

  • 可扩展性:WebFlux可以轻松地集成其他的响应式组件和服务,例如Reactive Streams、Spring Cloud、RSocket等,从而提高系统的可扩展性和灵活性。

综上所述,WebFlux服务编排可以帮助我们构建高性能、高可靠性、可扩展性强的响应式应用程序,提高系统的并发能力和性能,从而更好地满足现代应用程序的需求。

一个示例

public Mono> getOrderDetails(String orderId) {
   return Mono.fromCallable(() -> {
       // 查询订单基本信息
       return "order info";
   })
   .flatMap(orderInfo -> {
       // 查询订单商品信息
       return Mono.fromCallable(() -> {
           return "order item info";
       });
   })
   .flatMap(orderItemInfo -> {
       // 查询订单配送信息
       return Mono.fromCallable(() -> {
           return "order delivery info";
       });
   })
   .flatMap(orderDeliveryInfo -> {
       // 查询订单支付信息
       return Mono.fromCallable(() -> {
           return "order payment info";
       });
   });
}

为什么使用 fromCallable,就是上面说的,WebFlux 编排的是异步服务,而不是同步服务。

但是实际线上不要使用 fromCallable,会导致创建很多个线程,高并发场景下会导致资源竞争激烈,从而服务性能急剧下降。

1 串行

1.1 不需要 invoker1 的结果

long start = System.currentTimeMillis();
Mono<String> invoke1 = Invoker1.invoke1();
Mono<String> result = invoke1.flatMap(p -> Invoker2.invoke2())
     .map(s -> {
        return s.toString();
     });
// result: invoker2, 耗时:3592(串行)
System.out.println("result: " + result.block() + ", 耗时:" + (System.currentTimeMillis() - start));

1.2 需要返回 invoker1 的结果

long start = System.currentTimeMillis();
Mono<String> invoke1 = Invoker1.invoke1();
Mono<String> result = invoke1.flatMap(p -> {
  return Invoker2.invoke2().map(s -> {
     return p + s;
  });
});
// result: invoker1invoker2, 耗时:3554(串行)
System.out.println("result: " + result.block() + ", 耗时:" + (System.currentTimeMillis() - start));

2 并行

2.1 zip 方法

zip() 方法可以一次组装任意个Mono,适用于有多个Mono的情况

long start = System.currentTimeMillis();
Mono<String> invoke1 = Invoker1.invoke1();
Mono<String> invoker2 = Invoker2.invoke2();
Mono<String> result = Mono.zip(invoke1, invoker2)
     .map(s-> {
        String t1 = s.getT1();
        String t2 = s.getT2();
        return String.format("invoke1:%s, invoke2: %s", t1, t2);
     });
// invoker1invoker2耗时:2650 (并行)
System.out.println("result: " + result.block() + ",耗时:" + (System.currentTimeMillis() - start));

2.2 zipWith 方法

zipWith() 每次组装一个Mono对象,使用于组装Mono个数比较少的情况。

long start = System.currentTimeMillis();
Mono<String> invoke1 = Invoker1.invoke1();
Mono<String> invoker2 = Invoker2.invoke2();
Mono<String> result = invoke1.zipWith(invoker2)
     .map(s -> {
        return String.format("invoke1:%s, invoke2: %s", s.getT1(), s.getT2());
     });
// invoker1invoker2耗时:2469 (并行)
System.out.println(result.block() + ",耗时:" + (System.currentTimeMillis() - start));

3 前提

这里的 invoker 就是第三方系统调用。

保证 invoker 是在独立的线程中执行,这样 invoker 不会影响业务处理。

public class Invoker1 {
  public static Mono<String> invoke1() {
     return Mono.
           fromSupplier(() -> {
              try {
                 Thread.sleep(1000);
              } catch (InterruptedException e) {
                 throw new RuntimeException(e);
              }
              return "invoker1";
           })
           .subscribeOn(Schedulers.parallel())
           .doOnError(e -> {
              System.out.println("error invoker1");
           });
  }
}
public class Invoker2 {
  public static Mono<String> invoke2() {
     return Mono.fromSupplier(() -> {
              try {
                 Thread.sleep(2000);
              } catch (InterruptedException e) {
                 throw new RuntimeException(e);
              }
              return "invoker2";
           })
           .subscribeOn(Schedulers.parallel())
           .doOnError(e -> {
              System.out.println("error invoker2");
           });
  }
}

来源:https://juejin.cn/post/7225902886944751677

标签:WebFlux,服务编排,优势
0
投稿

猜你喜欢

  • 使用SpringMVC访问Controller接口返回400BadRequest

    2023-06-05 00:14:01
  • 深入c# GDI+简单绘图的具体操作步骤(二)

    2022-01-31 12:43:49
  • Java中重载与重写的对比与区别

    2021-08-29 13:22:31
  • Java基于栈方式解决汉诺塔问题实例【递归与非递归算法】

    2023-04-10 08:05:02
  • Android studio 运行main 函数的方法

    2023-09-14 15:57:38
  • java集合与数组的相同点和不同点

    2022-07-19 03:13:53
  • 解决IDEA2020 创建maven项目没有src/main/java目录和webapp目录问题

    2022-05-29 07:57:18
  • 解决Springboot get请求是参数过长的情况

    2023-11-27 16:45:37
  • 教你如何使用Java输出各种形状

    2023-08-21 00:46:55
  • C#6.0中你可能不知道的新特性总结

    2023-08-17 04:25:54
  • Spring容器-BeanFactory和ApplicationContext使用详解

    2022-03-20 07:02:45
  • android为ListView每个Item上面的按钮添加事件

    2023-12-19 06:06:47
  • unity实现翻页按钮功能

    2021-07-15 03:33:47
  • java AOP原理以及实例用法总结

    2022-11-05 03:30:41
  • 关于@ConditionalOnProperty的作用及用法说明

    2023-11-24 02:39:19
  • VSCODE+cmake配置C++开发环境的实现步骤

    2023-05-31 21:25:14
  • Java中的final关键字详解及实例

    2023-05-26 11:09:46
  • Java基础之反射详解

    2022-06-16 12:25:11
  • Java并发之串行线程池实例解析

    2023-01-07 18:35:54
  • java 读写文件[多种方法]

    2022-10-04 09:09:00
  • asp之家 软件编程 m.aspxhome.com