由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪,甚至导致服务“雪崩”。
为了解决这个问题,就出现断路器模型。
当对特定的服务的调用达到一个阀值(hystric 是5秒20次) 断路器将会被打开。
就是当服务不可用时就会返回断路器设定的值,防止长时间等待和重试。
当断路器打开后,超过一定时间后又会重新允许请求尝试访问(默认为5s)。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
ribbon方式:
@SpringBootApplication //spring boot 开启应用 //@EnableDiscoveryClient //Discovery Service”有多种实现,比如:eureka, consul, zookeeper。 @EnableEurekaClient //只能为eureka作用 @EnableHystrix//断路器 public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean @LoadBalanced RestTemplate restTemplate() { return new RestTemplate(); } }
package com.Service; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; //ribbon远程调用服务 @Service("callService") public class CallService { final static Logger logger = LogManager.getLogger(CallService.class); @Autowired RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "callServiceError") public String callService(String name) { //这里只是把IP和端口号变成了服务的名字(通过HTTP进行远程服务调用的) return restTemplate.getForObject("http://eureka-Client/eurekaClient/Test/test",String.class); } public String callServiceError(String name) { return "hi,"+name+",sorry,error!"; } }
feign方式:(feign是自带断路器的)
server.port=8765 #logging.pattern.level=INFO #服务器路径 server.context-path=/feign # #eureka.instance.hostname=localHost #表示是否注册自身到eureka服务器,因为当前这个应用就是eureka服务器,没必要注册自身,所以这里是false。 #eureka.client.registerWithEureka=false #fetchRegistry表示是否从eureka服务器获取注册信息,同上,这里不需要 #eureka.client.fetchRegistry=false #设置eureka服务器所在的地址,查询服务和注册服务都需要依赖这个地址。 #eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/ eureka.client.serviceUrl.defaultZone=http\://localhost\:8761/eurekaServer/eureka/ spring.application.name=feign #自定义断路器(网上有说falser的,但实测应该使用true) feign.hystrix.enabled=true
package com.Service; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @FeignClient(value = "eureka-Client",fallback = CallServiceError.class) //服务名字 public interface CallService { @RequestMapping(value = "/eurekaClient/Test/test",method = RequestMethod.GET) String callService(); }
package com.Service; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @Component public class CallServiceError implements CallService{ @Override public String callService() { return "sorry Error!"; } }
勘误:有人反映feign的熔断器不起作用,springcloud版本的问题,用这个:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>