Reactor 第九篇 WebFlux重构个人中心,效果显著

news2024/11/16 1:53:56

1 重构背景

原有的开发人员早已离职,代码细节没人知道,经过了一段时间的维护,发现有以下问题:

个人中心系统的特征就是组装各个业务的接口,输出个人中心业务需要的数据,整个系统调用了几十个第三方业务线的接口,如果编排不合理,可能会导致响应时间急剧上涨,尤其是弹窗业务,新的弹窗会不断接入,整个接口可能会不可用。

2 整体架构

service:是最小的业务编排单元,request方法对infrastructure第三方接口进行编排调用;apply 方法对第三方接口调用的结果进行组装,结果是service的业务返回;

infrastructure:是对第三方的异步非阻塞调用,不包含业务逻辑。一个service内部根据实际业务可以编排0个或者多个infrastructure服务。

在实际优化过程中我们抽象了30多个infrastructure第三方调用,40多个service。他们都是小而且独立的类,减轻了开发同学尤其是新同学熟悉的成本。边界也比较清晰,逻辑内聚。

2 编排举例

每个 service 内部都是由一个或者多个 infrastructure 第三方调用组装编排的业务单元,内部处理能异步处理的全是使用异步处理,实在不能异步处理的使用串行+并行的方式。

2.1 串行

需要串行的可以使用 flatMap 方法,可以参考以下格式。

这种方式会执行S1,然后S2。

伪代码如下:

Mono.from(service1.func())
				.flatMap(service1Res-> {
          return service2.func();
        })

2.2 并行

zip 和 zipWith,zipWith一次组装一个Mono,zip 一次可以组装多个Mono。

示例代码如下:

service1.zipWith(service2)

Mono.zip(service1, service2, service3)

一个使用 zip 组装多个service的示例代码,并行执行service1, service2, …, service6,使用doOnError处理错误,onErrorReturn 处理异常返回,doOnFinally 监控整个接口调用量、耗时情况。

Mono.zip(service1, service2, service3, service4, service5, service6)
				.map(t -> {
					String service1Ret = t.getT1();
					String service2Ret = t.getT2();
          // ....
					return "组合结果";
				})
        // 异常返回
				.onErrorReturn(new DTO())
				.doOnError(e -> {
					// 异常详情日志;异常请求量监控
				})
				.doFinally(e -> {
          // 请求量、耗时监控
				});

2.3 并行-但只取第一个有数据的结果

弹窗类业务与一般service不通,它需要调用很多的业务的数据出不同的弹窗,但是每次都只能给用户展示确定的一个。但是如果串行的话,随着上线的弹窗越来越多,整个弹窗接口的耗时会越来越长。

但是如果改成异步的话,又无法控制弹窗之间的优先级,优先级对于公司整体业务来说是必要的,把重要的业务放在高优的位置上,做到资源最大利用,才能实现利润的最大化,从而做到基业长青。

Flux 有个flatMapSequential方法,它能完美解决这个问题,看看它的注释:

Transform the elements emitted by this Flux asynchronously into Publishers, then flatten these inner publishers into a single Flux, but merge them in the order of their source element.

将此Flux发出的元素异步地转换为 publisher,然后将这些内部 publisher 扁平化为单个Flux,但按照源元素的顺序合并它们。

如上图所示,总共有S1、S2、S3、S4按顺序的四个弹窗,会并行执行S1到S4,如果S1和S2没有数据,S3有数据,则会返回S3。

伪代码如下:

Flux<Map<String, Object>> monoFlux = Flux.fromIterable(serviceList)
				.flatMapSequential(serviceName -> {
					    
							})
							.onErrorContinue((err, i) -> {
                  // 某个service异常或者无数据,继续执行
							});
				})
				.onErrorContinue((err, i) -> {
          // 服务异常,继续执行
				});
Mono<Map<String, Object>> mono = monoFlux.elementAt(0, Maps.newHashMap());        

这里就是异步执行所有弹窗service,运行过程中某个弹窗异常或者无数据返回,则继续下一个。通过monoFlux.elementAt(0, Maps.newHashMap())获取第一个有数据的弹窗。

4 重构效果

4.1 后端指标

相比于原来的后端系统,所有接口耗时都有大幅度降低,:

  • 头部身份信息接口响应速度提升:26%。
  • 卡片各业务线入口接口响应速度提升:87%。
  • 弹窗和浮标接口响应速度提升:146%。

经过 flatMapSequential 编排弹窗之后,耗时从220ms,降到160ms,绝对值下降了60ms,下降了 28%;

4.2 新需求开发和维护

新需求开发更快,QA 测试更快。

原来开发一个弹窗,需要考虑的事情很多:

  1. 开发的时候需要考虑代码放在哪个层级上,是否与其他弹窗有耦合,
  2. 弹窗优先级需要通过if-else实现,很容易出错;
  3. 弹窗自测很麻烦,需要注释调其他弹窗;
  4. QA 需要测试所有弹窗的优先级是否有问题;

现在开发一个弹窗,只需要增加一个service类,然后把service配置再优先级列表中即可。

4.3 其他

框架使用了响应式框架 Spring WebFlux,也支持本地启动,编写了service层和基础设施层的单测case,提升开发效率。

删除了原来的业务网关层,使用公司层面的网关系统,配置即生效;删除了原来业务网关中的业务逻辑代码,把相关逻辑移动到业务层中,解除了原来的多层之间的耦合关系。

现在各个service之前相互独立,异常不会相互影响。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/487644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

moment在vue的使用

第一步&#xff1a;安装moment npm install moment --save-dev第二步&#xff1a;在使用moment的地方引入moment import moment from "moment"; monent的方法&#xff1a; &#xff08;1&#xff09;moment([日期])&#xff1a; 获取当前日期或指定日期&#xff…

pytorch学习率设置——optimizer.param_groups、对不同层设置学习率、动态调整学习率。

文章目录 前言1、关于optimizer.param_groups2、设置学习率3、optim 提供的优化器 前言 我的需求&#xff1a;我需要在yolov7中更改其中一层的学习率&#xff0c;但yolov7的学习率是随着eporch的变化动态变化的。 1、关于optimizer.param_groups “param_groups” 是 Pytorch…

LeetCode1047. 删除字符串中的所有相邻重复项

1047. 删除字符串中的所有相邻重复项 给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一…

RabbitMQ 工作队列模型(任务队列)

任务模型 概念 ​ 当消息处理比较耗时的时候&#xff0c;可能生产消息的速度大于消费的速度&#xff0c;长此以往&#xff0c;就会导致消息堆积&#xff0c;无法及时处理&#xff0c;此时可以使用任务模型&#xff0c;当多个消费者绑定一个队列&#xff0c;共同消费其中的消息…

认识JSP

什么是JSP? JSP&#xff08;Java Server Pages&#xff09;是一种类似于HTML的标记语言&#xff0c;用于创建动态Web页面。与HTML不同的是&#xff0c;JSP页面中可以嵌入Java代码&#xff0c;由Web服务器在动态页面中生成HTML代码&#xff0c;从而实现Web应用程序的前端交互效…

scratch求和 中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析2023年3月

目录 scratch求和 一、题目要求 1、准备工作 2、功能实现 二、案例分析

node之Express

目录 Express简介 安装 创建基本的Web服务器 托管静态资源 以上述案例为基础访问静态资源的路径为&#xff1a;http://127.0.0.1:8080/xxx.html 托管多个静态资源目录 路由的概念 路由的匹配过程 模块化路由 模块化路由案例 中间件的概念 定义中间件函数例 全局生…

AI助阵,领先创新丨智能评价分析·数字员工,开启顶级消费者体验新篇章!

GPT-4作为人工智能时代发展道路上的里程碑&#xff0c;以其惊人的多模态大模型能力吸引了众多零售消费品牌的关注&#xff0c;利用AI技术解决客户复杂业务问题&#xff0c;成为推动行业提质增效的重要途径。实在智能是国内首个生成式AI标准编写单位&#xff0c;始终坚持AI赋能商…

各种常用字符编码详解【图文教程】,Unicode 是一个编码规范,并不是一个具体的编码

文章目录 常见编码的比较&#xff0c;各个编码中各字符占用(字节数):简体中文编码发展史&#xff0c;编码出现时间和涵盖范围UTF-8、unicode与GBK编码转化一问一答其他ASCII表 参考文档 常见编码的比较&#xff0c;各个编码中各字符占用(字节数): 编码英文中文&#xff08;简体…

数说热点 | 跟着《长月烬明》起飞,今年各地文旅主打的就是一个听劝

近日&#xff0c;随着热播剧《长月烬明》的爆火&#xff0c;蚌埠、宣城、敦煌等多个与剧情梦幻联动的宝藏城市被带飞&#xff0c;各地热心网友也纷纷催促自家文旅局赶紧“蹭飞”&#xff0c;《长月烬明》以一己之力打造了影视文旅融合的新样板。 仙偶剧特效天花板&#xff0c;…

SpringCloud------代码demo(二)

SpringCloud------代码demo&#xff08;二&#xff09; 编码实操 以订单——支付微服务模块作为基础&#xff0c;开始逐渐扩充 微服务架构编码构建 1.约定 > 配置 > 编码 2.IDEA新建project工作空间 3.Rest微服务工程构建 总父工程 POM project module 首先创建maven项…

FPGA入门系列14--VGA

文章简介 本系列文章主要针对FPGA初学者编写&#xff0c;包括FPGA的模块书写、基础语法、状态机、RAM、UART、SPI、VGA、以及功能验证等。将每一个知识点作为一个章节进行讲解&#xff0c;旨在更快速的提升初学者在FPGA开发方面的能力&#xff0c;每一个章节中都有针对性的代码…

06 - 3 事件驱动架构模式——EDA

何为EDA 事件驱动架构是一种异步分发事件的架构模式用于高扩展且低耦合的系统以事件为核心&#xff0c;一系列解耦的、单一功能的事件处理器 Notification 源系统发送消息通知其他系统状态改变接收方响应非必须发送 Event 逻辑与处理 Event 逻辑无依赖&#xff0c;独立变化解…

华为路由WS5200 四核版使用体验

文章目录 前言一、主界面和上网设置二、网络WIFI设置三、安全和系统总结 前言 其实我是看不上这种除了能上网&#xff0c;没任何用的东东的。除了上古时代用过类似的简单设备&#xff0c;已经十数年没再看一眼这种东西了&#xff0c;当然更不会去买这种东西&#xff0c;别误会…

vscode配置latex

reference&#xff1a;https://zhuanlan.zhihu.com/p/166523064 1 texlive卸载 找到texlive\2019\tlpkg\installer下的uninst.bat文件并点击运行。 删除环境变量 2 texlive安装 打开https://tug.org/texlive/acquire-iso.html点击下载iso文件 3 vscode 安装 4 latex插件…

Linux系统编程 多线程基础

文章目录 前言一、线程概念二、线程的创建三、线程的退出四、pthread_join函数总结 前言 本篇文章作为多线程的入门讲解将带大家先创建几个线程来感受一下什么是多线程&#xff0c;了解一下多线程到底有什么作用。 一、线程概念 线程&#xff08;Thread&#xff09;是程序执…

C++类与对象(二)——构造函数与析构函数

文章目录 一.类的默认6个成员函数二.构造函数1.引例2.构造函数的概念及特性 三.析构函数&#x1f60b;析构函数的特性 前言&#xff1a; 上篇文章初步认识了类以及类的相关知识&#xff0c;本篇将继续深入学习类与对象——类的默认6个成员函数&#xff1a; 一.类的默认6个成员函…

制造企业如何跨越大规模定制鸿沟?中国最大减速机企业的答案来了

导读&#xff1a;传统制造企业如何深度用云&#xff1f; 在中国制造向中国智造的转型中&#xff0c;长三角地区一直扮演着急先锋的角色。总部位于常州的江苏国茂减速机股份有限公司(简称国茂股份)&#xff0c;就是中国制造上云转型的典型代表。 国茂股份成立于1993年&#xff0…

Microelectronic学习章节总结(2)-- data path和control unit设计

文章目录 part1. Data path设计1.1 logic unit1.2 shifter1.3 adder1.4 comparator1.5 multiplier1.6 divider1.7 register file part2. Control unit设计part3. CPU SoC上的其它部件 (TODO&#xff1a;理解总结)3.1 总线AMBA&#xff08;parallel&#xff09; 3.2 Memorymemor…

[C++基础]-类和对象(下)

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正。 目录 一、深入学…