Spring Cloud 之 Feign,Hystrix 和 Gateway

Feign声明式服务调用

Feign概述

• Feign 是一个声明式的 REST 客户端,它用了基于接口的注解方式,很方便实现客户端配置。
• Feign 最初由 Netflix 公司提供,但不支持SpringMVC注解,后由SpringCloud 对其封装,支持了SpringMVC注 解,让使用者更易于接受。

  • Feign自动集成Ribbon,且默认开启相关功能
  • Feign自动集成Hystrix,但默认关闭,需要手动开启

Feign 快速入门

  1. 在消费端引入 open-feign 依赖
  2. 编写Feign调用接口
  3. 在启动类 添加 @EnableFeignClients 注解,开启Feign功能
  4. 测试调用

Feign依赖:

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-openfeignartifactId>
dependency>

Feign调用接口:

package com.itheima.consumer.feign;

import com.itheima.consumer.FeignLogConfig;
import com.itheima.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * feign声明式接口,发起远程调用
 * String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
 * Goods goods = restTemplate.getForObject(url, Goods.class);
 *
 * 1.定义接口
 * 2.接口上添加注解,@FeignClient,设置属性为 服务提供者的 应用名称,日志级别配置类
 * 3.编写调用接口,接口的声明规则和提供方接口保持一致
 * 4.注入该接口,调用接口方法完成远程调用
 */

@FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
public interface GoodsFeignClient {
     

    @GetMapping("/goods/findOne/{id}")
    public Goods findGoodsById(@PathVariable("id") int id);

}

package com.itheima.consumer.controller;


import com.itheima.consumer.domain.Goods;
import com.itheima.consumer.feign.GoodsFeignClient;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

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

    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private GoodsFeignClient goodsFeignClient;


    @GetMapping("/goods/{id}")
    public Goods findGoodsById(@PathVariable("id") int id){
     
        
        Goods goods = goodsFeignClient.findGoodsById(id);
        return goods;
    }
}

启动类 开启Feign功能

package com.itheima.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableDiscoveryClient // 激活DiscoveryClient
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients //开启Feign功能
public class ConsumerApp {
     


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

Feign - 超时设置

服务调用方配置
• Feign 底层依赖于 Ribbon 实现负载均衡和远程调用。
• Ribbon默认1秒超时。
• 超时配置:
在这里插入图片描述

Feign - 日志记录

开启SpringBoot框架的debug日志

  • 开启全部
# 设置当前的日志级别 debug,feign只支持记录debug级别的日志
logging:
  level:
    root: debug
  • 开启部分
logging:
  level:
    com.itheima: debug

服务调用方配置
• Feign 只能记录 debug 级别的日志信息。
在这里插入图片描述

• 定义Feign日志级别Bean

服务调用方根包下定义日志级别

package com.itheima.consumer;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;



@Configuration
public class FeignLogConfig {
     
    /**
     * NONE:不记录
     * BASIC:记录基本的请求行,响应状态码数据
     * HEADERS:记录基本的请求行,响应状态码,记录响应头信息
     * FULL:记录完整的请求 响应数据
     * @return
     */
    @Bean
    public Logger.Level debug(){
     
        return Logger.Level.FULL;
    }
}

• 启用该Bean:
@FeignClient(configuration = XxxConfig.class)

package com.itheima.consumer.feign;

import com.itheima.consumer.FeignLogConfig;
import com.itheima.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * feign声明式接口,发起远程调用
 * String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
 * Goods goods = restTemplate.getForObject(url, Goods.class);
 *
 * 1.定义接口
 * 2.接口上添加注解,@FeignClient,设置属性为 服务提供者的 应用名称,日志级别配置类
 * 3.编写调用接口,接口的声明规则和提供方接口保持一致
 * 4.注入该接口,调用接口方法完成远程调用
 */

@FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
public interface GoodsFeignClient {
     

    @GetMapping("/goods/findOne/{id}")
    public Goods findGoodsById(@PathVariable("id") int id);

}

Hystrix 熔断器

Hystrix 概述

• Hystix 是 Netflix 开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败(雪崩)。

Hystix 主要功能

  • 隔离:用于隔离不同调用链之间相互不受影响
    1.线程池隔离
    2.信号量隔离
  • 降级:封装友好的错误提示并返回
    1.异常
    2.超时
  • 熔断:当请求错误率较高时,自动降级熔断
  • 限流:合理分配每个调用的并发请求数量

Spring Cloud 之 Feign,Hystrix 和 Gateway_第1张图片

Hystrix 降级

• Hystix 降级:当服务发生异常或调用超时,返回默认数据
Spring Cloud 之 Feign,Hystrix 和 Gateway_第2张图片

Hystrix 降级 - 服务提供方

  1. 在服务提供方,引入 hystrix 依赖
  2. 定义降级方法
  3. 使用 @HystrixCommand 注解配置降级方法
  4. 在启动类上开启Hystrix功能:@EnableCircuitBreaker
package com.itheima.provider.controller;

import com.itheima.provider.domain.Goods;
import com.itheima.provider.service.GoodsService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * Goods Controller 服务提供方
 */

@RestController
@RequestMapping("/goods")
public class GoodsController {
     

    @Autowired
    private GoodsService goodsService;

    @Value("${server.port}")
    private int port;

    /**
     * 降级
     * 1.出现异常
     * 2.服务器调用超时
     * @param id
     * @return
     */

    @GetMapping("/findOne/{id}")
    //指定降级后调用的方法名称
    @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
     
            //设置hystrix的超时时间,默认1秒
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public Goods findOne(@PathVariable("id") int id){
     

        int i = 1/0;
        try {
     
            Thread.sleep(2000);
        } catch (InterruptedException e) {
     
            e.printStackTrace();
        }
        Goods goods = goodsService.findOne(id);

        goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
        return goods;
    }

    /**
     * 定义降级方法:
     * 返回值,参数和原方法一致
     */

    public Goods findOne_fallback(int id){
     
        Goods goods = new Goods();
        goods.setTitle("降级了.....");
        return goods;
    }
}

Hystrix 降级 - 服务消费方

  1. feign 组件已经集成了hystrix 组件。
  2. 定义feign 调用接口实现类,复写方法,即 降级方法
  3. 在 @FeignClient 注解中使用 fallback 属性设置降级处理类。
  4. 配置开启 feign.hystrix.enabled = true

Spring Cloud 之 Feign,Hystrix 和 Gateway_第3张图片

package com.itheima.consumer.feign;


import com.itheima.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;



@FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class)
public interface GoodsFeignClient {
     


    @GetMapping("/goods/findOne/{id}")
    public Goods findGoodsById(@PathVariable("id") int id);

}

package com.itheima.consumer.feign;

import com.itheima.consumer.domain.Goods;
import org.springframework.stereotype.Component;

/**
 * feign的客户端降级处理类
 * 1.定义类:实现feign客户端接口
 * 2.使用@Component注解将该类的Bean加入到Spring中
 */
@Component
public class GoodsFeignClientFallback implements GoodsFeignClient {
     
    @Override
    public Goods findGoodsById(int id) {
     
        Goods goods = new Goods();
        goods.setTitle("又降级了...");
        return goods;
    }
}

# 开启feign对hystrix的支持
feign:
  hystrix:
    enabled: true

Hystrix 熔断

• Hystrix 熔断机制,用于监控微服务调用情况,当失 败的情况达到预定的阈值(5秒失败20次),会打开 断路器,拒绝所有请求,直到服务恢复正常为止。
• circuitBreaker.sleepWindowInMilliseconds:监控时间
• circuitBreaker.requestVolumeThreshold:失败次数
• circuitBreaker.errorThresholdPercentage:失败率
Spring Cloud 之 Feign,Hystrix 和 Gateway_第4张图片
Spring Cloud 之 Feign,Hystrix 和 Gateway_第5张图片

Gateway 网关

网关概述

Spring Cloud 之 Feign,Hystrix 和 Gateway_第6张图片

Gateway 网关快速入门

  1. 搭建网关模块
  2. 引入依赖:starter-gateway
  3. 编写启动类
  4. 编写配置文件
  5. 启动测试

依赖:


        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-gatewayartifactId>
        dependency>

配置文件:

server:
  port: 80

spring:
  application:
    name: api-gateway-server

  cloud:
    # 网关配置
    gateway:
      # 路由配置:转发规则
      routes: #集合
        #id:唯一标识,默认是一个uuid
        #uri:转发路径
        #predicates:条件,用于请求网关路径的匹配规则
        - id: gateway-provider
          # uri: http://localhost:8001/
          uri: lb://GATEWAY-PROVIDER
          predicates:
          - Path=/goods/**
          filters:
          - AddRequestParameter=username,zhangsan

        - id: gateway-consumer
          # uri: http://localhost:9000/
          uri: lb://GATEWAY-CONSUMER
          predicates:
          - Path=/order/**

      discovery:
        locator:
          enabled: true # 设置为true,请求路径前可以加微服务名称
          lower-case-service-id: true # 允许小写



eureka:
  client:
    service-url:
      defealtZone: http://localhost:8761/eureka

Gateway 网关路由配置

uri:
静态路由:http://locathost:8080/
动态路由:lb://服务名称

Gataway 过滤器

Spring Cloud 之 Feign,Hystrix 和 Gateway_第7张图片

Gateway 过滤器 – 局部过滤器

Spring Cloud 之 Feign,Hystrix 和 Gateway_第8张图片

Gateway 过滤器 – 全局过滤器

Spring Cloud 之 Feign,Hystrix 和 Gateway_第9张图片
自定义全局过滤器

package com.itheima.gateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class MyFilter implements GlobalFilter, Ordered {
     
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
     

        System.out.println("自定义全局过滤器执行了...");

        return chain.filter(exchange);//放行
    }

    /**
     * 过滤器排序
     * @return 数值越小,越先执行
     */
    @Override
    public int getOrder() {
     
        return 0;
    }
}

你可能感兴趣的:(网关,过滤器,spring,java,spring,boot)