首页 > 编程语言 > 详细

SpringCloud之服务降级

时间:2020-04-09 18:16:35      阅读:46      评论:0      收藏:0      [点我收藏+]

1.Hystrix(断路器)

1.1定义

扇出:多个微服务调用的时候,假设微服务A调用微服务B和C,微服务B和C又调用其他的服务。
服务雪崩:如果扇出的链路上某个微服务的调用时间过长或不可用,对微服务A的调用就会越来多的系统资源,进而引起系统崩溃。
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,能够保证在一个依赖出现问题的情况下,不会导致整体服务失败,从而提高分布式系统的弹性。它的功能有服务降级、服务熔断、服务限流等。
断路器:一种开关装置,当某个服务单元发生故障后,通过断路器的故障监控向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或抛出异常。
服务熔断:当扇出链路的某个微服务不可用火响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。
服务降级:在客户端实现的

1.2项目开发

源代码:https://github.com/zhongyushi-git/cloud-hystrix.git

1.2.1服务提供者进行服务降级

1)参考feign的搭建来搭建hystrix的项目,只需要eureka集群、api和consumer80。

2)按照provider8001创建服务提供者cloud-provider-hystrix-8001,再导入hystrix依赖

技术分享图片
 <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
View Code

3)对发生异常的方法进行处理

在服务提供者的UserController中的get方法添加结果为空的异常处理

技术分享图片
    @GetMapping("/get/{id}")
    @HystrixCommand(fallbackMethod = "hystrix_get")
    public User getUser(@PathVariable("id")long id){
        User user=userService.getUser(id);
        //数据为空就抛出异常
        if(user==null){
           throw new RuntimeException("未查询到数据");
        }
        return user;
    }

    //服务熔断
    public User hystrix_get(@PathVariable("id")long id){
        User user=new User();
        user.setId(id);
        user.setName("未查询到数据");
        user.setPhone(new Date().toString());
        return user;
    }
View Code

4)在服务提供者启动类添加注解@EnableCircuitBreaker

技术分享图片
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class ProviderMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(ProviderMain8001.class, args);
    }
}
View Code

5)启动测试

先启动eureka集群,然后启动8001。分别访问http://localhost:8001/user/get/1http://localhost:8001/user/get/123,get/1能获取正常数据,get/123不能获取正常数据而显示的错误信息。

1.2.2服务消费者进行服务降级

1)把服务提供者进行异常处理的地方给注释掉

技术分享图片
    @GetMapping("/get/{id}")
    @HystrixCommand(fallbackMethod = "hystrix_get")
    public User getUser(@PathVariable("id")long id){
        User user=userService.getUser(id);
        //数据为空就抛出异常
//        if(user==null){
//            throw new RuntimeException("未查询到数据");
//        }
        return user;
    }
View Code

2)在cloud-feign-consumer80导入hystrix依赖

技术分享图片
 <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
View Code

3)修改cloud-feign-consumer80的yml

技术分享图片
feign:
  hystrix:
    enabled: true
View Code

4)创建service接口,用于feign获取服务

技术分享图片
package com.zys.cloud.serivce;

import com.zys.cloud.entity.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

//添加注解,指定微服务名称
@FeignClient(value="CLOUD-PROVIDER")
public interface UserClientService {

    @GetMapping("/user/get/{id}")
    public User getUser(@PathVariable("id")long id);

    @PostMapping("/user/add")
    int addUser(User user);
}
View Code

5)创建controller

技术分享图片
package com.zys.cloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.zys.cloud.entity.User;
import com.zys.cloud.serivce.UserClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;

@RestController
@RequestMapping("/consumer")
public class UserController {

    @Resource
    private UserClientService userClientService;

    @GetMapping("/get/{id}")
//    @HystrixCommand(fallbackMethod = "hystrix_get")
    public User getUser(@PathVariable("id") long id){
        User user=userClientService.getUser(id);
        //数据为空就抛出异常
        if(user==null){
            throw new RuntimeException("抱歉,未查询到数据");
        }
        return user;
    }
    //服务熔断
    public User hystrix_get(@PathVariable("id")long id){
        User user=new User();
        user.setId(id);
        user.setName("抱歉,未查询到数据");
        user.setPhone(new Date().toString());
        return user;
    }

    @PostMapping("/add")
    public int addUser(User user){
        return userClientService.addUser(user);
    }



}
View Code

6)在服务消费者启动类添加注解@EnableHystrix

技术分享图片
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class ConsumerFeignMain80 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeignMain80.class, args);
    }
}
View Code

7)启动测试

先启动eureka集群,然后启动8001,最后80启动。分别访问http://localhost/consumer/get/1http://localhost/consumer/get/123,get/1能获取正常数据,get/123不能获取正常数据而显示的错误信息。然后关闭8001,再次访问http://localhost/consumer/get/1也是显示错误信息。

1.2.3服务降级优化

在上面的服务提供者和消费者中,对服务进行降级,都有一些问题。就是要对每一个方法进行降级,降级的方法又混合在controller中,显示很繁琐,配置起来也很麻烦。不过是可以进行全局配置的。

(1)DefaultProperties设置默认的处理方法

在80的controller中加入注解进行配置

技术分享图片
package com.zys.cloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.zys.cloud.entity.User;
import com.zys.cloud.serivce.UserClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Date;

@RestController
@RequestMapping("/consumer")
@DefaultProperties(defaultFallback = "globalFallBack")
public class UserController {

    @Resource
    private UserClientService userClientService;

    @GetMapping("/get/{id}")
//    @HystrixCommand(fallbackMethod = "hystrix_get")
    //未指定fallback,就使用默认的
    @HystrixCommand
    public User getUser(@PathVariable("id") long id){
        User user=userClientService.getUser(id);
        //数据为空就抛出异常
        if(user==null){
            throw new RuntimeException("抱歉,未查询到数据");
        }
        return user;
    }
    //服务熔断
    public User hystrix_get(@PathVariable("id")long id){
        User user=new User();
        user.setId(id);
        user.setName("抱歉,未查询到数据");
        user.setPhone(new Date().toString());
        return user;
    }

    @PostMapping("/add")
    public int addUser(User user){
        return userClientService.addUser(user);
    }

    //设置全局的fallback
    public User globalFallBack(){
        User user=new User();
        user.setName("服务器维护中,请稍后再试!");
        user.setPhone(new Date().toString());
        return user;
    }

}
View Code

当没有指定fallback时,就会去使用默认的fallback。

(2)代码解耦

在service中新建一个类UserClientServiceFallBackFactory,实现FallbackFactory

技术分享图片
package com.zys.cloud.serivce;

import com.zys.cloud.entity.User;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

@Component
public class UserClientServiceFallBackFactory implements FallbackFactory<UserClientService> {
    @Override
    public UserClientService create(Throwable throwable) {
        return new UserClientService() {
            @Override
            public User getUser(long id) {
                User user=new User();
                user.setId(id);
                user.setName("未查询到数据,服务降级-停止服务");
                return user;
            }

            @Override
            public int addUser(User user) {
                return 0;
            }
        };
    }
}
View Code

在UserClientService中给FeignClient注解加fallbackFactory属性

技术分享图片
@FeignClient(value="CLOUD-PROVIDER",fallbackFactory = UserClientServiceFallBackFactory.class)
View Code

1.3服务监控

对于微服务,也是需要进行监控的。Hystrix也提供了准实时的服务监控(Hystrix Dashboard),它会持续的记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展现给用户。在1.2的基础上继续开发。

1)新建cloud-feign-hystrix-dashboard-consumer9001的maven工程

2)在pom中添加依赖

技术分享图片
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
View Code

3)配置yml文件

技术分享图片
server:
  port: 9001
View Code

4)在包com.zys.cloud下创建启动类并添加注解@EnableHystrixDashboard

技术分享图片
package com.zys.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableHystrixDashboard
public class ConsumerFeignHystrixDashboardMain9001 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerFeignHystrixDashboardMain9001.class, args);
    }
}
View Code

5)在8001的启动类加配置方法

技术分享图片
 //指定监控路径
    @Bean
    public ServletRegistrationBean getServlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
View Code

6)启动测试

先启动9001,然后启动eureka集群,然后启动8001。然后在浏览器输入http://localhost:9001/hystrix,可以看到下面的界面,说明配置成功。

技术分享图片

 

在第一个输入框输入http://localhost:8001/hystrix.stream,点击下面的按钮,可以进入服务的监控页面。

 再输入http://localhost:8001/user/get/1,快速的刷新几次,再回到监控页面看到有图形在实时变化,这就是实时的监控效果。

技术分享图片

 

SpringCloud之服务降级

原文:https://www.cnblogs.com/zys2019/p/12652314.html

(1)
(1)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!