浅谈.NET微服务架构的演变

服务架构的演变

单体架构=>分布式架构=>SOA架构=>微服务架构=>Service Mesh=>Cloud Native

单体架构/垂直架构

image

分布式架构

image

SOA架构

image

SOA是一种软件设计理念与架构模式,核心是将系统拆分为一系列的松耦合,可复用,可独立部署的"单个服务",通过标准化接口让各个服务之间协同工作。
本质上是为了解决单体架构(所有功能都放一起)的紧耦合,难复用问题。

什么是ESB?为什么需要它?

在没有ESB的系统中,系统与系统之间的通信往往是点对点直连,比如服务A需要调用服务B/C,就必须适配B/C的协议,比如HTTP,TCP,JMS等,并且格式也各不相同(JSON/XML/CSV),
当某一个服务发生变更,比如参数调整,协议变化,都会导致依赖它的服务也需要同步适配。

所以延伸出了ESB,它作为一个adapter,起到了承上启下的作用,所有服务只需要连接到ESB,由ESB提供统一的协议转换,格式转换,动态路由等功能。

微服务架构

image

需要注意一点,微服务架构是分布式架构的一种轻量级落地,它们之间是接口与实现类的关系。

微服务为什么又不需要ESB?

  1. 性能瓶颈
    所有服务之间的通信都由ESB统一处理,很有可能造成ESB的处理能力不足。
  2. 单点故障
    原因同上,当ESB发生故障时,所有依赖ESB的服务均会被拖累,尽管可以通过集群化缓解,但风险依旧存在
  3. 与微服务理念冲突
    微服务理念是“轻量,去中心化”,而ESB则是强调中心化,基础功能大而全。

微服务核心功能

服务发现

为什么需要服务发现?

  1. 服务实例的动态变化
    在水平架构中,我们的服务集群往往是通过Nginx/IIS的静态配置来实现节点的增/减。加上节点少,因此,每次修改节点配置都是人工修改。
    而微服务架构天然的动态性与不确定性,服务实例通常需要动态扩容/缩容,故障重启,滚动升级等特点,因此服务示例的网络地址是随时变化的,加上微服务化之后,服务实例呈指数级增加,再由人工干预就不明智了。
  2. 分布式环境的网络复杂性
    服务实例可能步骤在不同的物理机,虚拟机,容器中,将它们整合非常麻烦,需要一个能够屏蔽底层细节,提供统一入口的组件,让调用方无需关心目标服务具体位置
  3. 抽象网络地址
    水平架构中,我们常常依赖IP+端口的形式来确定服务实例,在微服务架构中,使用Service-Name来提供一个逻辑名称
  4. 去除不可用实例
    通过心跳访问实例提供的Healthcheck,当某个实例故障时,自动去除,避免访问到不可用节点。

简单来说,服务发现解决的是微服务实例之间的动态通信问题,主要用于内部服务间的调用。

image

API网关

API 网关是什么,它具备什么功能?

  1. 统一路由
    根据请求路径将请求转发到后端实例,比如https://gateway.XXXXX.com/你的业务实例前缀/user/{id};
  2. 协议转换
    将前端的HTTP请求转换为服务内部的rpc协议
  3. 身份认证与鉴权
    集中处理JWT,OAuth2等鉴权操作,避免每个微服务都重复校验
  4. 流量管理
    实现服务的负载均衡,限流等操作,避免微服务收到冲击。
  5. 日志与指标分析
    作为统一入口,可以统一记录请求量,响应实践,成功率等指标,方便分析。

感觉服务发现与API网关重合了?

服务发现解决的是微服务实例之间的动态通信问题,主要用于内部服务间的调用
API 网关是外部客户端访问微服务的统一入口,主要用于客户端与微服务之间的通信

举个例子:

  1. 客户端认证需求
    若没有API网关,客户端直接调用微服务,每个微服务都要重复检验用户的JWT。
  2. 多协议支持
    微服务内部使用gRPC协议,而客户端是HTTP协议,这中间无法转换。
  3. 流量保护
    服务发现仅能实现简单的负载均衡(如轮询),但 API 网关可通过限流策略(如令牌桶、漏桶算法)防止突发流量压垮后端服务,这是服务发现无法实现的
  4. 数据聚合优化
    比如客户端需要同时获取 user与order信息,若通过服务发现,需要分别调用user service与order service,产生多次网络请求,而API网关将多个响应结果合并为一个,减少客户端的请求量。

有人可能会问了,我让服务发现与API网关合并就好了,这样不就大而全了?
合二为一的组件确实存在,如 Kong、Traefik、Istio Gateway 等,它们通过集成服务发现机制到网关中,简化了微服务架构的复杂度。

image

服务发现与API网关如何协同工作?

  1. API网关接收客户端请求后,根据route规则确定service.
    比如https://gateway.XXXXX.com/user-service/user/{id}
    根据user-service前缀,便可确定需要调用哪个微服务。
  2. 通过服务发现接口,查询获得可用服务列表
    调用注册中心 API。
  3. 选择一个实例转发
    基于负载均衡策略
  4. 微服务之间内部流转
    微服务 A 调用微服务 B 时,直接通过服务发现获取 B 的实例地址,无需经过 API 网关。微服务之间走轻量级通信方式,比如gRPC,避免使用HTTP协议提高性能。

网关+服务发现+服务实例=微服务架构的核心,这两个核心组件便已经组成了微服务基本实现,剩下的组件都是对微服务架构的锦上添花,但不是雪中送炭

为什么还有服务间负载均衡?

API网关只负责外部HTTP请求,微服务内部之间通信不走API网关,因此需要一个服务间负载均衡的组件来承担内部流量的转发

ESB与API Gateway的区别?

看到这里的小伙伴又犯嘀咕了,API Gateway的职能怎么感觉与ESB一模一样?都是负责"翻译",这不是又回到了老路了吗?ESB不就是因为太重才被淘汰的吗?
它们之间概念上确实很接近,但定位跟场景上还是有不少区别。

对比维度 ESB API Gateway
核心定位 企业级“系统集成中枢”,侧重“跨系统、跨协议的复杂集成” 微服务“入口网关”,侧重“对前端(如APP、网页)的API管理”
主要功能 协议转换、数据转换、复杂路由、消息持久化、事务支持 路由转发、认证授权(如OAuth2)、限流熔断、API文档管理
通信模式 支持“双向通信”“异步通信”(如JMS消息队列) 以“同步通信”为主(如HTTP请求-响应),少数支持异步(如WebSocket)
轻量化程度 偏重型(尤其商业产品),部署和配置复杂 轻量级,可容器化部署(如Docker),适配微服务的敏捷迭代

简单来说,虽然概念上类似。但ESB主要解决的是系统之间如何集成的问题,而API Gateway解决的是前端如何调用微服务的问题。在实际落地中,它们可以共存,且不冲突。
ESB集成外部或者内部老系统,API Gateway提供统一服务API。

甚至可以这么理解,ESB是API Gateway的超集,因为它功能更强大,也更重。 因为微服务的轻量化,去中心化思想,才有了API Gateway这种轻量级实现。

微服务架构的拓展

image

分布式配置

为什么需要分布式配置中心?

在单体架构或水平架构,抑或是简单的分布式架构中,配置文件通常以文件形式(appsettings.json)打包在application中,锁着系统规模的扩大,之前的管理方式就非常折磨人了。

举个例子,你有10个微服务,每个微服务部署3个实例,此时你要修改数据库连接,那么你的工作就是要修改30次配置文件,并重启服务器,然后还要小心中途不出错,还要考虑敏感信息的加密。

分布式配置中心是微服务中用于集中管理和动态推送配置的拓展组件。它通过统一的平台解决传统配置管理的痛点(如配置分散、修改复杂、环境隔离困难),是保障系统高可用、可维护的关键基础设施。

传统配置管理的痛点 分布式配置中心的解决方式
配置分散在各服务实例中,修改需逐个操作(如修改Nginx限流阈值需登录100台服务器) 集中存储配置,通过统一界面或API修改,自动同步到所有实例
配置变更需重启服务(如Spring Boot修改server.port需重启) 支持动态推送,配置修改后服务无需重启即可生效
多环境(开发/测试/生产)配置重复,易因复制错误导致线上故障 支持环境隔离(如按dev/test/prod划分配置)
配置版本混乱(如回滚时找不到历史版本) 提供版本管理回滚功能,记录每次修改的时间、操作人
敏感配置(如数据库密码)明文存储,存在安全风险 支持加密存储权限控制(如仅管理员可修改数据库配置)

分布式日志

分布式日志处理是指在分布式系统,对于分散在不同节点的日志进行集中收集,存储,分析和监控。其核心目标是解决分布式环境下的日志的分散性,异构性,高并发问题,帮助团队快速定位故障,挖掘数据。

为什么需要分布式日志中心?

  1. 全链路追踪,快速定位问题
    通过唯一请求 ID(如 Trace ID)将跨服务的日志串联,形成完整调用链路,秒级定位故障节点。。
  2. 统一日志管理,提升可观测性
    将分散日志汇聚到统一平台(如 Elasticsearch),支持多维度查询(按时间、服务名、关键字、日志级别),通过标准化格式将日志转换为统一JSON格式。
  3. 数据驱动的决策与优化
    统计用户行为日志(如页面访问、按钮点击),优化产品功能设计。
    分析日志中的耗时数据,识别服务瓶颈(如数据库慢查询、接口响应超时)
    通过日志量趋势分析,预测服务器存储和计算资源需求。

结构化日志的重要性

非结构化日志如同 “原始矿石”,而结构化日志是 “精雕细琢的宝石”—— 前者仅能提供原始信息,后者则通过标准化和字段化,让日志成为驱动系统优化、业务增长的核心资产。
无论是故障排查、性能优化,还是合规审计,结构化日志都是实现 “数据驱动运维” 的必经之路。

举个例子,你想统计出某个特定时间段用户登陆失败的次数。通过结构化日志,你可以轻松的以SQL的形式得出统计结果。
再举个例子,通过提取response_time,设置 “当 95% 请求耗时> 500ms 时触发告警

{
  "timestamp": "2025-05-24T14:30:00Z",
  "service_name": "user-service",
  "response_time":182ms,
  "level": "ERROR",
  "message": "用户登录失败",
  "metadata": {
    "user_id": "U12345",
    "error_code": "AUTH_001",
    "trace_id": "abc-123"
  }
}

简单来说,结构化日志,使得日志变成了数据库中的字段,从而发生质变。从之前的仅用于故障排查,上升到挖掘商业价值,用户行为分析的高度,让日志拥有了无限种可能。
image

分布式链路跟踪

链路跟踪主要用于追踪和记录跨多个服务/组件的链路请求,并分析经过的每个节点的处理时间,状态和依赖关系。其核心目标是解决分布式系统中又臭又长的调用链路,并结合分布式日志帮助开发者快速定位性能瓶颈与故障点

为什么需要链路跟踪?

  1. 线上故障快速排查
    一个请求可能设计到数十个服务,一个服务一个服务的查看,非常废人,效率也非常低下。
    比如用户支付失败,但无法确定是支付服务故障、库存服务超时,还是网络问题。链路跟踪通过 Trace ID 串联所有相关 Span,快速定位出错的服务或节点。

  2. 性能优化
    识别慢调用(如超时的 RPC 接口、低效的数据库查询),优化服务间调用逻辑或资源配置。

  3. 指导集群容量规划
    通过分析链路流量和资源消耗,评估各服务压力,指导集群扩/缩容

  4. 指导服务治理
    通过可视化的服务依赖关系,指导辅助熔断、限流策略的制定(如对高延迟服务设置降级规则)。

image

根据我的血泪史,链路跟踪最大的好处就是跟其它项目组扯皮的时候有理有据,免得其它项目组不认账!

分布式事务

分布式事务是指在分布式系统种,涉及多个服务节点或数据库节点的操作,需要保证其操作原子性,也就是要么全部成功,要么全部回滚。

为什么需要链路跟踪?

  1. 微服务架构下的业务拆分
    例如电商系统中,用户下单时需要同时完成:
    *. 订单服务创建订单(写入订单数据库)
    *. 库存服务扣减库存(写入库存数据库);
    *. 支付服务冻结预授权(调用第三方支付接口)。
    若其中某一步骤失败(如库存不足或支付超时),需回滚所有已完成的操作(如撤销订单、恢复库存),否则会导致数据不一致(例如用户下单成功但库存未扣减,或库存扣减但支付失败)。

  2. 分布式数据库的事务需求
    使用分库分表,一个事务可能涉及多个数据库节点的数据操作。
    传统数据库的本地事务无法跨节点保证一致性,需分布式事务机制(如 2PC、3PC)协调各节点的提交或回滚。
    根据业务不同,金融、电商等对数据敏感的领域必须保证强一致性。

受限于CAP定理,一致性,可用性,分区容错性无法同事满足,因此需要根据业务场景权衡。
image

模式 核心思想 适用场景
两阶段提交(2PC) 通过事务管理器协调各参与者的“准备”和“提交”阶段,保证强一致性但性能较低。 金融交易、实时数据同步
三阶段提交(3PC) 优化 2PC 的超时问题,引入“预提交”阶段,降低阻塞但实现复杂。 高可用分布式系统
事务消息(最终一致性) 通过消息中间件异步协调,允许短暂不一致,最终达到一致。 异步业务(如订单通知、物流更新)
TCC(Try-Confirm-Cancel) 自定义“尝试-确认-取消”逻辑,灵活处理部分成功的操作,适合复杂业务。 微服务架构中的复杂流程(如支付)
最大努力通知 通过重试机制和回调接口确保最终一致性,允许人工干预。 非核心业务(如短信通知)

如果将微服务架构比作数学高考,那么分布式事务就是最后那道压轴题。这道题做好了,清华就离你不远了。
别理解错了,我的意思不是让你玩好分布式事务,而是尽量避免使用分布式事务,它的收益其实很低,性能也不高。对于互联网业务,我们应该在设计阶段就尽量避免,能补偿就补偿,尽量不要高频次使用分布式事务。
对于平庸的大多数而言,最后一道压轴题直接放弃会比较明智。

微服务不是套公式,你的架构可以是Application微服务化,但底层数据库是同一个。你要相信SQL Server的能力,绝大多数公司业务达不到能让SQL Server出现瓶颈的时候

微服务架构的演化,简单介绍版

Service Mesh

随着微服务规模扩大,传统 SDK 模式的弊端(如代码侵入、升级成本高)凸显,服务网格作为基础设施层应运而生。

image

服务网格解决了什么问题?

在传统微服务架构中,服务间通信需要处理大量复杂逻辑,例如:
服务发现:如何找到目标服务的地址?
负载均衡:如何将请求均匀分配到多个实例?
流量控制:如何处理超时、重试、熔断?
安全通信:如何实现服务间的认证、授权和加密?
可观测性:如何收集调用链、指标、日志以监控系统?

这些逻辑通常通过 SDK集成到服务代码中,代码侵入性强,维护成本高

而Service Mesh将这些底层通信逻辑从业务代码中剥离,下沉到独立的基础设施层,实现透明化、标准化、自动化的服务间通信。

简单来说,就是做了一层抽象,解决了微服务架构中最复杂的 “连接” 问题。服务网格就像微服务之间的 “智能路由器” 和 “通信管家”,自动处理所有网络相关的脏活累活,让服务只需关心 “做什么”,而不是 “如何连接”。

维度 传统微服务(如Spring Cloud) 服务网格
通信实现 通过SDK集成到服务代码中(侵入式) 独立Sidecar代理(无侵入)
语言绑定 强绑定(如Java用Spring Cloud) 语言无关(服务可由任意语言开发)
升级成本 需修改服务代码并重新部署 只需升级Sidecar或控制平面
复杂度 服务代码包含底层逻辑,复杂度高 底层逻辑下沉到网格,服务逻辑更纯粹
资源消耗 低(无额外进程) 高(每个服务需运行Sidecar,Sidecar 的资源消耗通常为 “10%-20% 的额外 CPU / 内存)

Cloud Native

Cloud Native(云原生) 是一种利用云计算特性设计、构建和运行应用的技术理念与实践方法,其核心目标是通过云的弹性、分布式和自动化能力,实现应用的高可用、可扩展、快速迭代。云原生并非单一技术,而是一套包含方法论、架构模式和工具链的完整体系
image

云原生解决了什么问题?

微服务解决了 “拆” 的问题,云原生解决了 “在云中管好、用好这些拆分后的服务” 的问题。

简单来说说,当服务上云后,云原生通过容器化、编排、服务网格等技术,解决了微服务在云环境中的部署、运维、治理难题,让微服务真正 “跑好” 在云中。
极大的简化了微服务架构的工作量,协助开发人员更加专注于业务,而不是陷在微服务架构的技术细节中爬不出来。

由于.NET 在互联网的生态不足,相对JAVA的Spring Cloud这种商店式脚手架,采用.NET技术栈的公司往往需要投入更大的资源才能完成微服务化建设,但上云后,由云厂商提供的简单快捷的SDK与UI ,极大简化了微服务架构的复杂性,甚至可以不需要架构师。

Service Mesh与Cloud Native的关系?

Cloud Native的核心是微服务架构,而微服务的高效运行依赖可靠的服务间通信。传统微服务通过 SDK实现通信逻辑,但存在代码侵入、语言绑定等问题。Service Mesh 通过 Sidecar 代理拦截流量,将通信逻辑下沉到基础设施层,完美契合 Cloud Native 对 “解耦” 和 “无侵入” 的要求。

说人话就是在Service Mesh的基础上又做了一层抽象。

Serverless

Serverless(无服务器架构) 是一种云原生时代的计算模型和开发模式,其核心是将服务器的运维和资源管理完全交给云服务商,开发者只需专注于编写业务代码(如函数、事件处理逻辑),无需关心服务器的采购、部署、扩容或故障修复。它通过 “按需付费” 和 “事件驱动” 的设计,彻底改变了传统应用的开发与运维方式。

维度 传统架构(VM/容器) Serverless架构
资源管理 需手动申请/释放服务器,管理扩缩容 云服务商自动管理,开发者无需干预
付费模式 按服务器时长付费(如包年包月) 按实际使用的计算资源(执行时间、内存)付费
开发重心 需编写服务器配置、运维脚本、监控代码 仅需编写业务逻辑(函数或调用BaaS API)
扩缩容能力 需手动或脚本触发,响应延迟高(分钟级) 自动扩缩容,支持毫秒级启动(冷启动可能延迟)
适用场景 长生命周期、高并发、状态敏感的应用 短任务、事件驱动、无状态或轻状态的应用

理论与具体落地

逼逼了这么多,道理谁都懂,你又是如何落地呢?
再次强调一点,微服务不是套公式,也不是银弹,技术始终是为业务服务,符合当前业务发展规模的架构就是好架构!
image

我司在实践微服务的10年中,从最开始的单体到水平拓展再到拥抱AWS Cloud,中间经历了多次变更,虽未严格按照理论实践,但始终与业务发展步调一致,持续更新
以下是与理论不同的地方:

  1. 合并API网关与服务发现/治理
    评论区说得对,一个分布式服务治理框架,市面上99%都是处于这个阶段,我们的实践也是如此,使用Kong网关,作为分布式服务治理框架,集成了API与服务治理,服务发现。
    简化了绝大多数建设成本,因为类似ESB的服务发现/服务治理就是实现微服务的核心,剩余的组件均是锦上添花。

  2. Application微服务化,数据库只使用一个
    不同项目组使用不同的数据库,但都统一部署在同一个物理机上,因为我们相信SQL Server的能力,要万一遇到了瓶颈,因为也照了业务划分数据库,所以快速切成独立的物理数据库成本也较低。
    还有一个原因是,分布式事务成本不低,实现复杂,也增加了运维/开发难度。SQL Server做好读写分离,主从同步,足以支撑业务发展很长一段时间。

我司从起步到被收购,12年期间,成为了全美TOP级别房产公司,SQL Server从未掉过链子,也从未成为过木桶效应的那块短板。

  1. 各微服务之间通过HTTP调用
    倒反天罡!微服务不用Grpc,你这还叫微服务吗?
    首先要明白一个点,Grpc快的根本在于使用HTTP2,所以我们内部调用协议是用的HTTP2甚至HTTP3,即可满足业务发展需要。

  2. 有了Kafka为什么还要使用AWS SQS/SNS
    Kafka 是面向大数据和流处理的 “重型” 平台,适合构建数据基础设施,但在延迟队列/死信号队列上需要插件实现。团队希望单一职责,保持Kafka纯粹性。
    SQS/SNS 是面向应用解耦和通知的 “轻量级” 托管服务,适合快速开发和 AWS 生态内的场景。

  3. 为什么要使用Kong网关而不是K8s全家桶
    技术为业务服务,研发人员不应该陷在技术细节中出不来,尽管技术是研发的基本盘,但boss喊人来做事是来解决问题的,不是逢1,3,5升插件版本,逢2,4开技术分享会。
    说人话就是,项目和你有一个能跑就不要动,每天这么多会议,要跟产品斗智斗勇,没有这么多精力去学习新框架。
    框架复框架,框架何其多,你还记得大明湖畔的WCF,Silverlight,WindowsPhone吗?

参考资料

https://blog.51cto.com/universsky/5850036
https://cloud.tencent.com/developer/article/1549492
https://blog.csdn.net/weixin_43114209/article/details/144203876

posted @ 2025-05-25 12:09  叫我安不理  阅读(2101)  评论(2)    收藏  举报