java断路器触发条件_断路器,AOP实现断路器模式 ------------Hystrix

断路器:https://martinfowler.com/bliki/CircutiBreaker.html

核心思想:

在断路器对象中封装受保护的方法调用。

该断路器监控调用和断路情况

调用失败触发阈值后,后续调用直接由短路器返回错误,不再执行实际调用。

理解:

客户端通过circuit breaker调用服务提供者,正常的时候可以调用。如果服务提供方出现了问题,发生了超时, 前几次可以超时处理, 到达一个阀值可以通过断路器进行处理, 就不再向服务方发起请求。

importlombok.extern.slf4j.Slf4j;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.springframework.stereotype.Component;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;importjava.util.concurrent.atomic.AtomicInteger;

@Aspect

@Component

@Slf4jpublic classCircuitBreakerAspect {//阀值

private static final Integer THRESHOLD = 3;//记录失败的次数

private Map counter = new ConcurrentHashMap<>();//记录被保护的次数

private Map breakCounter = new ConcurrentHashMap<>();/***

*@parampjp 程序连接点

*@return*@throwsThrowable*/@Around("execution(* 拦截的区域")public Object doWithCircuitBreaker(ProceedingJoinPoint pjp) throwsThrowable {//获取当前执行的方法

String signature =pjp.getSignature().toLongString();

log.info("Invoke {}", signature);

Object retVal;try{if(counter.containsKey(signature)) {//失败次数达到预制,如果保护次数没到,返回null

if (counter.get(signature).get() > THRESHOLD &&breakCounter.get(signature).get()

log.warn("Circuit breaker return null, break {} times.",

breakCounter.get(signature).incrementAndGet());return null;

}

}else{

counter.put(signature,new AtomicInteger(0));

breakCounter.put(signature,new AtomicInteger(0));

}

retVal=pjp.proceed();

counter.get(signature).set(0);

breakCounter.get(signature).set(0);

}catch(Throwable t) {

log.warn("Circuit breaker counter: {}, Throwable {}",

counter.get(signature).incrementAndGet(), t.getMessage());

breakCounter.get(signature).set(0);throwt;

}returnretVal;

}

}

Hystrix

Hystrix [hɪst'rɪks],中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。本文所说的Hystrix是Netflix开源的一款容错框架,同样具有自我保护能力。为了实现容错和自我保护,下面我们看看Hystrix如何设计和实现的。

Hystrix设计目标:

对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的

阻止故障的连锁反应

快速失败并迅速恢复

回退并优雅降级

提供近实时的监控

3b0868055202a46177bf58a95ab4407f.png

实现了断路服务器模式

在需要服务熔断的方法上添加@HystrixCommand注解, fallbackMethod指定熔断的地址,默认情况下@HystrixCommand是在另外一个线程执行的。可以做一些超时的处理。

@HystrixProperty(name="excution.isolation.strategy",value="SEMAPHORE")设置为信号

Hystrix配置项参考:

Spring cloud 支持

spring-cloud-starter-netfixi-hystrix

@EnableCircuitBreaker

Feign支持

feign.hystrix.enable=true

@FeignClient

fallback / fallbackFactory

简单示例:

pom引入

org.springframework.cloud

spring-cloud-starter-netflix-hystrix

application.properties

feign.client.config.default.connect-timeout=500

feign.client.config.default.read-timeout=500

#开启feign支持

feign.hystrix.enabled=true

#cousul连接配置

spring.cloud.consul.host=localhost

spring.cloud.consul.port=8500

spring.cloud.consul.discovery.prefer-ip-address=true

bootstarp.properties

spring.application.name=name-service

开启注解:

@EnableDiscoveryClient // 注册发现服务

@EnableFeignClients // feign的支持

@EnableCircuitBreaker // feignClient的演示

//Spring cloud 支持

@PostMapping("/order")

@HystrixCommand(fallbackMethod= "fallbackCreateOrder")publicCoffeeOrder createOrder() {/*业务代码*/

returnorder;

}publicCoffeeOrder fallbackCreateOrder() {

log.warn("Fallback to NULL order.");return null;

}

//FeignClient 的支持

importorg.springframework.cloud.openfeign.FeignClient;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.PathVariable;importorg.springframework.web.bind.annotation.RequestParam;importjava.util.List;

@FeignClient(name= "waiter-service", contextId = "coffee",

qualifier= "coffeeService", path="/coffee",

fallback= FallbackCoffeeService.class)//如果用了Fallback,不要在接口上加@RequestMapping,path可以用在这里

public interfaceTestService {

@GetMapping("/{id}")

Product getById(@PathVariable Long id);

}/*实现TestService*/

importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Component;importjava.util.Collections;importjava.util.List;

@Slf4j

@Componentpublic class FallbackTestService implementsTestService{

@OverridepublicProduct getById(Long id) {/**发送了垄断的逻辑代码*/

return null;

}

}/**Controller调用*/@GetMapping("testGetById")publicString testGetById() {

TestService.getById((long) 1);return "";

}


版权声明:本文为weixin_28753113原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。