一、微服务架构概述

1.1 什么是微服务

微服务,说白了就是把一个大型应用拆成多个小服务。每个小服务独立运行,独立部署,各管各的一亩三分地。

我刚开始接触这个概念时,也觉得不就是拆模块吗?后来真正上手才发现,没那么简单。微服务不是简单的代码拆分,而是一种架构思想——每个服务都围绕特定的业务能力构建,拥有自己的数据库、自己的技术栈、自己的发布节奏。

举个例子,一个电商系统可以拆成:

  • 用户服务:管注册、登录、权限
  • 商品服务:管商品信息、库存
  • 订单服务:管下单、支付流程
  • 物流服务:管配送、快递查询

每个服务都是独立的进程,通过HTTP或RPC通信。你想想看,如果订单服务挂了,用户还能浏览商品,这就是微服务的魅力。

我的经验:刚开始别拆太细。我见过一个团队把用户服务拆成「登录服务」「注册服务」「密码重置服务」三个独立服务,结果光服务间调用就乱成一锅粥。微服务的粒度,以「业务边界」为准,别以「功能点」为准。

1.2 微服务与单体架构对比

先说说单体架构。一个典型的单体应用,所有代码打成一个包,部署在一台服务器上。早期项目这么做没问题,简单直接。

但随着业务增长,问题就来了:

对比维度 单体架构 微服务架构
部署方式 整体部署,牵一发动全身 独立部署,互不影响
扩展能力 只能整体水平扩展 按需扩展单个服务
技术栈 统一技术栈 每个服务可自选
团队协作 所有人在一个代码库 每个服务独立团队
故障影响 一个bug拖垮整个系统 故障隔离在单个服务
开发效率 项目越大,启动越慢 小服务快速启动

我记得有一次,一个单体项目上线前发现了一个支付模块的小bug。修复本身只花了10分钟,但重新打包、测试、部署整个应用花了整整4个小时。这就是单体架构的痛点——改一行代码,得重新发布整个系统。

微服务就不一样了。支付服务出问题,只重新部署支付服务就行。其他服务照常运行,用户甚至感觉不到。

注意:微服务不是银弹。我曾经接手过一个项目,团队为了「微服务而微服务」,把只有三个开发人员的项目拆成了8个微服务。结果光维护服务间通信就占了一半工作量。小团队、小项目,老老实实用单体架构更香。

1.3 微服务核心挑战

微服务虽然好,但坑也不少。我总结四个核心挑战,也是咱们这门课要重点解决的问题。

1.3.1 服务发现

单体架构下,服务地址是写死的。但微服务不一样,服务实例随时可能增减——扩容、缩容、故障重启,IP地址都在变。

服务发现就是解决「怎么找到对方」的问题。常见的方案有两种:

  • 客户端发现:服务启动时注册到注册中心,调用方从注册中心拉取地址列表
  • 服务端发现:通过负载均衡器转发请求,调用方只认识负载均衡器

我个人习惯用Consul做服务发现,配合.NET的Consul客户端库,配置起来很顺手。当然,Eureka、Nacos也是不错的选择。

避坑指南:我曾经遇到过一个问题——服务注册成功了,但调用方就是找不到。排查了半天,发现是健康检查配置不对。Consul默认每10秒检查一次,如果服务启动慢,健康检查先失败了,注册中心就把服务踢掉了。解决方案是把健康检查的间隔调大,或者等服务完全启动后再注册。

1.3.2 配置管理

单体应用配置少,一个appsettings.json搞定。微服务呢?每个服务都有自己的配置,而且不同环境(开发、测试、生产)配置还不一样。

配置管理的核心需求:

  • 集中管理:所有配置放在一个地方,别散落在各个服务里
  • 动态刷新:改配置不用重启服务
  • 版本控制:配置变了能回滚

我推荐用Consul的KV存储做配置中心,或者用Apollo。.NET这边,微软官方也提供了配置中心方案,集成起来很方便。

嗯,这里要注意:配置里千万别写密码。我见过有人把数据库密码明文写在配置文件里,还提交到了Git仓库。正确的做法是用密钥管理服务,或者环境变量注入。

1.3.3 网关

微服务多了,客户端就头疼了。调用订单服务一个地址,调用用户服务又一个地址,还得处理认证、限流、日志……

API网关就是统一入口。所有请求先到网关,网关再转发到对应的微服务。网关负责:

  • 路由转发:根据请求路径分发到不同服务
  • 认证鉴权:统一处理Token验证
  • 限流熔断:防止流量冲垮后端服务
  • 日志监控:记录所有请求的出入

.NET生态里,Ocelot是最流行的网关框架。我用了好几年,稳定、灵活、社区活跃。当然,微软官方的YARP也不错,性能更好一些。

我的建议:网关不要做太多业务逻辑。我见过有人把业务校验写在网关里,结果网关越来越重,最后变成了一个「超级单体」。网关只做通用能力,业务逻辑留给后端服务。

1.3.4 限流

限流是保护系统的最后一道防线。没有限流,一个突发的流量高峰就能把服务打垮。

常见的限流算法:

  • 令牌桶:匀速往桶里放令牌,请求来了拿令牌,拿不到就等或拒绝
  • 漏桶:请求先进桶,桶以固定速率往外漏,桶满了就丢弃
  • 滑动窗口:统计时间窗口内的请求数,超过阈值就限流

我个人偏爱令牌桶算法,因为它能应对突发流量。比如平时限流1000QPS,但突然来了2000的并发,令牌桶允许短时间内消耗积攒的令牌,不会直接拒绝所有请求。

在.NET里,可以用AspNetCoreRateLimit这个库,配合Redis做分布式限流。网关层也可以做限流,Ocelot就内置了限流中间件。

曾经踩过的坑:有一次线上服务突然大量报错,查了半天发现是限流阈值设得太低了。测试环境压测没问题,但线上流量是测试的10倍。限流参数一定要根据线上实际流量动态调整,别拍脑袋定数字。

好了,微服务架构的概述就讲到这里。这四个核心挑战——服务发现、配置管理、网关、限流,正是咱们这门课要深入实战的内容。下一章,我会带大家搭建第一个微服务项目,从零开始体验微服务的魅力。