目前使用eureka server完成了服务注册和服务发现,ribbon完成了客户端负载均衡。如果服务提供者的响应很慢那么服务消费者会强制等待,一直等到http请求超时,如果服务消费者还是其他的服务提供者,那么就会产生级联的雪崩。
超时机制:等待几秒还是没响应,就直接返回了。
断路器模式:A如果有大量的超时,B一直去请求A是没有意义的,不再去请求A直接返回异常。保证B不会拖死。
断路器全开(B不去请求A),断路器半开(过了10分钟,B猜测A是不是好了,留一小部分流量去请求A大部分还是直接抛异常,发现A响应时间/失败率达标了就把断路器关闭)
容错:雪崩效应。CD的微服务调了B的接口,B又调了A的接口。A宕机了,B里面就会堆积线程,接着B宕机了,CD里面堆积线程,接着CD宕机了。
5秒钟失败20次就打开。
实践:
1.监控:判断A是不是挂掉了(有一个阈值,请求多少次有多少次失败了)。
2.断路器状态:打开,关闭,半开。
3.分流:留小部分流量尝试请求A服务。
4.自我修复:断路器状态切换
超时机制:高并发下,A挂了,设置超时机制,内网传输很快。
断路器:B调用A出现了异常,并不会立即扔到断路器里面去,比如达到60%都是异常状态,就会丢到断路器里面去,B就不请求A了。
断路器打开了,过一段时间看A微服务是否已经修复了,就小部分流量去请求(判断是否达到阈值),如果还是失败就继续打开(继续直接返回),如果好了就关闭。
ribbon整合hystrix:
package com.itmuch.cloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;@SpringBootApplication@EnableEurekaClient@EnableCircuitBreaker //启用断路器public class ConsumerMovieRibbonApplication { @Bean @LoadBalanced //ribbon的客户端负载均衡 public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(ConsumerMovieRibbonApplication.class, args); }}
package com.itmuch.cloud.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import com.itmuch.cloud.entity.User;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;@RestControllerpublic class MovieController { @Autowired private RestTemplate restTemplate; //http://localhost:8010/movie/1 //查看hystrix的状态http://localhost:8010/hystrix.stream //第一次会进fallbackMethod方法,后面走microservice-provider-user。因为Hystrix默认超时时间是1秒。 //microservice-provider-user挂了就进fallbackMethod @GetMapping("/movie/{id}") @HystrixCommand(fallbackMethod = "findByIdFallback") //参数和返回值类型一样,当用户微服务挂了就走fallbackMethod。进入了fallbackMethod不代表断路器打开。 public User findById(@PathVariable Long id) { return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class); } public User findByIdFallback(Long id) { User user = new User(); user.setId(0L); return user; }}
package com.itmuch.cloud.entity;import java.math.BigDecimal;public class User { private Long id; private String username; private String name; private Short age; private BigDecimal balance; public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Short getAge() { return this.age; } public void setAge(Short age) { this.age = age; } public BigDecimal getBalance() { return this.balance; } public void setBalance(BigDecimal balance) { this.balance = balance; }}
spring: application: name: microservice-consumer-movie-ribbon-with-hystrixserver: port: 8010eureka: client: healthcheck: enabled: true serviceUrl: defaultZone: http://user:password123@localhost:8761/eureka instance: prefer-ip-address: truehystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
4.0.0 microservice-consumer-movie-ribbon-with-hystrix jar com.itmuch.cloud microservice-spring-cloud 0.0.1-SNAPSHOT UTF-8 UTF-8 1.8 org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-eureka org.springframework.boot spring-boot-starter-actuator org.springframework.cloud spring-cloud-starter-hystrix
package com.itmuch.cloud.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import com.itmuch.cloud.entity.User;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;@RestControllerpublic class MovieController { @Autowired private RestTemplate restTemplate; @GetMapping("/movie/{id}") @HystrixCommand(fallbackMethod = "findByIdFallback", commandProperties = @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")) //配置上面之后findById方法和fallbackMethod的方法在一个线程里面 public User findById(@PathVariable Long id) { return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class); } public User findByIdFallback(Long id) { User user = new User(); user.setId(0L); return user; }}
org.springframework.boot spring-boot-starter-actuator