什么是同步调用
在微服务架构中,服务之间需要频繁通信。同步调用是最常见的一种方式——一个服务发起请求,必须等待另一个服务返回结果后才能继续执行。就像你去餐厅点餐,服务员把单子交给厨房,你得坐在座位上等着菜做出来,这期间干不了别的事,这就是典型的同步过程。
对应到系统里,比如订单服务创建订单时,要调用用户服务验证用户状态,只有拿到“用户正常”的回复,订单才能继续创建。这个过程是阻塞的,调用方必须等对方回应。
常见的实现方式
最常用的同步调用技术是 HTTP + RESTful 接口,配合 JSON 数据格式。例如,订单服务通过 HTTP GET 请求获取用户信息:
GET /api/users/123 HTTP/1.1\nHost: user-service.example.com用户服务收到请求后处理并返回:
HTTP/1.1 200 OK\nContent-Type: application/json\n\n{\n "id": 123,\n "name": "张三",\n "status": "active"\n}这种写法清晰、通用,前后端都能理解,开发调试也方便。
同步调用的问题在哪里
虽然简单直接,但同步调用有个硬伤:依赖强、风险高。还是拿点餐打比方,如果厨房突然忙不过来,或者厨师请假了,那你就一直等下去,饭吃不上,还占着座位。在系统中,这就叫“雪崩”——一个服务卡住,调用它的服务也被拖住,层层传导,整个系统就卡死了。
另外,网络不稳定也会让请求变慢甚至失败。比如用户服务部署在另一个机房,网络抖动导致响应时间从 50ms 涨到 5 秒,那订单服务也就跟着卡 5 秒。
怎么缓解这些问题
加超时设置是最基本的防护。不能无限等下去,一般设置 2 到 5 秒,超过就认为失败。比如用 OpenFeign 调用时可以这样配置:
feign:\n client:\n config:\n default:\n connectTimeout: 2000\n readTimeout: 5000同时配合熔断机制,比如用 Hystrix 或 Resilience4j。当失败次数太多,就暂时切断调用,避免持续消耗资源。就像餐厅发现厨房彻底瘫痪了,干脆暂停接单,先处理积压问题。
还有一个办法是引入本地缓存。比如用户状态不会频繁变化,订单服务可以缓存一段时间,不必每次都要远程调用。既减轻压力,又提升响应速度。
什么时候适合用同步调用
不是所有场景都得上异步。如果业务逻辑本身就需要即时结果,比如支付完成后查余额、登录时校验账号密码,那就老老实实用同步调用。它逻辑清晰,排查问题也容易,适合大多数常规交互。
关键是要控制调用链深度。别出现 A 调 B,B 调 C,C 又回过头调 A 的情况,否则一旦出问题,根本理不清谁在等谁。
微服务拆得越细,同步调用的风险就越突出。设计接口时得多想想:这个请求能不能容忍延迟?失败了怎么办?有没有备用方案?提前考虑清楚,系统才不容易趴窝。