首页 / 知识库 / python服务端进阶 / 后端微服务架构

04 - 服务之间怎么”说话”

拆成微服务后,最直接的问题来了:原来在一个进程里,订单模块要拿用户信息,直接调个函数 get_user(id) 就行。现在用户服务和订单服务是两个独立的应用,中间隔着网络——它们该怎么互相说话?

答案分两大类:同步调用异步消息

方式一:同步调用 —— 像”打电话”

订单服务需要用户信息,就直接通过网络发一个请求给用户服务,然后等它回复

订单服务                          用户服务
   │   "喂,用户 42 的信息给我一下"     │
   │ ───────────────────────────────▶ │
   │                                  │ 查库…
   │        "他叫张三,是 VIP"          │
   │ ◀─────────────────────────────── │
   │  (拿到结果,继续往下走)           │

这就像打电话:我问,你答,在你回答之前,我得一直拿着话筒等着

你已经很熟悉这种形态了——它本质就是一个 HTTP 请求,跟你用 FastAPI 写的接口、前端用 Axios 调接口是一回事,只不过这次是一个服务去调用另一个服务的接口

常见的两种同步方式:

  • REST / HTTP:最常见,就是你熟悉的 GET /users/42,通用、好调试
  • gRPC:性能更高、更省流量,服务间内部调用常用,了解即可

特点:能立刻拿到结果,但必须等对方——对方慢,我就跟着慢;对方挂了,我这次调用就失败。

方式二:异步消息 —— 像”发微信”

有些事,我根本不需要等结果。比如”用户下单成功后要发一封通知邮件”——订单服务只要把”下单成功”这件事喊一声,就可以继续干自己的事了,发邮件让别人慢慢去做。

这时候就用消息队列(你已经学过了):

订单服务                消息队列              通知服务
   │  丢一条"订单已创建"消息   │                   │
   │ ──────────────────────▶ │ (消息在这排队)    │
   │  丢完就走,不等          │ ────────────────▶ │ 慢慢取出来
   │                        │                   │ 发邮件/发短信

这就像发微信:消息发出去我就走了,你什么时候看、什么时候回,不耽误我做别的事。

特点:发出去就不管了(解耦),对方挂了消息也不会丢(在队列里等着),高峰期还能削峰。代价是:拿不到即时结果

这正是你在消息队列入门里学的”异步、解耦、削峰”,在微服务里派上了大用场。

到底该用哪种?一句话决策

我现在马上就要这个结果,
拿不到就没法往下走?

    ┌───┴───┐
   是        否
    │         │
    ▼         ▼
 同步调用    异步消息
(打电话)    (发微信)

例:下单前要先查用户是不是VIP  →  必须立刻知道  →  同步
例:下单后要发通知邮件         →  可以慢慢来    →  异步
  • 要实时结果、拿不到就走不下去 → 用同步调用
  • 通知类、耗时任务、不用等结果 → 用异步消息

真实系统里,两种是混着用的(第 08 章的下单例子你会看到)。

一个补充概念:服务的”接口约定”

服务之间能对话的前提,是事先约定好接口长什么样:用户服务对外提供 GET /users/{id},返回哪些字段——这就是它对外的契约(API)

调用方(订单服务)只依赖这个约定,不关心用户服务内部是怎么实现的、用什么语言写的。只要约定不变,双方就能各自独立升级——这也是微服务能”独立开发”的基础。

小结

  • 服务间通信分两大类:同步调用(打电话,要等)异步消息(发微信,不等)
  • 同步:REST/HTTP、gRPC,能拿即时结果,但会被对方拖累。
  • 异步:走消息队列,解耦、削峰、不怕对方挂,但拿不到即时结果。
  • 决策:要不要立刻拿到结果——要就同步,不要就异步。真实系统两者混用。
  • 服务之间靠**接口约定(API 契约)**协作,这是”独立开发”的基础。

上一章 ← 03 - 微服务解决了什么,又带来了什么 | 下一章 → 05 - 数据怎么办:每个服务一个数据库 | 回到 README 目录