写点什么

杂七杂八系列 ---- 浅谈.NET 微服务架构的演变

作者:秃头小帅oi
  • 2025-05-29
    福建
  • 本文字数:4765 字

    阅读完需:约 16 分钟

服务架构的演变

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

单体架构/垂直架构



分布式架构



SOA 架构



微服务架构



微服务架构的核心

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

服务发现

为什么需要服务发现?

  1. 服务实例的动态变化


    在水平架构中,我们的服务集群往往是通过 Nginx/IIS 的静态配置来实现节点的增/减。加上节点少,因此,每次修改节点配置都是人工修改。


    而微服务架构天然的动态性与不确定性,服务实例通常需要动态扩容/缩容,故障重启,滚动升级等特点,因此服务示例的网络地址是随时变化的,加上微服务化之后,服务实例呈指数级增加,再由人工干预就不明智了。

  2. 分布式环境的网络复杂性


    服务实例可能步骤在不同的物理机,虚拟机,容器中,将它们整合非常麻烦,需要一个能够屏蔽底层细节,提供统一入口的组件,让调用方无需关心目标服务具体位置

  3. 抽象网络地址


    水平架构中,我们常常依赖 IP+端口的形式来确定服务实例,在微服务架构中,使用 Service-Name 来提供一个逻辑名称

  4. 去除不可用实例


    通过心跳访问实例提供的 Healthcheck,当某个实例故障时,自动去除,避免访问到不可用节点。

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



API 网关

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

  1. 统一路由


    根据请求路径将请求转发到后端实例,比如 https://gateway.XXXXX.com/你的业务实例前缀/user/{id};

  2. 协议转换


    将前端的 HTTP 请求转换为服务内部的 rbc 协议

  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 等,它们通过集成服务发现机制到网关中,简化了微服务架构的复杂度。



服务发现与 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 网关,因此需要一个服务间负载均衡的组件来承担内部流量的转发

微服务架构的拓展



分布式配置

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

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

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

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

分布式日志

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

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

  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"  }}
复制代码

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


分布式链路跟踪

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

为什么需要链路跟踪?

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

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

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

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



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

分布式事务

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

为什么需要链路跟踪?

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

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

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


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

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

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

Service Mesh

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



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

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

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

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

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

Cloud Native

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


云原生解决了什么问题?

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

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

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

Service Mesh 与 Cloud Native 的关系?

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

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

Serverless

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


用户头像

摸个鱼,顺便发点有用的东西 2023-06-19 加入

互联网某厂人(重生版)

评论

发布
暂无评论
杂七杂八系列----浅谈.NET微服务架构的演变_秃头小帅oi_InfoQ写作社区