大报文之道:优化策略与实践

news/发布时间2024/5/3 20:29:10

写在前面

在做正常的需求开发时,当我们提供了一个接口或是调用别人接口时,我们需要考虑接口除了正常的逻辑处理外,还需要考虑接口能接收报文的上限,性能,响应时间等一系列非功能性需求。如果不注意这些问题,就可能在某一天的某个时刻收到一系列系统告警,严重者甚至导致系统不可用,引发线上事故。如涉及明细列表相关的接口中没考虑明细的上限,某一时刻上游下发了一个大明细从而可能就引发了上述的问题。这就是日常所说的大报文,其特点就是单次请求的数据量特别大,超出了系统正常的处理能力,需要耗费较长的时间才能处理完成。面对此类非功能性需求,在日常的开发中如何去避免和解决呢,今天主要带来的是主子模型下,明细行过大的处理。

一、识别大报文

大报文一般来源于批量接口或单个接口中入参为主子模型的接口,如果是消息队列,则是一次发送的消息中消息报文里发送了多条业务消息或是消息的报文结构也为主子模型的消息导致。

批量接口模型
Response<List<T>> method(List<T> list);单个接口入参为主子模型
T method(OrderInfo orderInfo);class OrderInfo{List<OrderDetailInfo> orderDetailInfoList;
}class OrderDetailInfo{
}

对于批量接口或是消息队列里发送了多条业务消息的情况在这不做过多阐述,通常的逻辑是改为分批调用或分批发送消息就可以。但对于主子模型的报文,如果是正常的业务,则不能要求业务不要这么来下发,尤其是TOB类业务,因此需要从技术的角度加以解决。

 

二、解决大报文

这里主要讨论针对单个接口,里面的参数是主子模型的场景,因这类场景在日常的开发中最常见,用得很普遍。

 

 

 

第一点,先从AppA侧看可优化的点:

从调用方AppA的角度,如果传入的消息报文过大,导致AppB处理失败,那么对AppA来说也是失败,为了确保调用的成功,从AppA的角度看,对其可做如下一些优化。

首先,AppA在调用AppB时,可以和AppB约定接口的超时时间。超时后,AppA需要有重试机制,而对应的AppB需要保证接口执行的幂等性。在超时时间的设置上,如果大报文是个极少发生的场景,还可以考虑对超时时间进行动态设置,针对大报文的请求,把相应的超时时间适当加长,确保调用的成功。

其次,为了保证数据报文能快速达到AppB,AppA在请求调用AppB时,可以对报文进行压缩,确保网络传输能以最快的速度把数据报文发送到AppB。

 

 

 

 

第二点,从AppB侧看可优化的点:

而从AppB侧来看,需要从业务逻辑里分析耗时的逻辑,一般来说这个分析比较靠谱的是压测,搭建一套与线上环境类似的环境,模拟线上场景进行压测,压测出耗时的业务逻辑,针对耗时的业务逻辑进行优化。在这里由于我们的入参是主子模型的,按经验来讲,耗时点一般位于处理明细的逻辑里,所以可以重点关注明细处理相关逻辑。

首先,AppB在接收到请求后,对请求报文中的参数做基本的业务逻辑校验,校验通过后,为了能快速的响应调用方,可以把整个业务处理逻辑转入异步进行处理,确保调用方不超时。业务逻辑进入异步处理后还可能处理的时间比较耗时,此时可根据业务的时效性再进行处理。

其次,在AppB内,如果通过压测最后的耗时的确是在对明细的处理上,那么可以考虑对明细进行分批处理,不同的处理逻辑对于分批大小后得到的处理时长是不一样的,需要经过多轮调整参数的压测,找到适合自己业务逻辑的参数值。在我经历的大明细保存数据库实践中,不分批一次直接保存1万条明细到数据库与分批保存数据库及每批次的大小不同最终导致所有明细保存完数据库的时间也是有天壤之别的。

 

  保存方案 每次保存条数(条) 平均耗时(毫秒)
10000条 一次保存 10000 159005
10000条 分批保存 200 15363
10000条 分批保存 500 18720

再次,在确定了耗时的业务逻辑后,针对耗时的业务逻辑可以启用多线程处理。在使用多线程时,核心线程数的设置建议与CPU的核数相同,确保有较好的性能输出。在本文所述的此类场景中,用到了多线程就需要对批量的明细进行分批,结合上面说的不同的批次大小会有不同的性能表现,所以设置的参数建议还是通过压测获取,确保参数的最优。

 


 

还是刚才保存10000条明细进数据库的案例,在使用多线程并结合分批保存的方案后,在相同硬件及网络条件,单次保存的耗时降低至1秒左右,最终所有明细保存完成的总耗时在10秒左右,此时应用的压力有所上升,但数据库的压力几乎没什么变化。

 

数据条数 保存方案 每次保存条数(条) 单次平均耗时(毫秒) 总耗时(毫秒)
10000条 分批+多线程保存 100 1103 10184

三、经验沉淀

在进行大报文优化时,没有一个通用可行的方法能解决各类问题,本文阐述的仅是在主子模型下,明细过大的一些可行方法及在实际中的实践。而在实际的开发中,结合具体的业务场景,大报文的处理会更加复杂,需要结合具体业务具体分析。但我们日常积累的分批,多线程,异步,调整超时时间等手段都可在解决大报文中发挥各自应有的作用,可结合具体场景进行多种技术手段的综合运用,最终把大报文场景消灭在上线前,确保生产环境的稳定、可靠。

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

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

FlinkSQL 实时同步 MySQL

本文主要介绍了使用 FlinkSQL 实现 MySQL 数据的实时同步。准备工作MySQL 数据库(version: 5.7.25),注意,MySQL 数据库版本必须大于 5.6,否则不支持。开启 MySQL 的 log-bin: [mysqld] # Binary Logging. log-bin=mysql-bin server-id=1Flink (version : 1.15.4)添加 fli…

FlinkSQL 实时数据同步

准备工作MySQL 数据库(version: 5.7.25),注意,MySQL 数据库版本必须大于 5.6,否则不支持。开启 MySQL 的 log-bin: [mysqld] # Binary Logging. log-bin=mysql-bin server-id=1Flink (version : 1.15.4)添加 flink-connector-jdbc-1.15.4.jar 和 flink-sql-connector-mys…

关于虚拟机内存和JVM内存设置的思考

关于虚拟机内存和JVM内存设置的思考背景 最近有同事总问JVM的设置问题. 之前总结过不少. 但是感觉没法讲对方说服 当然了, 自己能力有限, 只能自说自话. 现在这个就是留存一个底稿. 希望能人能帮忙解释关于内存和CPU的观点 CPU的能力有上限. 一般情况下不建议让CPU处于高峰作业…

04-drf视图层详细

drf的request请求 这里的request请求是基于APIView的,也就是新的request 正常情况下,request请求分为:urlcoded、json、form-data,可以控制只接受哪一个请求导入模块 from rest_framework.parsers import JSONParser, MultiPartParser, FormParser模块 描述 请求JSONParser…

缓存数据“消失”之谜

吃一堑,长一智。吃一堑,长一智。“邪门!真是邪门!”自从踏入 Go 的领域之后,奇事怪事接连不断。很多看上去似乎没啥问题的代码,可就是有问题,可怎么也看不出问题所在。问题背景 事情是这样的:有两个流程和一个缓存数据: 流程一:接收 kafka 数据,解析模型数据,并存入…

Python调用微信OCR识别文字和坐标

原理 在看雪看到一篇文章:逆向调用QQ截图NT与WeChatOCR-软件逆向。里面说了怎么调用微信和QQ本地的OCR模型,还有很详细的分析过程。 我稍微看了下文章,多的也看不懂。大概流程是使用mmmojo.dll这个dll来与WeChatOCR.exe做通信的,也是用它来启动和关闭WeChatOCR.exe进程的。…