.NET-记一次架构优化实战与方案-底层服务优化

简介: .NET-记一次架构优化实战与方案-底层服务优化

前言

  

经过上一篇《.NET-记一次架构优化实战与方案-前端优化》与大家分享了对页面加载优化的心得和经历。虽然优化前端的性能效率,但是由于底层服务的触发方式,根本性问题仍然存在的。


问题分析

  

在本系列第一篇文章我们提到,底层服务是一系列的JOB,那么问题主要存在以下两点:

  • 代码冗余
  • 时效低


代码冗余


例如:

  • 领奖方法不统一,一次性的写一套,可循环的又写一套。



image.png


  • 每个类型任务都需要独自的实现该任务的完成任务 JOB 与发放奖励 JOB

  

image.png


  

以上问题直接导致了后续开发、日常维护成本过高。

 

因为早期开发时缺少沟通,没有封装成公共的方法,而JOB每个开发人员都单独实现了一套,当然他们未必那么蠢,可能是某个先完成了,后续的先前COPY后修改一下。

  

试想一下,没新增一个任务类型就要重写一份完成任务的JOB和自动发奖的JOB,这是一个N*2的工作量。如果后续有个规则改了,那是不是每个JOB都跑去改一次?


时效低


  

由于任务完成是由定时服务根据业务数据源定时批量执行:

  1. 定时任务频率低,则导致数据集中过多处理


  1. 定时任务频率高,则导致 Job 对数据库的压力剧增或者 99%的无用查询,无结果并不代表不会造成消耗,因为查询都是要经过下面步骤,建立连接、词法分析、语法分析、选取执行方式、到存储引擎读取数据、返回客户端。


  1. 随着数据源数据量增加,查询耗时也逐渐增加


  以上问题直接导致了,用户完成任务后无法及时查看完成任务并领奖,如需及时查看状态需要在展示页面逻辑额外添加查询后更新的操作


优化实施


流程图


image.png


方案一(抽离公共点)


目的:减少代码冗余,提高可维护性,提高后续新任务的开发效率


具体实施:从业务流程图可以直观的观察出,整个底层业务流程基本一致,只有数据源上的差异,因此可以从以下方面入手优化:


  1. 抽离出唯一的自动发奖 Job,发奖JOB基于【任务完成结果】进行发奖,逐步去除原个性任务自动发奖 Job。


  1. 自动发奖与手动领奖的具体执行流程一致的,可将其封装成公共方法。分别由H5领奖按钮与领奖JOB进行调用。


  1. 任务完成 Job 使用模板模式,由基类统一业务执行流程,每个任务类型只需继承任务父类,再由子类重写查询数据源。当然也可以简单粗暴点不使用设计模式,把查询数据源后的完成任务的方法封装成一个公共方法供不同任务类型的JOB去调用。


从我角度来看,这种方案处理没有任何坏处的。如果真要计较,那就是所涉及的JOB都得改,但是从上述分析出,如果真要重构,工作量也是在写父类模板和封装公共方法,查询数据源代码是可以复用的。但是带来的收益就是良好的扩展性和可维护性。


方案二(业务埋点)


该方案主要对任务参与的触发方式变更,不同的任务类型由对应的业务最终流程的完成点进行发送队列消息,由任务服务(消费端)订阅相关消息执行任务完成流程。


通俗讲叫业务埋点,当然也可以称其为事件驱动。


架构图


image.png


事件驱动架构

  

服务之间是高内聚的,它们的耦合度应该很低,当服务需要相互协作时,假设服务“A”需要触发服务“B”中的某段逻辑,平常的方式是让服务A直接串行调用服务B中的某个方法。但前提是A必须知道B的存在,如果B出异常了就会影响到A的正常执行。

这样它们之间就是强耦合的,A必须依赖于B了。这样使得系统更难以维护与扩展,因此引入事件驱动来降低服务间的耦合度

  

当服务A需要触发服务B的逻辑时,不要直接调用它,我们可以将消息发送到消息队列,由服务B订阅相应的队列,并在事件发生时异步执行操作。这意味着服务A、B都依赖于中间件消息队列,但他们之间将不需要知道彼此的存在,因此它们之间于此解耦。

如果将此方案引入我们的活动业务中,收益主要分为短期与长期。


短期收入


  1. 减少无用重复的查询:无需重复查询数据源,只需由业务端推送可靠的消息,减少对数据库的多余压力


  1. 用户体验良好:时效性高,原集中时间点批量处理,现分散到不同的时间点执行


  1. 伸缩性优秀:RabbitMQ 自带负载均衡功能,在消费能力不足情况下,可以做到业务无损的动态横向扩展。虽然JOB也可以做到,但是需要对物理表做特殊处理,增加中间状态


长期收益

  

事件驱动架构长期收益比短期要大,以RabbitMQ与投资业务举个例子。初期完成核心业务投资理财,投资后我们需要APP通知用户,在此投资无论成功与否都往RabbitMQ发送消息,投资成功RouteKey=TZ.SUCCESS,投资失败RouteKey=TZ.FAILE。APP通知服务订阅队列NoticeQueue绑定RouteKey=TZ.#,其中包括成功和失败的消息,服务根据消息状态发送APP通知。哪天业务拓展需要增加投资成功积分,只需要添加积分服务订阅队列IntegrationQueue并绑定RouteKey=TZ.SUCCESS消息即可。接着又多了任务活动、信用消费等,如此类推。


由此可见,如同广播一样,我不知道你们谁要,如果你们需要的就好好监听着,不需要就当耳旁风。


复杂点


分布式事务

  

既然我们使用了RabbitMQ中间件,那么分布式事务会选择基于可靠消息的方案:

  1. 消息可靠性:保证业务端的本地事务执行成功的同时也保证队列消息正常发布


  1. 消息补偿:保证消息消费端的正常消费,如果消费失败后需重新投递,如果重新投递失败可由补偿服务补偿发送。


  1. 幂等处理:因存在自动重试机制,避免重复执行业务导致的意外问题。


模型图

  image.png


  

这种基于可靠消息的方案,也叫本地消息事务表的方案,可根据自己情况自研解决,


也可使用类似开源分布式事务框架 CAP 解决。https://github.com/dotnetcore/CAP

相关实践学习
快速体验阿里云云消息队列RocketMQ版
本实验将带您快速体验使用云消息队列RocketMQ版Serverless系列实例进行获取接入点、创建Topic、创建订阅组、收发消息、查看消息轨迹和仪表盘。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
目录
相关文章
|
3月前
|
消息中间件 负载均衡 中间件
⚡ 构建真正的高性能即时通讯服务:基于 Netty 集群的架构设计与实现
本文介绍了如何基于 Netty 构建分布式即时通讯集群。随着用户量增长,单体架构面临性能瓶颈,文章对比了三种集群方案:Nginx 负载均衡、注册中心服务发现与基于 ZooKeeper 的消息路由架构。最终选择第三种方案,通过 ZooKeeper 实现服务注册发现与消息路由,并结合 RabbitMQ 支持跨服务器消息广播。文中还详细讲解了 ZooKeeper 搭建、Netty 集群改造、动态端口分配、服务注册、负载均衡及消息广播的实现,构建了一个高可用、可水平扩展的即时通讯系统。
292 0
|
3月前
|
文字识别 运维 监控
架构解密|一步步打造高可用的 JOCR OCR 识别服务
本文深入解析了JOCR OCR识别服务的高可用架构设计,涵盖从用户上传、智能调度、核心识别到容错监控的完整链路,助力打造高性能、低成本的工业级OCR服务。
153 0
架构解密|一步步打造高可用的 JOCR OCR 识别服务
|
6月前
|
中间件 Go
Golang | Gin:net/http与Gin启动web服务的简单比较
总的来说,`net/http`和 `Gin`都是优秀的库,它们各有优缺点。你应该根据你的需求和经验来选择最适合你的工具。希望这个比较可以帮助你做出决策。
239 35
|
6月前
|
数据采集 自然语言处理 JavaScript
Playwright多语言生态:跨Python/Java/.NET的统一采集方案
随着数据采集需求的增加,传统爬虫工具如Selenium、Jsoup等因语言割裂、JS渲染困难及代理兼容性差等问题,难以满足现代网站抓取需求。微软推出的Playwright框架,凭借多语言支持(Python/Java/.NET/Node.js)、统一API接口和优异的JS兼容性,解决了跨语言协作、动态页面解析和身份伪装等痛点。其性能优于Selenium与Puppeteer,在学术数据库(如Scopus)抓取中表现出色。行业应用广泛,涵盖高校科研、大型数据公司及AI初创团队,助力构建高效稳定的爬虫系统。
314 2
Playwright多语言生态:跨Python/Java/.NET的统一采集方案
|
4月前
|
存储 缓存
.NET 6中Startup.cs文件注入本地缓存策略与服务生命周期管理实践:AddTransient, AddScoped, AddSingleton。
记住,选择正确的服务生命周期并妥善管理它们是至关重要的,因为它们直接影响你的应用程序的性能和行为。就像一个成功的建筑工地,工具箱如果整理得当,工具选择和使用得当,工地的整体效率将会大大提高。
164 0
|
7月前
|
消息中间件 人工智能 监控
文生图架构设计原来如此简单之分布式服务
想象一下,当成千上万的用户同时要求AI画图,如何公平高效地处理这些请求?文生图/图生图大模型的架构设计看似复杂,实则遵循简单而有效的原则:合理排队、分工明确、防患未然。
239 14
文生图架构设计原来如此简单之分布式服务
|
10月前
|
存储 JavaScript 开发工具
基于HarmonyOS 5.0(NEXT)与SpringCloud架构的跨平台应用开发与服务集成研究【实战】
本次的.HarmonyOS Next ,ArkTS语言,HarmonyOS的元服务和DevEco Studio 开发工具,为开发者提供了构建现代化、轻量化、高性能应用的便捷方式。这些技术和工具将帮助开发者更好地适应未来的智能设备和服务提供方式。
基于HarmonyOS 5.0(NEXT)与SpringCloud架构的跨平台应用开发与服务集成研究【实战】
|
12天前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
3月前
|
缓存 Cloud Native Java
Java 面试微服务架构与云原生技术实操内容及核心考点梳理 Java 面试
本内容涵盖Java面试核心技术实操,包括微服务架构(Spring Cloud Alibaba)、响应式编程(WebFlux)、容器化(Docker+K8s)、函数式编程、多级缓存、分库分表、链路追踪(Skywalking)等大厂高频考点,助你系统提升面试能力。
156 0

热门文章

最新文章