实现开关降级
在电商项目中,开关降级是每个微服务都必须支持的一项功能,主要用于在促销活动期间、每日流量高峰期间、主播带货期间关闭一些无关紧要的功能,降低数据库的压力以换取更高的TPS。
虽然Sentinel不提供开关降级功能,但Sentinel使用了Java SPI机制,因此不需要修改源码也能扩展Sentinel实现开关降级。
本章内容主要包括以下几个方面:
使用AOP实现开关降级。
扩展Sentinel实现开关降级。
使用AOP实现开关降级
实现开关降级并不难,在不使用Sentinel的前提下,可以使用Spring AOP或动态代理模式拦截目标方法的执行,在方法执行之前,根据开关配置决定是否拦截请求。
开关配置可以使用Redis缓存,这样可以使集群之间共享配置,这种方式付出的性能损耗也只有一次Redis的GET操作。而如果不想每个请求都需要读取Redis缓存,也可以通过动态配置方式,使用配置中心管理开关。
以使用Redis缓存开关配置为例,讲解如何实现开关降级。使用Spring AOP实现开关降级只需要进行如下3个步骤。
(1)定义注解并将其用作切点,并且在注解中指定开发配置的缓存key。
(2)实现开关降级切面,在拦截方法时,先根据key从Redis中读取value,如果value是true,则不执行目标方法,直接响应服务降级。
(3)在需要使用开关降级的接口方法上添加开关降级注解。
第一步,定义开关降级注解@SwitchDegrade,代码如下:
在使用@SwitchDegrade注解时,key通常被定义为一个有意义的资源名称。
提示:如果是应用在实际项目中,建议为@SwitchDegrade注解添加一个前缀属性,使同一个应用下的开关key都使用同一个前缀,避免多个应用之间的缓存key冲突。
第二步,实现开关降级切面SwitchDegradeAspect,该切面用于拦截目标方法的执行,代码如下:
如上述代码所示,SwitchDegradeAspect用于拦截目标方法的执行,先从方法上的@SwitchDegrade注解中获取开关的缓存key,再根据key从Redis中读取当前开关的状态,若key存在且value为true,则抛出SwitchDegradeException,拒绝该请求。
在本例中,当开关打开时,SwitchDegradeAspect并不会直接响应请求,而是会抛出异常并由全局异常处理器处理该异常。这是因为并不是每个接口方法都会有返回值,且返回值类型也不固定,所以还需要由全局异常处理器处理开关降级抛出的异常,代码如下:
提示:在本例中,BaseResponse作为通用的响应协议,只有code和errMsg两个字段,code等于ResultCode.SERVICE_DEGRADE,作为降级响应状态码。
第三步,在需要使用开关降级的接口方法上添加@SwitchDegrade注解,代码如下。
此时,如果在Redis缓存中添加配置“auth:switch=true”,然后访问接口“/v1/test/demo”,将会得到如下响应:
使用Spring AOP实现开关降级虽然能够满足需求,但是也有一个缺点,就是必须在方法上添加@SwitchDegrade注解,因此配置不够灵活。
本文给大家讲解的内容是深度解析微服务高并发实现开关降级 :使用AOP实现开关降级
下篇文章给大家讲解的内容是深度解析微服务高并发实现开关降级 :扩展Sentinel实现开关降级
感谢大家的支持!
领取专属 10元无门槛券
私享最新 技术干货