SpringCloud(二)

Spring Cloud Feign

Feign简介

Feign [feɪn] 译文 伪装。Feign是一个声明式WebService客户端.使用Feign能让编写WebService客户端更加简单,它的使用方法是定义一个接口,然后在上面添加注解。不再需要拼接URL,参数等操作。项目主页:https://github.com/OpenFeign/feign 。

  • 集成Ribbon的负载均衡功能
  • 集成了Hystrix的熔断器功能
  • 支持请求压缩
  • 大大简化了远程调用的代码,同时功能还增强了
  • Feign以更加优雅的方式编写远程调用代码,并简化重复代码

实现

(1)导入依赖
user-consumer中添加spring-cloud-starter-openfeign依赖

<!--配置feign-->
<dependency>    
<groupId>org.springframework.cloud</groupId>    
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

(2)创建Feign客户端
在这里插入图片描述

Feign会通过动态代理,帮我们生成实现类。 注解@FeignClient声明Feign的客户端,注解value指明服务名称
接口定义的方法,采用SpringMVC的注解。Feign会根据注解帮我们生成URL地址
注解@RequestMapping中的/user,不要忘记。因为Feign需要拼接可访问地址

(3)编写控制层
在Controller中使用@Autowired注入FeignClient,代码如下:

@RestController
@RequestMapping(value = "/feign")
public class ConsumerFeignController {

    @Autowired
    private UserClient userClient;

    /****
     * 使用Feign调用user-provider的方法
     */
    @RequestMapping(value = "/{id}")
    public User queryById(@PathVariable(value = "id")Integer id){
        return userClient.findById(id);
    }
}

(4)开启Feign
修改user-consumer的启动类,在启动类上添加@EnableFeignClients注解,开启Feign,代码如下:
在这里插入图片描述
(5)测试

请求<http://localhost:18082/feign/2>,效果如下:

在这里插入图片描述

负载均衡

Feign自身已经集成了Ribbon,因此使用Feign的时候,不需要额外引入依赖。
在这里插入图片描述
Feign内置的ribbon默认设置了请求超时时长,默认是1000,可以修改

ribbon内部有重试机制,一旦超时,会自动重新发起请求。如果不希望重试可以关闭配置:

# 修改服务地址轮询策略,默认是轮询,配置之后变随机
user-provider:
  ribbon:
    #轮询
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
    ConnectTimeout: 10000 # 连接超时时间
    ReadTimeout: 2000 # 数据读取超时时间
    MaxAutoRetries: 1 # 最大重试次数(第一个服务)
    MaxAutoRetriesNextServer: 0 # 最大重试下一个服务次数(集群的情况才会用到)
    OkToRetryOnAllOperations: false # 无论是请求超时或者socket read timeout都进行重试

熔断器支持

feign整合Hystrix熔断器

Feign默认也有对Hystrix的集成!
在这里插入图片描述

  1. 在配置文件application.yml中开启feign熔断器支持
  2. 编写FallBack处理类,实现FeignClient客户端
  3. 在@FeignClient注解中,指定FallBack处理类。
  4. 测试

(1)开启Hystrix

在配置文件application.yml中开启feign熔断器支持:默认关闭

feign:
  hystrix:
    enabled: true # 开启Feign的熔断功能

(2)熔断降级类创建

实现刚才编写的UserClient,作为FallBack的处理类,代码如下:

@Component
public class UserClientFallback implements UserClient{

    /***
     * 服务降级处理方法
     * @param id
     * @return
     */
    @Override
    public User findById(Integer id) {
        User user = new User();
        user.setUsername("Fallback,服务降级。。。");
        return user;
    }
}

(3)指定Fallback处理类
在@FeignClient注解中,指定FallBack处理类在这里插入图片描述
(4)测试

关闭服务消费方,请求<http://localhost:18082/feign/2>,效果如下:在这里插入图片描述

请求压缩

SpringCloudFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。

通过配置开启请求与响应的压缩功能:

feign:
  compression:
    request:
      enabled: true # 开启请求压缩
    response:
      enabled: true

也可以对请求的数据类型,以及触发压缩的大小下限进行设置

feign:
  compression:
    request:
      enabled: true # 开启请求压缩
      mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
      min-request-size: 2048 # 设置触发压缩的大小下限   #以上数据类型,压缩大小下限均为默认值

Feign的日志级别配置

通过loggin.level.xx=debug来设置日志级别。然而这个对Feign客户端不会产生效果。因为@FeignClient注解修饰的客户端在被代理时,都会创建一个新的Feign.Logger实例。我们需要额外通过配置类的方式指定这个日志的级别才可以。

(1)普通日志等级配置

# com.itheima 包下的日志级别都为Debug
logging:
  level:
    com.itheima: debug

(2)Feign日志等级配置

@Configuration
public class FeignConfig {

    /***
     * 日志级别
     * @return
     */
    @Bean
    public Logger.Level feignLoggerLevel(){
        return Logger.Level.FULL;
    }
}

日志级别说明:

Feign支持4中级别:
NONE:不记录任何日志,默认值
BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
HEADERS:在BASIC基础上,额外记录了请求和响应的头信息
FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据

(3)指定配置类
在这里插入图片描述

重启项目,即可看到每次访问的日志在这里插入图片描述

小结

Feign的使用过程

1.引入Feign依赖包
2.创建Feign接口,feign接口中需要指定调用的服务名字
3.使用@EnabledFeignClients启用Feign功能

Feign的负载均衡配置
在配置文件中配置

{spring.application.name}:ribbon:负载均衡属性配置

Feign的熔断配置

1.在application.yml中开启Hystrix
2.给Feign接口创建一个实现类
3.给Feign指定fallback类

Feign的压缩配置

在application.yml中指定压缩属性即可

Feign的日志配置

1.在application.yml中开启普通日志等级
2.创建一个类,定义Feign日志等级
3.在Feign接口中指定定义日志的配置

网关 Spring Cloud Gateway

Gateway 简介

Spring Cloud Gateway 是Spring Cloud团队的一个全新项目,基于Spring 5.0、SpringBoot2.0、Project Reactor 等技术开发的网关。 旨在为微服务架构提供一种简单有效统一的API路由管理方式。

Spring Cloud Gateway 作为SpringCloud生态系统中的网关,目标是替代Netflix Zuul。Gateway不仅提供统一路由方式,并且基于Filter链的方式提供网关的基本功能。例如:安全,监控/指标,和限流。

本身也是一个微服务,需要注册到Eureka

**网关的核心功能:**过滤、路由

核心概念:

  • 路由(route):
  • 断言Predicate函数: 路由转发规则
  • 过滤器(Filter):

实现

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">
    <parent>
        <artifactId>springcloud-parent</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>gateway-service</artifactId>

    <dependencies>
        <!--网关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- Eureka客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
</project>

启动类

@SpringBootApplication
@EnableDiscoveryClient// 开启Eureka客户端发现功能
public class GatewayApplication {

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

application.yml配置

# 注释版本
server:
  port: 18084
spring:
  application:
    name: api-gateway # 应用名
# Eureka服务中心配置
eureka:
  client:
    service-url:
      # 注册Eureka Server集群
      defaultZone: http://127.0.0.1:7001/eureka

路由配置

在这里插入图片描述
通过网关配置一个路由功能,用户访问网关的时候,如果用户请求的路径是以/user开始,则路由到user-provider服务去,修改application.yml配置即可实现,配置如下:

spring:
  application:
    # 应用名
    name: api-gateway
  cloud:
    gateway:
      routes:
        #id唯一标识,可自定义
        - id: user-service-route
          #路由的服务地址
          uri: http://localhost:18081
          # 路由拦截的地址配置(断言)
          predicates:
            - Path=/user/**

访问http://localhost:18084/user/find/2会访问user-provider服务,效果如下:
在这里插入图片描述

动态路由

在这里插入图片描述
刚才路由规则中,我们把路径对应服务地址写死了!如果服务提供者集群的话,这样做不合理。应该是根据服务名称,去Eureka注册中心查找服务对应的所有实例列表,然后进行动态路由!
修改映射配置:通过服务名称获取:
修改application.yml

因为已经配置了Eureka客户端,可以从Eureka获取服务的地址信息,修改application.yml文件如下:
在这里插入图片描述
上图代码如下:

spring:
  application:
    # 应用名
    name: api-gateway
  cloud:
    gateway:
      routes:
        #id唯一标识,可自定义
        - id: user-service-route
          #路由的服务地址
          #uri: http://localhost:18081
          #lb协议表示从Eureka注册中心获取服务请求地址
          #user-provider访问的服务名称。
          #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务
          uri: lb://user-provider
          # 路由拦截的地址配置(断言)
          predicates:
            - Path=/user/**

路由配置中uri所用的协议为lb时,gateway将把user-provider解析为实际的主机和端口,并通过Ribbon进行负载均衡。

过滤器

过滤器作为Gateway的重要功能。常用于请求鉴权、服务调用时长统计、修改请求或响应header、限流、去除路径等等…

过滤器的分类

默认过滤器:出厂自带,实现好了拿来就用,不需要实现
  全局默认过滤器
  局部默认过滤器
自定义过滤器:根据需求自己实现,实现后需配置,然后才能用哦。
  全局过滤器:作用在所有路由上。
  局部过滤器:配置在具体路由下,只作用在当前路由上。

默认过滤器几个,常见如下:

过滤器名称说明
AddRequestHeader对匹配上的请求加上Header
AddRequestParameters对匹配上的请求路由
AddResponseHeader对从网关返回的响应添加Header
StripPrefix对匹配上的请求路径去除前缀

详细说明官方链接

默认过滤器配置

默认过滤器有两个:全局默认过滤器和局部默认过滤器。

全局过滤器:对输出响应头设置属性

对输出的响应设置其头部属性名称为X-Response-Default-MyName,值为study

修改配置文件

spring:
  cloud:
    gateway:
     # 配置全局默认过滤器
      default-filters:
      # 往响应过滤器中加入信息
        - AddResponseHeader=X-Response-Default-MyName,itheima

查看浏览器响应头信息!
在这里插入图片描述
局部过滤器:
通过局部默认过滤器,修改请求路径。局部过滤器在这里介绍两种:添加路径前缀、去除路径前缀。

第一:添加路径前缀:

在gateway中可以通过配置路由的过滤器PrefixPath 实现映射路径中的前缀

配置请求地址添加路径前缀过滤器
在这里插入图片描述
上图配置如下:

spring:
  application:
    # 应用名
    name: api-gateway
  cloud:
    gateway:
      routes:
        #id唯一标识,可自定义
        - id: user-service-route
          #路由的服务地址
          #uri: http://localhost:18081
          #lb协议表示从Eureka注册中心获取服务请求地址
          #user-provider访问的服务名称。
          #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务
          uri: lb://user-provider
          # 路由拦截的地址配置(断言)
          predicates:
            - Path=/**
          filters:
            # 请求地址添加路径前缀过滤器
            - PrefixPath=/user
      default-filters:
        - AddResponseHeader=X-Response-Default-MyName,itheima

路由地址信息:

配置访问地址路由地址
PrefixPath=/userhttp://localhost:18084/find/2http://localhost:18081/user/find/2

第二:去除路径前缀:
在gateway中通过配置路由过滤器StripPrefix,实现映射路径中地址的去除。通过StripPrefix=1来指定路由要去掉的前缀个数。如:路径/api/user/1将会被路由到/user/1。

配置去除路径前缀过滤器
在这里插入图片描述
上图配置如下:

spring:
  application:
    # 应用名
    name: api-gateway
  cloud:
    gateway:
      routes:
        #id唯一标识,可自定义
        - id: user-service-route
          #路由的服务地址
          #uri: http://localhost:18081
          #lb协议表示从Eureka注册中心获取服务请求地址
          #user-provider访问的服务名称。
          #路由地址如果通过lb协议加服务名称时,会自动使用负载均衡访问对应服务
          uri: lb://user-provider
          # 路由拦截的地址配置(断言)
          predicates:
            - Path=/**
          filters:
            # 请求地址添加路径前缀过滤器
            #- PrefixPath=/user
            # 去除路径前缀过滤器
            - StripPrefix=1
      default-filters:
        - AddResponseHeader=X-Response-Default-MyName,itheima

路由地址信息:

配置访问地址路由地址
StripPrefix=1http://localhost:18084/api/user/find/2http://localhost:18081/user/find/2
StripPrefix=2http://localhost:18084/api/r/user/find/2http://localhost:18081/user/find/2

自定义过滤器

gateway-service中创建com.itheima.filter.LoginGlobalFilter全局过滤器类,代码如下:

@Component
public class LoginGlobalFilter implements GlobalFilter, Ordered {

    /***
     * 过滤拦截
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求参数
        String token = exchange.getRequest().getQueryParams().getFirst("token");

        //如果token为空,则表示没有登录
        if(StringUtils.isEmpty(token)){
            //没登录,状态设置403
            exchange.getResponse().setStatusCode(HttpStatus.PAYLOAD_TOO_LARGE);
            //结束请求
            return exchange.getResponse().setComplete();
        }

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

    /***
     * 定义过滤器执行顺序
     * 返回值越小,越靠前执行
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

测试:不携带token <http://localhost:18084/api/user/find/2>效果如下:
在这里插入图片描述
测试:携带token <http://localhost:18084/api/user/find/2?token=abc> 此时可以正常访问。

局部过滤器定义

自定义局部过滤器,该过滤器在控制台输出配置文件中指定名称的请求参数及参数的值,以及判断是否携带请求中参数,打印.
在gateway_service中编写MyParamGatewayFilterFactory类

@Component
public class MyParamGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
    /**
     * 处理过程  默认需要在配置配置文件中配置 NAME ,VALUE
     *
     * @param config
     * @return
     */
    public GatewayFilter apply(NameValueConfig config) {

        return new GatewayFilter() {
            //- MyParam=name,value
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                String name111 = config.getName();//获取参数名name的值
                String value111 = config.getValue();//获取参数名value的值
                System.out.println("获取配置中的参数的NAME值:" + name111);
                System.out.println("获取配置中的参数的VALUE值:" + value111);
                //获取参数值
                String name = exchange.getRequest().getQueryParams().getFirst("name");
                if (!StringUtils.isEmpty(name)) {
                    System.out.println("哈哈:" + name);
                }
                //添加到头信息或者作为参数传递等等.
                return chain.filter(exchange);
            }
        };
    }
}

修改application.yml配置文件在这里插入图片描述
测试访问,检查后台是否输出name和itheima;访问<http://localhost:18084/api/user/find/2?name=itheima&tomen=aaa>会输出。

微服务架构加入Gateway后

在这里插入图片描述

  • 不管是来自客户端的请求,还是服务内部调用。一切对服务的请求都可经过网关。
  • 网关实现鉴权、动态路由等等操作。
  • Gateway就是我们服务的统一入口

Spring Cloud Bus

SpringCloud Bus,解决上述问题,实现配置自动更新。

注意:SpringCloudBus基于RabbitMQ实现,默认使用本地的消息队列服务,所以需要提前安装并启动RabbitMQ。

Bus简介

Bus是用轻量的消息代理将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。

Bus可以为微服务做监控,也可以实现应用程序之间互相通信。Bus可选的消息代理RabbitMQ和Kafka。

广播出去的配置文件服务会进行本地缓存。

整合案例

目标:消息总线整合入微服务系统,实现配置中心的配置自动更新。不需要重启微服务。

改造配置中心

  1. 在config-server项目中加入Bus相关依赖
  2. 修改application.yml,加入RabbitMQ的配置信息,和暴露触发消息总线地址

实现过程

<!--消息总线依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-bus</artifactId>
</dependency>
<!--RabbitMQ依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>

application.yml配置文件
修改config-server的application.yml,如下配置的rabbit都是默认值,其实可以完全不配置,代码如下:
在这里插入图片描述

# 注释版本
server:
  port: 18085 # 端口号
spring:
  application:
    name: config-server # 应用名
  cloud:
    config:
      server:
        git:
          # 配置gitee的仓库地址
          uri: https://gitee.com/skllll/config.git
  # rabbitmq的配置信息;如下配置的rabbit都是默认值,其实可以完全不配置
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
# 暴露触发消息总线的地址
management:
  endpoints:
    web:
      exposure:
        # 暴露触发消息总线的地址
        include: bus-refresh

# Eureka服务中心配置
eureka:
  client:
    service-url:
      # 注册Eureka Server集群
      defaultZone: http://127.0.0.1:7001/eureka
# com.itheima 包下的日志级别都为Debug
logging:
  level:
    com: debug

改造用户服务

引入依赖

<!--消息总线依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-bus</artifactId>
</dependency>
<!--RabbitMQ依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<!--健康监控依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

添加bootstrap.yml文件
user-provider的resources目录下添加bootstrap.yml,添加rabbitmq配置,代码如下:

# 注释版本
spring:
  cloud:
    config:
      name: user-provider # 与远程仓库中的配置文件的application保持一致,{application}-{profile}.yml
      profile: dev # 远程仓库中的配置文件的profile保持一致
      label: master # 远程仓库中的版本保持一致
      discovery:
        enabled: true # 使用配置中心
        service-id: config-server # 配置中心服务id
# rabbitmq的配置信息;如下配置的rabbit都是默认值,其实可以完全不配置
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
#向Eureka服务中心集群注册服务
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka

添加刷新配置
添加一个@RefreshScope注解刷新配置信息,代码如下:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值