尚学堂108天总结+Hystrix

1. 什么是服务灾难性雪崩效应

image

造成雪崩原因是什么?

image

2. 如何解决灾难性雪崩效应

image

什么是请求缓存?

image

解决灾难性雪崩效应-请求缓存-请求缓存处理

  1. @CacheConfig注解的作用是什么?
image
  1. @CacheEvict注解的作用是什么?
image

解决灾难性雪崩效应-请求合并-创建项目

  1. 什么是请求合并?
image
  1. 请求合并有哪些缺点?
image
  1. 解决灾难性雪崩效应-请求合并-请求合并处理
image
  1. 解决灾难性雪崩效应-服务熔断-服务熔断处理

    1. 什么是服务熔断?
image
image
  1. 解决灾难性雪崩效应-隔离机制-线程池隔离-创建项目

  2. 什么是线程池隔离?

image
  1. 线程池隔离的优点是什么?
image
  1. 解决灾难性雪崩效应-隔离机制-线程池隔离-线程池隔离处理
image

代码示例

请求缓存

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bjsxt</groupId>
    <artifactId>springcloud-eureka-consumer-ribbon-cache</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springcloud-eureka-consumer</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <!-- springCache -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.properties

spring.application.name=eureka-consumer-ribbon-cache
server.port=9010

#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
# Redis
spring.redis.database=0
#Redis服务器地址
spring.redis.host=192.168.2.129
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(负值表示没有限制)
spring.redis.pool.max-active=100
#连接池最大阻塞等待时间(负值表示没有限制)
spring.redis.pool.max-wait=3000
#连接池最大空闭连接数
spring.redis.pool.max-idle=200
#连接汉最小空闲连接数
spring.redis.pool.min-idle=50
#连接超时时间(毫秒)
spring.redis.pool.timeout=600

ProductService

@CacheConfig(cacheNames={"com.bjsxt.ego.product"})
@Service
public class ProductService {

    @Autowired
    private LoadBalancerClient loadBalancerClient;// ribbon负载均衡器

    @HystrixCommand(fallbackMethod="fallback")
    public List<Product> getUsers() {
        // 选择调用的服务的名称
        // ServiceInstance 封装了服务的基本信息,如 IP,端口
        ServiceInstance si = this.loadBalancerClient.choose("ego-product-provider");
        // 拼接访问服务的URL
        StringBuffer sb = new StringBuffer();
        // http://localhost:9001/product/findAll
        sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/product/findAll");
        System.out.println(sb.toString());
        // springMVC RestTemplate
        RestTemplate rt = new RestTemplate();

        ParameterizedTypeReference<List<Product>> type = new ParameterizedTypeReference<List<Product>>() {
        };

        // ResponseEntity:封装了返回值信息
        ResponseEntity<List<Product>> response = rt.exchange(sb.toString(), HttpMethod.GET, null, type);
        List<Product> list = response.getBody();
        return list;
    }
    
    //返回托底数据的方法
    public List<Product> fallback(){
        List<Product> list = new ArrayList<>();
        list.add(new Product(-1, "我是托底数据"));
        return list;
    }
    
    //根据ID查询商品
    @Cacheable(key="'product' + #id")
    public Product getProductById(Integer id){
        System.out.println("=========Get======"+id);
        return new Product(id, "新的商品");
    }
    
    //根据ID删除商品
    @CacheEvict(key="'product' + #id")
    public void delProductById(Integer id){
        System.out.println("=========Del======"+id);
    }
}

ProductController

@RestController
public class ProductController {

    @Autowired
    private ProductService userService;

    @RequestMapping("/consumer")
    public List<Product> getUsers() {
        return this.userService.getUsers();
    }
    
    @RequestMapping(value="/get",method=RequestMethod.GET)
    public Product get(Integer id){
        return this.userService.getProductById(id);
    }
    
    @RequestMapping(value="/del",method=RequestMethod.GET)
    public void del(Integer id){
        this.userService.delProductById(id);
    }

}

请求合并

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bjsxt</groupId>
    <artifactId>springcloud-eureka-consumer-ribbon-batch</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springcloud-eureka-consumer</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.properties

spring.application.name=eureka-consumer-ribbon-batch
server.port=9010
#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

ProductControlle

@RestController
public class ProductController {

    @Autowired
    private ProductService userService;
    
    @RequestMapping("/consumer")
    public  void  getUsers() throws Exception{
        Future<Product> p1 = this.userService.getProduct(1);
        Future<Product> p2 = this.userService.getProduct(2);
        Future<Product> p3 = this.userService.getProduct(3);
        System.out.println(p1.get().toString());
        System.out.println(p2.get().toString());
        System.out.println(p3.get().toString());
    }
}

ProductService

@Service
public class ProductService {

    //利用hystrix合并请求  
    @HystrixCollapser(batchMethod = "batchProduct", scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,  
            collapserProperties = {  
            //请求时间间隔在20ms之内的请求会被合并为一个请求,默认为10ms
            @HystrixProperty(name = "timerDelayInMilliseconds", value = "20"),
            //设置触发批处理执行之前,在批处理中允许的最大请求数。
            @HystrixProperty(name = "maxRequestsInBatch", value = "200"),  
    })  
    //consumer的controller调用的方法 该方法返回值必须要返回Future类型
    public Future<Product> getProduct(Integer id){
        System.out.println("=========="+id+"==========");
        return null;
    }
    
    @HystrixCommand
    //调用Provider服务的方法
    public List<Product> batchProduct(List<Integer> ids){
        for(Integer id:ids){
            System.out.println(id);
        }
        //假设是调用provider服务后返回的list
        List<Product> list = new ArrayList<>();
         list.add(new Product(1, "电视"));
         list.add(new Product(2, "电脑"));
         list.add(new Product(3, "冰箱"));
         list.add(new Product(4, "手电筒"));
         list.add(new Product(100,"list............"));
         System.out.println("ddddddddddddddddddddddd");
         return list;
    }
}

服务熔断

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.bjsxt</groupId>
    <artifactId>springcloud-eureka-consumer-ribbon-breaker</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springcloud-eureka-consumer</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.properties

spring.application.name=eureka-consumer-ribbon-breaker
server.port=9010

#设置服务注册中心地址,指向另一个注册中心
eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/

ProductController

@RestController
public class ProductController {
    @Autowired
    private ProductService userService;
    
    @RequestMapping("/consumer")
    public List<Product> getUsers(@RequestParam("flag") Integer flag){
        return this.userService.getUsers(flag);
    }
}

ProductService

@Service
public class ProductService {

    @Autowired
    private LoadBalancerClient loadBalancerClient;// ribbon负载均衡器

    @HystrixCommand(fallbackMethod = "fallback",
            commandProperties = {
              //默认20个;10s内请求数大于20个时就启动熔断器,当请求符合熔断条件时将触发getFallback()。
              @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, 

value="10"),
              //请求错误率大于50%时就熔断,然后for循环发起请求,当请求符合熔断条件时将触发getFallback()。
              @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, 

value="50"),
              //默认5秒;熔断多少秒后去尝试请求
              @HystrixProperty(name=HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, 

value="5000"),
            })
    public List<Product> getUsers(int flag) {
        
        System.out.println(flag);
        if(flag == 1){
            throw new RuntimeException();
        }
        // 选择调用的服务的名称
        // ServiceInstance 封装了服务的基本信息,如 IP,端口
        ServiceInstance si = this.loadBalancerClient.choose("ego-product-provider");
        // 拼接访问服务的URL
        StringBuffer sb = new StringBuffer();
        // http://localhost:9001/product/findAll
        sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/product/findAll");
        System.out.println(sb.toString());
        // springMVC RestTemplate
        RestTemplate rt = new RestTemplate();

        ParameterizedTypeReference<List<Product>> type = new ParameterizedTypeReference<List<Product>>() {
        };

        // ResponseEntity:封装了返回值信息
        ResponseEntity<List<Product>> response = rt.exchange(sb.toString(), HttpMethod.GET, null, type);
        List<Product> list = response.getBody();
        return list;
    }
    //返回托底数据的方法
    public List<Product> fallback(int flag){
        List<Product> list = new ArrayList<>();
        list.add(new Product(-1, "我是托底数据"));
        return list;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容