目前已有的一个思考方向是使用 K8S 统合各个独立的 Laravel 小服务,再开放统一对外的 API Gateway
但碰到一个问题是各个服务间要如何在不发生耦合的状况下沟通
举例来说:订单发生后需要减少库存,若库存成功扣除后要再告诉订单更新状态
我目前想到三种解决方式:
- 在 API Gateway 处理流程问题,等订单服务回传成功后,再呼叫库存服务。
好处:流程简单直觉、使用者当下就可知道订单结果
坏处:API Gateway 会发生强耦合、API Gateway 会出现状态,违反微服务的 Stateless 原则 - 在订单服务的建立方法中直接呼叫库存服务
好处与坏处都跟方法一差不多,但更多的坏处是微服务本身会变复杂、与其他服务发生强耦合,且违反微服务间不能直接沟通的原则 - 借由某种广播机制,在订单建立完成后,由订单服务发出「订单建立成功」的广播,告诉其他服务有订单建立。库存服务接收到广播后就会扣除库存,并再次发出「库存扣除成功」的广播,由订单服务再次接收。而其他不相干的服务就会忽略广播。
好处:各服务完全解耦,彼此只借由单次事件进行沟通,不会在双方服务留下状态,且后续有逻辑改动只需要调整事件即可,不用动服务主逻辑
坏处:无法及时告诉使用者订单产生结果,会造成较差的使用者体验
我目前想采用的是第三种模式,因为我司目前还处于新创阶段,功能仍在快速调整,因此开发上最好能像电源一样快速插拔,若服务出现强耦合就会降低产品调整的速度。相较之下,第三种方法造成的使用者体验降低都还可以接受。
我搜寻过后似乎有「Message Queue」这种解法,但有点不明白它如何用 Laravel 实作,且有一部分文章来源表示 Message Queue 已经是过时的技术
想请问有没有人设计过微服务架构,或曾经碰过类似的状况能给我一些建议,谢谢
---------------------- 4/3 补充说明
我发现我之前对 Message Queue 的理解有错,因此上来补充说明
我之前对 Queue 的机制,是认为他注册的事件是一段程式码,等待 worker 执行
但 Laravel 的事件机制,实际上是由 Event 注册事件名称及相关资料,等 worker 空闲后,呼叫 Listener 接收事件
Event 注册的资料如下所示
array ( 'displayName' => 'App\Mail\SaveAsDraft', 'job' => 'Illuminate\Queue\CallQueuedHandler@call', 'maxTries' => NULL, 'timeout' => NULL, 'timeoutAt' => NULL, 'data' => array ( 'commandName' => 'Illuminate\Mail\SendQueuedMailable', 'command' => 'O:34:"Illuminate\Mail\SendQueuedMailable":3:{s:8:"mailable";O:20:"App\Mail\SaveAsDraft":20:{s:29:"' . "