SpringCloud支持多种断路器的实现,比较常见的是NetflixHystrix,不过最新版spring-cloud-2020.0.3已经去掉了netflix相关组件。在微服务之间的调用链中,如果没有适当的保护,当某个服务环节出现故障时,可能会导致整体服务雪崩不可用。例如,由于数据库查询速度慢,导致底层服务请求接口时间过长,进而导致服务线程爆满,等待线程数激增,导致大量超时并且无法对外提供服务。本文使用spring-cloud-2020.0.3和spring-boot-2.5.4来演示hystrix的使用以及相关参数的配置。1、模拟客户端(客户端)pom.xml关键依赖org.springframework.cloudspring-cloud-starter-netflix-eureka-client3.0.3org.springframework.cloudspring-cloud-starter-openfeign<版本>3.0.3org.springframework.cloudspring-cloud-starter-netflix-hystrix<版本>2.2.9.RELEASEorg.springframework.bootspring-boot-starter-actuatororg.springframework.cloudspring-cloud-starter-netflix-hystrix-dashboard2.2.9.RELEASE注意新版spring-boot引入了openfeign,老版使用netflix-feign写client调用类UserService并融合回调类UserServiceFallback。UserService.java如下packagecom.mixfate.hystrix.client;@FeignClient(value="hystrix-server",path="/user",fallback=UserServiceFallback.class)publicinterfaceUserService{@GetMapping("/{id}")StringfindById(@PathVariable("id")Stringid);}UserServiceFallback.java如下packagecom.mixfate.hystrix.client.fallback;@ComponentpublicclassUserServiceFallbackimplementsUserService{@OverridepublicStringfindById(Stringid){return"defaultvalue";}}FeignClient指定服务名为hystrix-server,根路径为/user。如果调用失败,使用UserServiceFallback回调类处理。编写Application启动类。packagecom.mixfate.hystrix;@EnableEurekaClient@EnableFeignClients@EnableHystrix@SpringBootApplication@EnableHystrixDashboard@EnableSchedulingpublicclassHystrixDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(@HystrixDemoApplication.class,}注意其中的介绍);只是EnableHystrix,@EnableCircuitBreaker已经提示过时了,这个组件已经默认从spring-cloud组件中移除了,因为netflix已经不再维护对应的项目了。写一个测试类,写一个配置文件。application.yml如下server:port:8080spring:application:name:hystrix-clientcloud:circuitbreaker:hystrix:enabled:trueeureka:client:service-url:defaultZone:http://root:123456@loc??alhost:8761/eureka/fetch-registry:trueregister-with-eureka:falsefeign:circuitbreaker:enabled:trueclient:config:default:connectTimeout:2000readTimeout:2000logging:level:root:infohystrix:command:default:execution:isolation:thread:timeoutInMilliseconds:2000仪表板:代理流允许列表:“本地主机”管理:服务器:端口:8082端点:网络:曝光:包括:“*”私人用户服务用户服务;@Testpublicvoidtest(){log.info("开始");字符串结果=userService.findById("测试");日志信息(结果);log.info(userService.findById("test"));log.info(userService.findById("test"));}}由于开启了断路器,因此,即使服务器没有开启,也没有注册中心运行这个测试,依然??是成功的。Fuse调用Fallback回调并返回结果。首先,将日志级别调整为调试。简单跟踪调用情况,可以看到如下两条请求日志,说明获取不到。进入hystrix-server,启动eureka注册中心后如果没有服务注册到eureka,也会通过Fallback返回默认的调用结果。另外需要注意的是参数spring.cloud.circuitbreaker.hystrix.enabled是默认开启的,不需要单独配置。负载均衡器不包含服务hystrix-serverError执行HystrixCommand.run()的实例。进行回退逻辑...2.模拟一个简单的服务器(server)在大多数情况下,微服务既是服务器又是客户端服务器定义了一个简单的接口并向eureka注册服务。pom.xml关键依赖项。<依赖>org.springframework.bootspring-boot-starter-weborg.springframework.cloudspring-cloud-starter-netflix-eureka-client<版本>3.0.3org.springframework.bootspring-boot-configuration-processortrue控制器入口类、启动类及配置文件。UserHystrixController.java如下packagecom.mixfate.hystrix.controller;@RequestMapping("/user")@RestControllerpublicclassUserHystrixController{@GetMapping("/{id}")publicStringfindById(@PathVariable("id")Stringid)throwsInterruptedException{Stringresult=String.format("这是mixfate[%s][%s]",id,System.currentTimeMillis());线程.睡眠(500);返回结果;}}HystrixServerApplication.java如下packagecom.mixfate.hystrix;@SpringBootApplicationpublicclassHystrixServerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(HystrixServerApplication.class,args);}}application.yaml如下spring:application:name:hystrix-servereureka:client:fetch-registry:falseregister-with-eureka:trueservice-url:defaultZone:http://root:123456@loc??alhost:8761/eureka/server:port:8081服务器启动后,使用客户端调用查看正常调用结果,fetch-registry表示是否从eureka注册中心获取服务列表,不需要设置为false在这里,注册-with-eureka是否将服务注册到eureka?这里是server端,所以需要在eureka注册中心注册,其他服务才能调用。场景描述情况1未连接到eureka注册中心情况2可以连接到注册中心但无法获取服务(未注册)注册中心提示(Noserversavailableforservice:hystrix-server)情况3可以从注册中心获取服务,但调用目标服务超时。情况四:被调用服务器抛出异常。对于情况三,在服务端的接口添加Thread.sleep(2000),让程序休眠2秒模拟慢请求,观察情况发现三个请求都在fallback时,因为熔断请求的超时时间为1秒,即参数hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds,打开源码查看类HystrixCommandProperties,可以看到如下关键代码,就是呼叫超时的默认设置;但同时还需要注意openfeign的连接超时和读取超时设置feign.client.config.default.connectTimeout,feign.client.config.default.readTimeout,结合超时参数观察client的通话情况。Integerdefault_executionTimeoutInMilliseconds=1000;...省略protectedHystrixCommandProperties(HystrixCommandKeykey){this(key,newSetter(),"hystrix");}...省略this.executionTimeoutInMilliseconds=getProperty(propertyPrefix,key,"execution.isolation.thread.timeoutInMilliseconds",builder.getExecutionIsolationThreadTimeoutInMilliseconds(),default_executionTimeoutInMilliseconds);...省略privatestaticHystrixPropertygetProperty(StringpropertyPrefix,HystrixCommandKeykey,StringinstanceProperty,IntegerbuilderOverrideValue,IntegerdefaultValue){returnforInteger().add(propertyPrefix+".command."+key.name()+"."+instanceProperty,builderOverrideValue).add(propertyPrefix+".command.默认。”+instanceProperty,defaultValue).build();}确定这个参数后,调整为3秒,重试,可以连接了,但是还需要配置连接超时时间和假客户读取超时时间。如果小于熔断请求超时时间,仍然会返回fallback的默认值。您可以检查FeignClientProperties和FeignCclientConfiguration配置类;feign:client:config:hystrix-server:connectTimeout:5000readTimeout:5000注意FeignClientProperties配置类中的config是Map类型的。上面配置hystrix-server是指单独为这个服务配置timeout,需要配置全局timeout改成default后如何恢复?先看配置属性类HystrixCommandProperties的几个参数。注意hystrix的版本是2.2.9.RELEASE,低版本略有不同。Parameterdescriptiondefault_metricsRollingStatisticalWindow=10000slidingwindowtime,default10secondsdefault_circuitBreakerRequestVolumeThreshold=20circuitBreakerRequestVolumeThreshold=20circuitBreakerRequestVolumeThreshold=20circuitBreakerRequestVolumeThreshold=20timeswithin10secondstoopencircuitBreakerErrorThresholdPercentage=50errorratereaches50%circuitBreakerSleepWindow=InMillisecondafteralongtimeofcircuitBreakerSleepWindow0attemptsRecoverySo可以简单的写一个timer来测试hystrix开启关闭的效果。@Scheduled(cron="*****?")publicvoidschedule(){for(inti=0;i<2;i++){System.out.println(userService.findById("test"));}}定时器每秒触发两次请求,10秒内可以有20次请求,满足参数circuitBreakerRequestVolumeThreshold的条件,默认值为20,然后可以通过停止或启动服务来测试熔断功能,可以在hystrixdashboard查看打开和关闭http://localhost:8080/hystrix的状态。