一、案例
某系统中存在一个用户服务,大部分页面都需要用到它,这个服务包含两个接口:用户状态接口和用户权限接口。
- 用户状态接口:返回用户是否在线、用户车辆位置等;
- 用户权限接口:返回用户可操作的权限列表,包含通用权限和定制权限。 目前这两个接口存在两个问题:
- 请求慢 用户状态接口中的车辆位置信息需要调用第三方系统,但是第三方系统的响应速度有时会很慢,并且偶尔会发生故障,这样就会出现我们自己的接口响应时间过长,超时的问题。
- 流量洪峰缓存超时 用户可操作的通用权限列表都是存储在 Redis中的,只有当Redis中不存在权限列表或者Redis查询超时时才会出去查询数据库,因此在大流量访问时很容易出现Redis访问超时,所有的流量都去访问了数据库,就造成了数据库服务器CPU压力倍增,最终导致服务崩溃,进而导致整个系统不可用。
二、解决问题
要解决上一小节提到的两个问题我们需要引入新的技术,引入的技术需要满足两个条件:线程隔离和熔断机制。
- 线程隔离 用户状态接口之所以慢,是因为用户状态接口的所有请求都去访问这个第三方位置服务了,第三方服务又出现了响应速度慢甚至发生了故障,所有的请求都在等待返回结果。因此我们可以限制调用第三方位置服务的请求数量,保证在第三方位置服务出现问题时我们有足够的连接去处理其他请求,并且还需要在超出请求数量时给予用户提示。
- 熔断机制 第二个问题中,只是因为CPU压力过大造成数据库服务超时,这时我们可以暂时停止对数据库服务的访问,不接收新的请求,利用暂停时间来让Redis补上数据。
三、注意事项
我们在找到适合的技术后,还需要考虑如下几个方面:
- 数据一致性 如果A服务更新数据库后,调用B服务的时候出现了服务降级,那么A服务是否需要回滚数据库。再者A服务更新数据库后,又成功调用了B服务,但是B服务调用C服务时出现了服务讲解,那么B服务应该返回A服务成功还是失败,A服务是否需要回滚数据库。关于这了两个问题没有合适的方案来解决,我们需要根据实际情况来设计出方案即可。
- 超时降级 当A服务请求B服务时,B服务没有在规定的时间内返回结果给A服务,这时A服务就判断调用B服务超时,进行了服务降级,但是并非时B服务出现了问题,而是B服务收到了请求但是还没有处理完成,等B服务完成后还是会返回处理结果给A服务。但是A服务已经进行了服务降级,因此就造成了B服务数据异常的情况。
- 用户体验 用户请求触发熔断后,经常会遇到三种情况:
- 用户请求读取数据时就遇到了部分接口降级的情况,就导致了部分数据获取不到的问题,这时应该在界面上给用户一个提示,或者想办法弥补这部分数据(可以使用旧数据进行弥补);
- 用户请求写入数据时出现了接口降级,部分写操作变成了异步操作,后续处理虽然对用户没有任何影响但是还是要根据实际情况告知用户;
- 用户请求写入数据时出现了接口降级,操作的数据可能会被回滚掉,因此这时必须提醒用户重新操作。
- 熔断监控 并不是说引入熔断技术后就万无一失了,我们还需要监控熔断是否配置的有问题,效果怎么样。
四、小结
这篇文章只是简单的讲解了以下熔断和限流,就提用的技术没有讲解。后续文章我将利用本章所讲的内容带领大家进行技术选型和原理讲解。