一、初步介绍
工作中,我们或多或少都免不了和第三方交互。例如:对接第三方支付、第三方登录授权、对接银行服务。但我这里要说的场景是: "我们发起一个业务给第三方,第三方处理完成异步通知给我们"。但是考虑到我们是多个业务,所以需要一个统一的接收第三方异步回调的入口,故有下面的伪代码:
@Autowired
private IGatewayService igatewayService;
@ResponseBody
@PostMapping("/process")
public Result processRequest(){
GatewayDto gateway = extractRequest();//省略
return igatewayService.gateway(gateway );
}
这里的IGatewayService 是一个通用网关服务,可以针对不同的业务做分发。伪代码如下:
public Result gateway(GatewayDto gateway){
//根据不同的参数分发到不同的业务Bo对象。
IGatewayBo gatewayBo = routingHandler.getGatewayBo(gateway);
return gatewayBo.handle();
}
一切看起来似乎还没毛病,一个Servlet接收第三方回调,其中业务包括(充值、体系、其他业务、用户相关等等),然后根据传入的参数在"Service层"做分发。
二、分析
我们系统服务层采用的是微服务架构,产品、用户、充值、提现等等都是拆分后独立部署。也就是说IGatewayService 也是一个单独部署的服务。而IGatewayBo只是一个直接操作DB的DAO而已。 到底问题出在哪?
我们有没有想过,我们所有的业务都通过一个Servlet来接收,然后通过IGatewayService 去做一层业务转发,如果IGatewayService 出现问题怎么办?那将会导致平台所有依赖回调的业务都不可用,肯定是我们所不能接受的。而且这种方式完全违背了微服务架构的好处,微服务之所以好,就是将业务拆分独立部署,业务之间不受影响。
也就是说,我们的Servlet强依赖IGatewayService 服务,并没有将压力分配到其他业务上,将会极大的影响业务吞吐率,甚至导致整个IGatewayService线程池耗尽而宕机,随之而来的是所有业务都处于瘫痪。
三、应该怎么做
如果在Servlet层做业务分发就可以避免这个问题.即使其中一个业务出现问题,也不会影响其他业务。伪代码:
@Autowired
private IGatewayService igatewayService;
@ResponseBody
@PostMapping("/process")
public Result processRequest(){
//分发到不同的业务(注意:这里是Service,不是DAO)
IGatewayService gatewayService = routingHandler.getGatewayService(gateway);
return gatewayService.gateway(gateway );
}
这样就解决了所有业务都挤在一起的问题。或者说把IGatewayService 和其他业务一起部署,这样也没问题,当其中一个IGatewayService 服务挂了,只是影响同一节点的业务,其他服务并不影响。