微服务调用
一、微服务调用
服务之间通过网络互相请求数据、执行逻辑,完成完整业务。
1. 微服务调用规范
- 上层调用下层,禁止下层调用上层
- 同步调用保持简单,异步调用解耦
- 必须熔断、降级、限流,防止雪崩
- 禁止循环调用
- 底层通知上层用 MQ
- 调用必须带日志、链路追踪
2. 两种调用方式
1)同步调用(实时、直接)
- 一边发请求,一边等返回
- 实时性强
- 会阻塞、会耦合
场景:查询、下单、支付校验。
主流技术:OpenFeign(企业首选)
2)异步调用(不等待、解耦)
- 发消息到 MQ,不等待结果
- 解耦、高可用、不阻塞
场景:通知、日志、更新、后续流程。
主流技术:RabbitMQ / RocketMQ / Kafka
3. 微服务的调用方式
1)OpenFeign—— 最主流、企业首选
声明式调用,像调用本地方法一样调用远程服务。
@FeignClient(name = "stock-service") public interface StockClient { @GetMapping("/stock/deduct") Result deduct(); }2)RestTemplate—— 传统方式
restTemplate.getForObject("http://stock-service/stock/deduct", String.class);二、微服务调用顺序
1. 正常调用顺序
上层调用下层,基础服务不调用业务服务,同步按流程,异步解耦。
2. 特殊情况
底层调用上层,如:
- 库存更新了 → 想通知订单服务
- 商品变价了 → 想通知购物车服务
解决方案:
1) 事件驱动 + MQ 消息(最推荐、最标准)
流程:
- ① 底层服务(库存 / 商品)只发消息,不调用任何人
- ② 上层服务(订单 / 购物车)监听消息,自己处理
- ③ 完全无依赖、无调用、无耦合
优点:无依赖、无循环调用、不阻塞、不雪崩、架构最健康
2) 抽取公共服务(消除双向依赖)
如果 A 和 B 互相需要,抽一个公共服务 C。如订单服务和库存服务中的公共服务部分 公共逻辑、状态、数据可以抽出作为公共服务
3) 上层主动轮询 / 拉取(简单场景)
上层定时调用下层获取状态,下层不回调上层。
三、常见问题
1.服务雪崩
一个服务挂 → 调用方也挂 → 全部崩溃。
解决方案:
- 熔断 ——Sentinel、Hystrix
- 降级,兜底方案,保证系统的可用性
- 限流(Sentinel)
- 超时控制,快速失败,释放线程
- 隔离,如给每个服务调用分配独立线程池
2. 服务调用超时
网络波动导致调用失败。
超时原因:
- 下游服务响应慢、卡顿、死锁
- 数据库慢查询、IO 阻塞
- 网络延迟、抖动
- 线程池满、资源耗尽
- 调用链太长,一环慢,全链超时
解决方案:
- 设置合理的超时时间(最基础、必须做)
- 超时次数过多 →自动熔断,不继续调用,防止拖死调用方
- 异步化 & 异步调用(解耦,不阻塞),用MQ、事件驱动削峰、解耦、不等待响应
- 超时重试,注意保证接口幂等性
- 服务隔离 + 线程池隔离
3. 分布式事务数据不一致
现象:多服务分步操作,某一步失败,前面已经提交数据无法回滚。
解决方案:
- 强一致:Seata AT/TCC
- 最终一致:本地消息表、可靠消息 MQ、最大努力通知。
