SpringCloud------熔断器Hystrix的使用
1.GitHub地址
https://github.com/Netflix/Hystrix
https://github.com/Netflix/Hystrix/wiki
官方文档
2.为什么要用Hystrix?
在一个分布式系统里,一个服务依赖多个服务,可能存在某个服务调用失败,
比如超时,异常等,如何能保证在一个依赖出问题的情况下,不会导致整体服务失败,
通过Hystrix就可以解决
3.功能
提供熔断,隔离,Fallback,cache,监控等功能
4.熔断后怎么处理?
出现错误后,可以Fallback错误的处理信息
5.代码实现
1)添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.28</version> </dependency>
2)启动类添加@EnableCircuitBreaker
import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @MapperScan("cn.ytheng.order_service") @EnableFeignClients @EnableCircuitBreaker public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
3)添加ProductOrder订单实体类
import lombok.Data; import java.io.Serializable; import java.util.Date; /** * 商品订单实体类 */ @Data public class ProductOrder implements Serializable { private String id; private int userId; private String productName; private String tradeNo; private Date createTime; public ProductOrder() { } }
4)添加feign,为了测试Product服务挂掉时,降级处理的情况
import cn.theng.order_service.fallback.ProductFallback; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; /** * * 商品服务客户端 * product-service: 调用服务名称,即spring.application.name * ProductFallback:需要继承当前FeignClient的类 * */ @FeignClient(name = "product-service", fallback = ProductFallback.class) public interface ProductClient { @GetMapping("/api/v1/product/find") String getById(@RequestParam("id") int id); }
5)添加针对product-service服务的降级处理类
import cn.theng.order_service.service.ProductClient; import org.springframework.stereotype.Component; /** * * 针对商品服务,做降级处理 * */ @Component public class ProductFallback implements ProductClient { //当调用product-service的getById接口出现错误时,就会执行该方法 @Override public String getById(int id) { System.out.println("feign 调用product-service服务异常..."); return "null"; } }
6)添加ProductOrderService接口
import cn.theng.order_service.domain.ProductOrder; /** * 订单业务类 */ public interface ProductOrderService { /** * 下单接口 */ ProductOrder save(int userId, int productId); }
7)添加ProductOrderServiceImpl接口实现类import cn.theng.order_service.domain.ProductOrder;import cn.theng.order_service.mapper.ProductOrderMapper;
import cn.theng.order_service.service.ProductClient; import cn.theng.order_service.service.ProductOrderService; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; import java.util.UUID; @Service public class ProductOrderServiceImpl implements ProductOrderService { @Autowired private ProductClient productClient; @Override public ProductOrder save(int userId, int productId) { String data = productClient.getById(productId);
// 下面代码会报错,触发熔断
JSONObject product = JSON.parseObject(data); ProductOrder order = new ProductOrder(); order.setTradeNo(UUID.randomUUID().toString()); order.setProductName(product.getString("productName")); order.setCreateTime(new Date()); return order; } }
8)添加controller
package cn.theng.order_service.controller; import cn.theng.order_service.domain.ProductOrder; import cn.theng.order_service.service.ProductClient; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/api/v1/order") public class ProductOrderController { @Autowired private ProductOrderService productOrderService; @PostMapping("/test2") @HystrixCommand(fallbackMethod = "getProductFail") public Object test2(@RequestParam("product_id") int productId) { //如果test2内有报错,则会执行getProductFail方法 ProductOrder order = productOrderService.save(1, productId); return "success"; } //方法签名一定要与上面方法保持一致 public Object getProductFail(int productId) { Map<String, Object> map = new HashMap<>(); map.put("code", -1); map.put("msg", "目前排队人数过多,请稍后再试..."); return map; } }
9)修改application.yml配置
server: port: 8781 eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ spring: application: name: order-service #设置调用服务超时时间 #product-service为服务名称,也可以设置为默认值default #默认配置下,feign的hystrix配置是关闭的 feign: hystrix: enabled: true client: config: product-service: connectTimeout: 5000 readTimeout: 11000
10)访问地址