SpringCloud之Feign与Hystrix

一.服务之间的相互调用

搭建订单服务

1.创建项目
2.导入依赖
	spring-cloud-starter-netflix-eureka-client
	spring-boot-starter-web
3.启动类加注解
	@EnableDiscoveryClient
4.编写配置文件
	1.服务名
		spring:
  			application:
    			name: order
	2.注册中心地址
		eureka:
  			client:
    			service-url:
      				defaultZone: http://localhost:8761/eureka/
	3.端口号
		server:
  			port: 7001
5.编写一个controller,响应一个字符串
	@RestController
    @RequestMapping("/order")
    public class OderController {

        @GetMapping("/msg")
        public String order(){
            String msg = "this is order page";
            return msg;
        }
    }
6.启动

搭建商品服务

1.创建项目
2.导入依赖
	spring-cloud-starter-netflix-eureka-client
	spring-boot-starter-web
3.启动类加注解
	@EnableDiscoveryClient
4.编写配置文件
	1.服务名
		spring:
  			application:
    			name: goods
	2.注册中心地址
		eureka:
  			client:
    			service-url:
      				defaultZone: http://localhost:8761/eureka/
	3.端口号
		server:
  			port: 7002
5.编写一个controller,响应一个字符串
	@RestController
    @RequestMapping("/goods")
    public class OderController {

        @GetMapping("/msg")
        public String order(){
            String msg = "this is goods page";
            return msg;
        }
    }
6.启动

1.直接使用restTemplate

@GetMapping("/msg")
    public String order(){
        //1.直接使用restTemplate
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject("http://localhost:7002/goods/msg", String.class);
        
        String msg = "this is order page"+result;
        return msg;
    }

启动order注册到eureka,访问7001/order/msg
在这里插入图片描述
2.使用restTemplate,通过LoadBalancerClient获得指定的服务的路径

@RestController
@RequestMapping("/order")
public class OderController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @GetMapping("/msg")
    public String order(){
        /*//1.直接使用restTemplate
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject("http://localhost:7002/goods/msg", String.class);*/

        //2.使用restTemplate,通过LoadBalancerClient获得指定的服务的路径
        //获取服务信息
        ServiceInstance goods = loadBalancerClient.choose("GOODS");
        //获取服务的ip和端口
        //ip
        String ip = goods.getHost();
        //端口
        int port = goods.getPort();
        //使用restTemplate调用
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject("http://" + ip + ":" + port + "/goods/msg", String.class);

        String msg = "this is order page"+result;
        return msg;
    }
}

在这里插入图片描述
3.基于restTemplate和loadBalanced注解实现

@RestController
@RequestMapping("/order")
public class OderController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/msg")
    public String order(){
        /*//1.直接使用restTemplate
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject("http://localhost:7002/goods/msg", String.class);*/

        /*//2.使用restTemplate,通过LoadBalancerClient获得指定的服务的路径
        //获取服务信息
        ServiceInstance goods = loadBalancerClient.choose("GOODS");
        //获取服务的ip和端口
        //ip
        String ip = goods.getHost();
        //端口
        int port = goods.getPort();
        //使用restTemplate调用
        RestTemplate restTemplate = new RestTemplate();
        String result = restTemplate.getForObject("http://" + ip + ":" + port + "/goods/msg", String.class);
*/

        //3.基于restTemplate和loadBalanced注解实现
        String result = restTemplate.getForObject("http://GOODS/goods//msg", String.class);
        String msg = "this is order page"+result;
        return msg;
    }
}

编写RestTemplateConfig配置文件

@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

二.Feign

2.1.简介

feign是声明式的web service客户端,它让微服务之间的调用变得更简单了,类似controller调用service。springcloud集成了ribbon和eureka,可在使用feign时提供负载均衡的http客户端

只需要创建一个接口,然后添加注解即可

feign,调用微服务访问的两种方法

  • 微服务名字【Ribbon】
  • 接口和注解【Feign】
2.2.feign的简单使用

1.导入依赖

	   <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-openfeign</artifactId>
           <version>2.2.0.RELEASE</version>
       </dependency>

2.在公用springcloud-api服务中添加接口

//value值为服务的名称
@FeignClient(value = "PROVIDER-DEPT")
public interface DeptClientService {

    @RequestMapping("/dept/add")
    boolean addDept(Dept dept);

    @RequestMapping("/dept/get/{id}")
    Dept queryById(@PathVariable("id") Long id);

    @RequestMapping("/dept/list")
    List<Dept> queryAll();

}

3.创建feign的服务consumer-dept-feign
application.yml配置

server:
  port: 80
eureka:
  client:
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka,http://eureka7001.com:7001/eureka,http://eureka7003.com:7003/eureka
spring:
  application:
    name: consumer-dept

restTemplate配置

@SpringBootConfiguration
public class ConfigBean {

    //配置负载均衡实现restTemplate
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

controller

@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

//    private static final String REST_FUL_PREFIXX="http://127.0.0.1:8001";
//    private static final String REST_FUL_PREFIXX="http://PROVIDER-DEPT";
    @Autowired
    private DeptClientService deptClientService;

    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        return deptClientService.queryById(id);
    }

    @RequestMapping("/consumer/dept/add ")
    public boolean add(Dept dept){
        return deptClientService.addDept(dept);
    }

    @RequestMapping("/consumer/dept/list")
    public List<Dept> list(){
        return deptClientService.queryAll();
    }

}

启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.qf.scloudbibik"})
public class DeptConsumerApplication_80 {

    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerApplication_80.class,args);
    }
}

三.Hystrix

分布式系统面临的问题

  复杂分布式系统结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败

服务雪崩

多个微服务之间调用的时候,假设微服务A 调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的‘扇出’,如果扇出的链路上某个 微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的‘雪崩效应’

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的资源都在几秒内饱和,比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的练级故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统

1.什么是hystrix

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

‘断路器’本身是一种开关装置,当某个服务单元发生故障时,通过断路器的故障监控(类似熔断保险丝),向调用方法返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩

能干嘛:

  • 服务降级
  • 服务熔断
  • 服务限流
  • 接近实时的监控
2.hystrix:服务熔断
1.添加依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
2.启动类上添加注解

@SpringBootApplication
@EnableEurekaClient     //在服务启动自动注册到eureka中
@EnableDiscoveryClient  //服务发现
@EnableCircuitBreaker   //添加对熔断的支持
public class DeptProviderApplicaitonHystrix_8001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProviderApplicaitonHystrix_8001.class,args);
    }
}
3.编写配置

@RestController
public class DeptController {

    @Autowired
    private IDeptService deptService;

    @RequestMapping("/dept/get/{id}")
    //当该方法出现异常是会执行回调函数fallbackMethod
    @HystrixCommand(fallbackMethod = "hystrixGet")
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);
        if(dept==null){
            throw new RuntimeException("id"+id+",该用户不存在,找不到信息");
        }
        return dept;
    }

    //备选方法
    public Dept hystrixGet(@PathVariable("id") Long id){
        return new Dept()
                .setDeptno(id)
                .setDname("id"+id+",该用户不存在,找不到信息")
                .setDb_source("no this database in Mysql");
    }

}
3.hystrix:服务降级

编写服务降级的类


public class DeptClientServiceFallbackFactory implements FallbackFactory {
    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public boolean addDept(Dept dept) {
                return false;
            }

            @Override
            public Dept queryById(Long id) {
                return new Dept()
                        .setDeptno(id)
                        .setDname("id:"+id+",客户端提供了降级的信息,这个服务当前已被关闭")
                        .setDb_source("~~~~请稍后查询");
            }

            @Override
            public List<Dept> queryAll() {
                return null;
            }
        };
    }
}

在接口中声明

//value值为服务的名称
@FeignClient(value = "PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {

    @RequestMapping("/dept/add")
    boolean addDept(Dept dept);

    @RequestMapping("/dept/get/{id}")
    Dept queryById(@PathVariable("id") Long id);

    @RequestMapping("/dept/list")
    List<Dept> queryAll();

}

在消费者的application.yml中开启服务降级

    #开启降级
feign:
  hystrix:
    enabled: true

启动eureka,服务提供者和消费者,在请求http://localhost/consumer/dept/get/1成功之后,将服务提供者关闭,再次访问该页面出现如下页面:说明配置成功
在这里插入图片描述

4.hystrix-dashboard监控

创建consumer-hystrix-dashboard服务

导入依赖

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix-dashboard -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
            <version>2.2.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.qf</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
    </dependencies>

再修改端口并开启监控注解

@SpringBootApplication
@EnableHystrixDashboard     //开启监控
public class DeptConsumerDashBoard_9001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerDashBoard_9001.class,args);
    }
}

在需要监控的服务里添加依赖

<!--完善监控信息-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

在provider-dept-hystrix-8001中添加一个配置

	@Bean
    public ServletRegistrationBean registrationBean(){
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        servletRegistrationBean.addUrlMappings("/actuator/hystrix.stream");
        return servletRegistrationBean;
    }

分别启动eureka7001,provider-dept-hystrix-8001,comsumer-hystrix-dashboard三个服务
访问localhost:9001/hystrix,出现如下画面:
在这里插入图片描述
然后将http://localhost:8001/actuator/hystrix.stream粘贴到上面的页面中,delay填个2000,标题随便填,进入监控页面,每当访问localhost:8001/dept/get/1,下面的图示信息随之改变
在这里插入图片描述
实心圆:共有两种含义。它通过颜色的变化代表了实例的健康程度,它的健康程度从 绿色 > 黄色 > 橙色 > 红色 递减;

该实心圆除了颜色的变化之外,它的大小也会根据实例的请求流量发生变化,流量越大实心圆就越大,所以通过该实心圆的展示,就可以在大量实例中快速的发现故障实例和高压力实例
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值