0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

BFF层聚合查询服务异步改造及治理实践

京东云 来源:jf_75140285 作者:jf_75140285 2024-08-20 15:24 次阅读

首先感谢王晓老师的[接口优化的常见方案实战总结]一文总结,恰巧最近在对稳健理财BFF层聚合查询服务优化治理,针对文章内的串行改并行章节进行展开,分享下实践经验,主要涉及原同步改异步的过程、全异步化后衍生的问题以及治理方面的思考与改进。 希望通过分享这些经验,能够对大家的工作有所启发和帮助。如果有任何问题或建议,请随时提出。 感谢大家的关注和支持!

一、问题背景

将不同理财产品(如基金、券商、保险、银行理财等)针对不同投放渠道人群进行个性化商品推荐,每个渠道或人群看到的商品或特性数据又各不相同,为方便渠道快速对接,由BFF层统一对所有数据进行聚合下发,因此BFF层聚集依赖了大量底层原子服务,所以主要问题是在依赖大量上游接口的场景下保障TP99、以及可用率。

案例:

以其中比较典型的商品推荐接口为例,需要依赖本地商品池缓存、算法推荐服务、商品基础信息服务、持仓查询服务、人群标签服务、券配置服务,可领用券服务、其他数据服务ServN……等等,其中大部分上游原子接口对单次批量查询支持有限,所以极端情况,单个推品接口单次推荐1-n个推品,每个商品如果要绑定10个动态属性,至少需要发起(1~n)*10次io调用。

改造前的流程和问题:

流程:

wKgZombERICAGYHFAAKgzRNY5gg529.png

问题:

▪一是逻辑流程强耦合,很多上下游服务强同步依赖;

▪二是链路较长,其中某个上游服务不稳定时很容易造成整体链路失败。

改造后的流程和实现的目标:

流程:

wKgaombERIKAMZ1PAAYfE7O_Wg4591.png

目标:

▪改造目标也很明确,就是对现有逻辑改造,尽可能增加弱依赖比例,一是方便异步提前加载,二是弱依赖代表可摘除,为降级操作奠定基础,减少因某个链路抖动影响整体链路失败;

初步改造后的新问题【【重点解决】】:

▪逻辑上解耦比较简单,无非就是前置参数或冗余加载,本次不展开探讨;

▪技术上改造前期异步逻辑主要是采用@Async("tpXXX")标注,这也是最快捷实现的方式,但也存在以下几个问题,主要是涉及治理方面:

1. 随着项目和人员不断迭代,造成@Async注解满天飞;

2. 不同人员在不熟悉其他模块的情况下,无法界定不同线程池的是否可公用,大多都会采用声明新的线程池,造成线程池资源泛滥;

3. 部分调用场景不合理造成@Async嵌套过多或注解失效问题;

4. 降级机制重复代码太多,需要频繁手动声明各种降级开关;

5. 缺少统一的请求级别的缓存机制,虽然jsf已经提供了一定程度的支持;

6. 线程池上下文传递问题;

7. 缺少线程池状态的统一监控报警,无法观测实际运行过程中的每个线程池状态,可能每次都是拍脑袋觉设置线程池参数。

二、整体改造路径

切入点:

鉴于大部分项目都会封装单独的io调用层,比如 com.xx.package.xxx.client,所以以此为切入点进行重点改造治理。

最终目标:

实现、应用简单,对老代码改造友好,尽可能降低改造成本;

1. 抽象io调用模板,统一io调用层封装规范,标准化io调用需要的增强属性声明并提供默认配置,如所属线程池分配、超时、缓存、熔断、降级等;

2. 优化@Async调用,所有io异步操作统一收缩至io调用层,在模板层实现回调机制,老代码仅继承模板即可实现异步回调;

3. 请求级别的缓存实现,默认支持r2m;

4. 请求级别的熔断降级支持,在上游故障时使服务实现一定程度的自治理;

5. 线程池集中管理,对上下文自动传递MDC参数提供支持;

6. 线程池状态自动可视化监控、报警实现;

7. 支持配置中心动态设置。

具体实现:

1. io调用抽象模板

模板主要作用是进行规范和增强,目前提供两种模板,默认模板、缓存模板,核心思想就是对io操作涉及的大部分行为进行声明,比如当前服务所属线程池分组、请求分组等,由委托组件按照声明的属性进行增强实现,示例如下:

主要是提供代码级别的默认声明,从日常实践看大部分采用开发时的代码级别的配置即可。

wKgZombERIOAacbiAAqVuPgi5l8702.png

.

wKgaombERIWAccbsAAYpIbJ-Qeg025.png

2. 委托代理

此委托属于整个执行过程的桥接实现,io封装实现继承抽象模板后,由模板创建委托代理实例,主要用于对io封装进行增强实现,比如调用前、调用后、以及调用失败自动调用声明的降级方法等处理。

可以理解为:模板专注请求行为,委托关注对象行为进行组合增强。

wKgZombERIiARrcaAA_4etxMWiY133.png

3. 执行器选型

基于前面的实现目标,减少自研成本,调研目前已有框架,如 hystrix、sentinel、resilience4j,由于主要目的是期望支持线程池级别的壁舱模式实现,且hystrix集成度要优于resilience4j,最终选型默认集成hystrix,备选resilience4j, 以此实现线程池的动态创建管理、熔断降级、半连接重试等机制,HystrixCommander实现如下:

wKgaombERIqAcvqBAAg6e3cYyOk550.png

4. hystrix 适配 concrete 动态配置

1、继承concrete.PropertiesNotifier, 注册HystrixPropertiesNotifier监听器,缓存配置中心所有以hystrix起始的key配置;

2、实现HystrixDynamicProperties,注册ConcreteHystrixDynamicProperties替换默认实现,最终支持所有的hystrix配置项,具体用法参考hystrix文档。

wKgZombERIyAEZpSAAfmRxEwaJI080.png

5. hystrix 线程池上下文传递改造

hystrix已经提供了改造点,主要是对HystrixConcurrencyStrategy#wrapCallable方法重写实现即可,在submit任务前暂存主线程上下文进行传递。

wKgZombERI2ATqfuAAS61OwPqEE133.png

6. hystrix、jsf、spring注册线程池状态多维可视化监控、报警

主要依赖以下三个自定义组件,注册一个状态监控处理器,单独启动一个线程,定期(每秒)收集所有实现数据上报模板的实例,通过指定的通道实现状态数据推送,目前默认使用PFinder上报:

▪ThreadPoolMonitorHandler 定义一个线程状态监控处理器,定期执行上报过程;

▪ThreadPoolEndpointMetrics 定义要上报的数据模板,包括应用实例、线程类型(spring、jsf、hystrix……)、类型线程分组、以及线程池的几个核心参数;

▪AbstractThreadPoolMetricsPublisher 定义监控处理器执行上报时依赖的通道(Micrometer、PFinder、UMP……)。

例如以下是hystrix的状态收集实现,最终可实现基于机房、分组、实例、线程池类型、名称等不同维度的状态监控:

wKgaombERI-AX4EqAAeQ0F382gM876.png

wKgZombERJGAVLeJAAnxG305wPc922.png

wKgaombERJKAA43XAASI9f0_PQs347.png

PFinder实际效果:支持不同维度组合查看及报警

wKgZombERJSAL8h8AAObNtDM4nk932.png

wKgaombERJWAAUWeAAdapwpU7GI019.png

wKgZombERJiALAosAARqLtV9fao380.png

7. 提供统一await future工具类

由于大部分调用是基于列表形式的异步结果List>、Map>,并且hystrix目前暂不支持返回CompletableFuture,方便统一await,提供工具类:

wKgaombERJuAAy-vAAWwBwLbBgg133.png

8. 其他小功能

1、除了sgm traceId支持,同时内置自定义的traceId实现,主要是处理sgm在子线程内打印traceId需要在控制台手动添加监控方法的问题以及提供对部分无sgm环境的链路Id支持,方便日志跟踪;

2、比如针对jsf调用,基于jsf过滤器实现跨应用级别的前后请求id传递支持;

3、默认增加jsf过滤器实现日志打印,同时支持provider、consume的动态日志打印开关,方便线上随时开关jsf日志,不再需要在client层重复logger.isDebugerEnabled();

4、代理层自动上报io调用方法、fallback等信息至ump,方便监控报警。

日常使用示例:

1. 一个最简单的io调用封装

仅增加继承即可支持异步回调,不重写线程池分组时使用默认分组。

wKgZombERJyALnyBAAN4-9CU0mI221.png

2. 一个支持请求级别熔断的io调用封装

默认支持的熔断级别是服务级别,老服务仅需要继承原请求参数,实现FallbackRequest接口即可,可防止因为某一个特殊参数引起的整体接口熔断。

wKgaombERJ2ARx5zAAD8FecVDlg436.png

wKgaombERJ6ACyprAAdYJk735BI124.png

3. 一个支持请求级别缓存、接口级别熔断降级、独立线程池的io调用封装

wKgZombERKCAK_YGAAbvbXhODSc001.png

4. 上层调用,实际效果

1、直接将一个商品列表转换成一个异步属性绑定任务;

2、利用工具类await List>;

3、在上层无感知的状态下,实现线程池的管理、熔断、降级、或缓存逻辑的增强,且可根据pfinder监控的可视化线程池状态,通过concrete实时调整线程池及超时或熔断参数;

4、举例:比如某接口频繁500ms超时,可通过配置直接打开短路返回降级结果,或者调低超时为100ms,快速触发熔断,默认10s内请求总数达到20个,50%失败时打开断路器,每隔5s半链接重试。

wKgaombERKGAcAJPAALybjYxvCU379.png

wKgZombERKSAbfLzAAp8h25IU3k166.png

三、最后

本篇主要是思考如何依赖现有框架、环境的能力,从代码层面系统化的实现相关治理规范。

最后仍引用王晓老师文章结尾来结束

接口性能问题形成的原因思考我相信很多接口的效率问题不是一朝一夕形成的,在需求迭代的过程中,为了需求快速上线,采取直接累加代码的方式去实现功能,这样会造成以上这些接口性能问题。 变换思路,更高一级思考问题,站在接口设计者的角度去开发需求,会避免很多这样的问题,也是降本增效的一种行之有效的方式。 以上,共勉!

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    8279

    浏览量

    150044
  • 代码
    +关注

    关注

    30

    文章

    4674

    浏览量

    67816
收藏 人收藏

    评论

    相关推荐

    服务网格DPU卸载解决方案

    服务网格(Service Mesh)是微服务架构中的一种重要技术,它主要处理服务之间的通信,为服务间的信息交换提供更安全、更快速且更可靠的基础设施
    的头像 发表于 09-20 16:25 135次阅读
    <b class='flag-5'>服务</b>网格DPU卸载解决方案

    如何利用python和API查询IP地址?

    在Python中,直接查询IP地址的地理位置或详细信息(如所属国家、城市等)通常需要依赖外部API服务,因为Python标准库本身不提供直接查询IP地址地理位置的功能。以下是一个使用requests
    发表于 08-28 11:55

    中国高速服务区加油站应用触摸屏查询一体机智慧便民

    随着数字化科技的飞速发展,OBOO鸥柏触摸屏查询一体机在高速公路服务区、加油站等交通领域发挥着越来越重要的作用。服务区展厅展馆应用可以提供包括自驾车导航、餐饮连锁、旅游景区、娱乐、商务、教育、信息
    的头像 发表于 07-29 11:15 164次阅读
    中国高速<b class='flag-5'>服务</b>区加油站应用触摸屏<b class='flag-5'>查询</b>一体机智慧便民

    AT+CIPSERVERMAXCONN查询/设置服务器允许建立的最大连接数是几个呢?

    AT+CIPSERVERMAXCONN查询/设置服务器允许建立的最大连接数是几个呢?
    发表于 06-27 08:07

    分库分表后复杂查询的应对之道:基于DTS实时性ES宽表构建技术实践

    1 问题域 业务发展的初期,我们的数据库架构往往是单库单表,外加读写分离来快速的支撑业务,随着用户量和订单量的增加,数据库的计算和存储往往会成为我们系统的瓶颈,业界的实践多数采用分而治之的思想:分库
    的头像 发表于 06-25 18:30 723次阅读
    分库分表后复杂<b class='flag-5'>查询</b>的应对之道:基于DTS实时性ES宽表构建技术<b class='flag-5'>实践</b>

    聚合物锂电池型号表及容量查询

    聚合物锂电池型号表及容量查询
    发表于 06-22 10:55 0次下载

    ClickHouse内幕(3)基于索引的查询优化

    ClickHouse基于索引的查询算子优化方式。 在整个查询计划中Sort、Distinct、聚合这3个算子相比其他算子比如:过滤、projection等有如下几个特点:1.算子需要再内存中保存状态
    的头像 发表于 06-11 10:46 763次阅读
    ClickHouse内幕(3)基于索引的<b class='flag-5'>查询</b>优化

    SQL改写消除相关子查询实践

    GaussDB (DWS) 根据子查询在 SQL 语句中的位置把子查询分成了子查询、子链接两种形式。
    的头像 发表于 12-27 09:51 370次阅读

    金融服务急需数据改造

    金融服务越来越注重实时互动体验,重构关键业务流程,从数据入手该怎么做?文章速览:数字化转型正在颠覆银行与金融业金融服务的未来RedisEnterprise赋能实时金融应用一、数字化转型正在颠覆银行
    的头像 发表于 12-23 08:04 720次阅读
    金融<b class='flag-5'>服务</b>急需数据<b class='flag-5'>层</b><b class='flag-5'>改造</b>

    华为云 CodeArts 开源治理服务,解锁软件安全新标准

    在数字化时代,软件的安全性日益受到关注,而开源软件的快速发展也带来了新的挑战。再次背景下,华为云开源治理服务华为云开源治理服务 CodeArts Governance 应运而生,不仅打
    的头像 发表于 12-10 21:00 857次阅读
    华为云 CodeArts 开源<b class='flag-5'>治理</b><b class='flag-5'>服务</b>,解锁软件安全新标准

    主机服务器选择:关键因素与最佳实践

    在数字化时代,主机服务器的选择对于任何企业都是至关重要的。无论是大型公司还是初创企业,都需要一个稳定、高效且安全的服务器来支持其业务运行。然而,面对市场上众多品牌和型号的服务器,如何选择最适合自己需求的主机
    的头像 发表于 11-21 10:55 345次阅读

    普通三相异步电动机可以当作变频电机使用吗?

    有一台400kw10000v的三相异步电机。由于工艺改造。需要增加变频器调速控制。但原有电机为普通三相异步电机。如果增加变频器的话、是否需要更换电机(成本太高了)
    发表于 11-13 07:06

    6PCB叠设计指南

    布线。如果您以前从未使用过6电路板,或者遇到过难以解决的此类叠EMI问题,请继续阅读以了解一些6PCB设计指南和最佳实践
    发表于 10-16 15:24 2033次阅读
    6<b class='flag-5'>层</b>PCB叠<b class='flag-5'>层</b>设计指南

    一图看懂CodeArts Governance 三大特性,带你玩转开源治理服务

    华为云开源治理服务CodeArts Governance是针对软件研发提供的一站式开源软件治理服务,凝聚华为在开源治理上的优秀
    的头像 发表于 10-13 17:45 365次阅读
    一图看懂CodeArts Governance 三大特性,带你玩转开源<b class='flag-5'>治理</b><b class='flag-5'>服务</b>

    华为云发布 CodeArts Governance 开源治理服务,开源使用更安心

    2023 年 9 月 14 日,华为云正式发布 CodeArts Governance 开源治理服务。这是一款针对软件研发提供的一站式开源软件治理服务,将华为在开源
    的头像 发表于 10-12 15:41 374次阅读
    华为云发布 CodeArts Governance 开源<b class='flag-5'>治理</b><b class='flag-5'>服务</b>,开源使用更安心