1.2.3.1 开启sentinel
下边我们先编写降级逻辑,再实现服务熔断。
AI(Cursor)提示詞
帮我在已有工程里,对于itemclient实现降级策略,技术使用Sentinel,注意实现方案是implements FallbackFactory,降级类写在api的工程里,并最终在cart-service调用item-service时使用
首先配置Feign使用Sentinel:
在购物车服务application.yml中配置如下(默认已写好):
feign: sentinel: enabled: true # 开启feign对sentinel的支持
1.2.3.2 实现FallbackFactory接口
接下来给FeignClient编写失败后的降级逻辑有两种方式:
- 方式一:FallbackClass,无法捕获到远程调用的异常
定义一个降级类实现FeignClient接口,并在@FeignClient注解中配置fallback 属性,如下:
@FeignClient(name="item-service",path = "/items",fallback = 降级类名.class)
- 方式二:FallbackFactory,可以捕获远程调用的异常,我们一般选择这种方式。
定义一个降级类实现FallbackFactory接口,并在@FeignClient注解中配置fallbackFactory属性
@FeignClient(name="item-service",path = "/items",fallbackFactory= 降级类名.class)
这里我们演示方式二的失败降级处理。
步骤一:在hm-api模块中给ItemClient定义降级处理类,实现FallbackFactory接口:
代码如下:
package com.hmall.api.item; import com.hmall.api.item.dto.ItemDTO; import com.hmall.common.utils.CollUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.stereotype.Component; import java.util.Collection; import java.util.List; @Slf4j @Component public class ItemClientFallbackFactory implements FallbackFactory<ItemClient> { @Override public ItemClient create(Throwable cause) { return new ItemClient() { @Override public List<ItemDTO> queryItemByIds(Collection<Long> ids) { log.error("远程调用ItemClient#queryItemByIds方法出现异常,参数:{}", ids, cause); cause.printStackTrace(); // 查询购物车允许失败,查询失败,返回空集合 return CollUtils.emptyList(); } @Override public void deductStock(List<OrderDetailDTO> items) { log.error("远程调用ItemClient#deductStock扣减库存失败,参数:{}",items,cause); } }; } }
1.2.3.3 配置fallbackFactory
步骤二:在hm-api模块中的ItemClient接口中使用ItemClientFallbackFactory:
package com.hmall.api.item; import com.hmall.api.item.dto.ItemDTO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.Collection; import java.util.List; /** * @author Mr.M * @version 1.0 * @description 商品服务Feign接口 * @date 2024/8/3 16:21 */ @FeignClient(name="item-service",path = "/items",fallbackFactory = ItemClientFallbackFactory.class) public interface ItemClient { @GetMapping List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids); @PutMapping("/stock/deduct") public void deductStock(@RequestBody List<OrderDetailDTO> items); }
1.2.3.4 注入降级Bean
步骤三:在cart-service启动类添加扫描包配置,扫描降级类并将bean注册到spring容器
1.2.3.5 降级测试
最后测试降级效果。
重启cart-service,并将item-service停止来模拟item-service服务不可用
请求查询购物车接口,cart-service远程调用item-service,由于item-service不可用,Feign执行ItemClientFallbackFactory 中定义的降级逻辑
在ItemClientFallbackFactory 中打断点,在ItemClientFallbackFactory 中捕获到了远程调用的异常,降级方法返回空List<ItemDTO>。
接口测试最终效果,购物车可以正常显示,但由于获取的商品信息为空这里newPrice显示为null。
启动 ItemServiceApplication,再次请求购物车接口,验证发现此时返回了 newPrice数据
1.2.3.6 小结
feign远程调用怎么实现降级?
- 我们使用的是OpenFeign实现微服务之间的远程调用,使用Sentinel实现熔断降级。
- 首先配置sentinel,引入sentinel的依赖,配置sentinel的地址
- 在服务调用方开启feign使用sentinel
- 在服务调用方编写feign接口并编写降级逻辑,具体方法是编写降级类实现FallbackFactory接口,并在FeignClient注解中配置fallbackFactory。
降级逻辑到底谁实现?假设A调用B,希望当接口异常(异常比例、慢请求达到阈值)做降级时候能兜底
调用方:我来决定你默认返回什么
提供方:我告诉你,默认返回什么
【到底谁实现,需要靠业务来定,个人开发经验:建议提供方做实现(你不要干预一个提供接口的人默认做什么事情,这是别人的领域,也可以保证职责清晰)】
- 服务调用方当无法正常调用服务提供方接口时会走降级逻辑,并捕获到异常。