程序实现--对外接口可不仅仅是“给大佬递餐”,前置工作还是要做滴~
我们来看一个案例。
前端页面上,用户在订单详情页确认完信息后,点击“确认支付”,发起余额支付。
这里,我们做如下3项设定。
1)后台程序暴露的“支付”Rest接口名为 order/pay。
2)后台程序对于“支付”的处理逻辑,我们简化成下面的业务流程。
3)后台程序是微服务结构,包括提供RestAPI接口的springmvc服务和后面的订单服务、账户服务。
那么, 比较下面两种实现方式,左边第一种是在order/pay这个rest接口里先查单校验订单状态,通过后才调用订单服务的“支付订单”RPC接口。右边第二种是直接转发请求给订单服务的“支付订单”RPC接口。你更倾向于哪一种实现方式呢?
相比来说,我认为第一种更靠谱一些。
Why?
看上去,虽然两种实现方式都能达到目的,第一种方式还多了一个前置的校验。为什么我建议采用第一种方式呢?
这是典型的程序业务处理的方式。——接收到请求入参后,先进行前置校验,如果校验失败直接中止返回,否则才走后续的业务处理流程。
有同学就说了,按第二种实现方式,直接调用订单服务的“支付订单”RPC接口,“支付订单”RPC接口的实现里不是也有订单状态的前置校验吗?
这是有区别的。按第一种实现方式的话,支付订单RPC接口除了流程图里的实现方式外,也可以省掉查询订单这一步,直接通过包含状态机幂等的update操作来变更订单状态(sql诸如UPDATE order SET pay_status='PAYED' WHERE order_no = '001' AND pay_status = 'INIT'
),根据update是否成功来决定后面的扣减用户余额的逻辑。如果采用第二种实现方式,那就最好先老老实实的通过查询订单来判断状态,毕竟数据库的update成本比select要高很多。
从技术的角度来分析,两种实现方式也是有区别的。“支付订单”作为一个业务处理的RPC接口,我们要做的控制会比较多,例如事务控制、幂等、异常处理、耗时、锁、监控,等等。因此,从这个角度来看,在确认需要支付订单的时候再调用“支付订单”,是不是更合理呢?
类似的案例,也包括,我们的MQ消费者,在从队列里拿到消息后,先进行必要的判断和校验,然后再调用业务方法。而不是一上来就直接把参数丢给业务方法。
本文设计文稿自:https://www.processon.com/view/link/611e38c2e0b34d3511f7c479
当看到一些不好的代码时,会发现我还算优秀;当看到优秀的代码时,也才意识到持续学习的重要!--buguge
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/17765857.html