什么是微服务?它带来哪些挑战?

#Java#面试八股

什么是微服务?它带来哪些挑战?

结论先行:微服务是把一个单体应用按业务能力拆成一组可独立部署、独立演进的小服务,服务间通过轻量协议(HTTP/RPC/消息)通信。它换来的是「局部可扩展、技术异构、故障隔离」,代价是分布式系统固有的复杂度:服务发现、配置管理、调用治理、数据一致性、链路追踪、运维与测试成本。

1. 从单体到微服务

单体                          微服务
┌──────────────────┐        ┌────────┐ ┌────────┐ ┌────────┐
│ 用户 / 订单 / 支付 │        │ 用户   │ │ 订单   │ │ 支付   │
│ 同一个进程、同一个库│  ──▶   │ 独立库 │ │ 独立库 │ │ 独立库 │
└──────────────────┘        └────┬───┘ └───┬────┘ └───┬────┘
                                 └────── 网关 / 注册中心 ──────┘

拆分不是目的。判断是否该拆,通常看三个信号:业务边界清晰、团队规模超过一个敏捷小组、模块的伸缩需求差异大(例如秒杀流量只压订单服务)。

2. 单体 vs 微服务

维度单体微服务
部署一个包整体发布每个服务独立发布
扩展整体扩容,浪费资源按服务扩容
技术栈统一可异构
故障影响一个 bug 可能拖垮全部可隔离、可降级
事务本地事务,简单分布式事务,复杂
调用进程内方法调用网络调用,可能超时/重试/重复
数据一个库,join 自由每服务独立库,跨库 join 消失
排查单机日志需要链路追踪、日志聚合
团队共享代码库按服务划分 ownership

3. 拆完之后新增的六类问题

问题表现典型解法
服务发现实例 IP 变化,调用方如何找到Nacos / Eureka / Consul
配置管理几十个服务的配置分散Nacos Config / Apollo
流量入口鉴权、限流、跨域无处安放Spring Cloud Gateway
服务调用超时、重试、负载均衡OpenFeign + LoadBalancer
容错一个服务雪崩拖垮全站Sentinel / 熔断降级
可观测性一次请求跨 8 个服务TraceId + 日志聚合 + 指标

4. 代码:一个最小服务

@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    @RestController
    public static class OrderController {

        private final OrderService orderService;

        public OrderController(OrderService orderService) {
            this.orderService = orderService;
        }

        @GetMapping("/orders/{id}")
        public OrderVO detail(@PathVariable Long id) {
            return orderService.detail(id);
        }
    }
}
server:
  port: 8082
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

spring.application.name 就是服务在注册中心里的唯一标识,调用方用这个名字做负载均衡。

5. 一个必须谈的点:数据一致性

拆库后 order 与 inventory 不在同一个事务里,只能:

  • TCC / Seata AT:强一致但性能与侵入性高;
  • 本地消息表 + 最终一致:订单落库同时写消息表,由定时任务投递,失败重试;
  • Saga:长事务拆成多个本地事务 + 补偿动作。

绝大多数业务选最终一致:允许短暂不一致,用对账兜底,而不是硬上分布式事务。

6. 常见追问

追问一:微服务一定比单体好吗? 不是。小团队、业务未稳定时,单体开发效率更高。微服务的收益要在「团队规模、流量规模、迭代频率」达到一定程度后才显现,否则只是把复杂度提前。

追问二:服务拆分的粒度怎么定? 按领域驱动设计(DDD)的限界上下文(Bounded Context)拆,一个上下文一个服务;不要按技术分层拆(controller 服务、dao 服务),那样只会增加调用次数。

追问三:微服务网关和 Nginx 是什么关系? Nginx 做四/七层反向代理与静态资源,负责接入层;网关负责业务级的路由、鉴权、限流。常见拓扑是「公网 → Nginx/LB → Gateway → 各服务」。

追问四:服务间调用用 HTTP 还是 RPC? 内部高性能、强类型、跨语言场景用 gRPC/Dubbo;对外开放、调试友好、生态成熟用 HTTP + JSON。两者常在同一个系统里共存。

追问五:怎么防止一个服务拖垮全站? 三道防线:调用方设超时(禁止无限等待)、熔断降级(Sentinel/Hystrix)、资源隔离(线程池/信号量)。再加限流保护入口。

小结

微服务的本质是用分布式的复杂度换组织的伸缩性与业务的独立性。技术选型(Spring Cloud Alibaba 也好,Kubernetes 也罢)只是把复杂度工具化,真正决定成败的是服务边界划分、数据一致性策略与可观测性建设。

笔记加载中…