SpringCloud02(远程调用Feign,网关Gateway,配置中心Nacos)

目录

一、远程调用Feign【要会用】

1. Feign简介

1 什么是Feign

2 准备基础代码

2. Feign入门【重点】

步骤

实现

测试

3. Feign配置Ribbon

1 说明

2 配置

4. Feign配置日志

1 说明

2 步骤

5. Feign使用优化

1 说明

2 步骤

6. 小结

二、网关Gateway

1. 网关简介

1 网关简介

2 Gateway简介

2. Gateway入门【重点】

1 核心概念

路由Route

断言Predicate

过滤器Filter

2 入门示例

说明

步骤

实现

测试

3. Gateway断言

4. Gateway过滤器【重点】

1 说明

2 GatewayFilter

常见的内置局部过滤器

局部过滤器使用示例

3 GlobalFilter全局过滤器

自定义全局过滤器【重点】

说明

示例

练习:校验token

4 过滤器执行顺序【了解】

5. 跨域问题

1 浏览器的同源策略

什么是同源策略

什么是跨域问题

2 模拟跨域问题

3 解决跨域问题

6. 小结

三、配置中心Nacos

1. 配置中心简介

1 微服务的配置问题

2 配置问题的解决方案

2. 配置中心Nacos入门【重点】

1 把配置文件托管到nacos

2 从nacos上拉取配置

3. 配置参数的动态刷新

4. 配置共享【拓展】

1. 准备多环境配置

1 准备dev和test两个配置文件

2 准备多环境的启动链接

2. 多环境配置共享

1 创建共享配置文件

2 读取配置参数值

3 启动测试

3. 配置共享的优先级

5. 小结

大总结


什么是微服务:是一种经过良好设计的分布式架构。微服务特征:

  • 职责单一:每个服务只做一件事,服务的粒度非常细

  • 服务自治:每个服务可以有独立的团队、独立的技术、独立的数据、独立交付部署

  • 面向服务:所有服务都要遵循相同的协议暴露访问接口。SpringCloud使用的是HTTP协议

  • 服务隔离:服务之间应该做好隔离与保护,防止出现服务雪崩

微服务核心组件:

  • 注册中心:解决服务治理问题的组件。Nacos,Eureka

  • 远程调用:解决服务之间互相访问的组件,发起远程调用。HttpClient、RestTemplate、Feign

  • 服务保护:解决服务之间的隔离,防止出现雪崩。Sentinel,Hystrix

  • 配置中心:解决服务的配置文件散乱、不好处理的问题。Nacos,SpringCloudConfig

  • 服务网关:解决 众多微服务对象提供统一的访问入口。SpringCloudGateway, Zuul

注册中心Nacos-使用入门:

  1. 安装启动Nacos。Nacos的管理界面地址是 http://localhost:8848/nacos

  2. 所有微服务要整合Nacos:

    添加依赖:先锁定SpringCloudAlibaba依赖版本,再给每个微服务添加nacos-discovery依赖坐标

    修改配置:每个微服务的配置文件里,需要有两项配置

    • 服务名

    • Nacos的地址

    修改引导类:添加@EnableDiscoveryClient

注册中心Nacos-运行原理:

  • 服务注册:每个服务在启动时都会把自己的地址信息上报给Nacos。由Nacos来维护所有活跃微服务的地址

  • 服务续约:

    临时实例:由微服务定时向Nacos发送心跳进行续约。5s一次心跳,15s没有心跳会被Nacos标记成不健康状态,30s清除服务实例的地址信息

    非临时实例:由Nacos主动探测微服务的健康状态,如果服务有问题也只是标记成不健康状态,不会剔除信息

  • 服务发现(服务拉取):微服务会从Nacos里拉取地址列表

注册中心Nacos-分级存储模型:

  • 每个服务下边可以有多个集群,每个集群里边可以有多个服务实例。实际部署时把相同集群的实例部署到同一机房

  • 好处:灾备,同集群优先访问

  • 给微服务配置集群:只要修改配置文件,设置每个实例所属的集群名称

    spring.cloud.nacos.discovery.cluster-name

注册中心Nacos-实现环境隔离

  • 相同环境名称空间的实例之间,可以互相发现、互相调用

  • 不同环境名称空间的实例之间,是绝对隔离,不可能互相发现、不可能互相调用

  • 做法:

    1. 在Nacos添加名称空间namespace,设置id、名称、描述

    2. 修改每个微服务的配置文件,设置当前服务实例所属的环境名称空间

      spring.cloud.nacos.discovery.namespace=名称空间的id

负载均衡Ribbon-负载均衡的划分

  • 提供者一方的负载均衡:比如nginx。适合于 整个服务端的最前沿,直接面向客户端的访问实现负载均衡

  • 消费者一方的负载均衡:比如Ribbon。适合 微服务之间的互相调用,实现负载均衡

负载均衡Ribbon-使用入门

  • 不需要导依赖,因为很多SpringCloud组件都 内置了Ribbon

  • 不需要额外配置,就有默认的负载均衡效果。默认使用的轮询策略

负载均衡Ribbon-修改负载均衡策略

  • 方式1:修改消费者一方的配置文件

    目标服务名.ribbon.NFLoadBalancerRuleClassName = 负载均衡策略的全限定类名

  • 方式2:使用@Bean把负载均衡策略对象放到IoC容器里

  • 常见的负载均衡策略:

    RandomRule:随机策略

    NacosRule:是Nacos单独提供策略,可以用于实现Nacos分级存储模型时,同集群的优先访问

    RoundRobinRule:轮询策略

负载均衡Ribbon-饥饿加载

  • 如果不开启饥饿加载:是当第一次访问时,Ribbon才会从Nacos里拉取服务地址列表;第一次访问通常比较慢

  • 如果开启了饥饿加载:是当微服务启动时,就立即从Nacos里拉取服务地址列表

  • 修改配置文件:

ribbon:
    eager-load:
        enabled: 是否开启
        clients: 
            - 目标服务名
            - 目标服务名

一、远程调用Feign【要会用】

本章节学习目标:

  • 能够使用Feign进行远程调用
  • 能够给Feign配置日志输出

1. Feign简介

1 什么是Feign

Feign是Netflix公司提供服务调用组件,单独使用Feign比较麻烦。SpringCloud对Feign做了集成封装,提供了声明式服务调用组件Open-Feign。

Open-Feign支持SpringMVC注解。是Spring Cloud提供的一个声明式的伪Http客户端,它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。

Feign默认集成了Ribbon,所以使用Feign默认就具备负载均衡的效果。

2 准备基础代码

以SpringCloud第1天的服务拆分后的代码为基础:

  • 只要再整合Nacos即可,不需要配置Nacos的cluster-name、namespace

  • 不需要RestTemplate,也不需要配置负载均衡策略

父工程依赖

<!--打包方式:pom-->
<packaging>pom</packaging>

<!--SpringBoot父工程坐标-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.9.RELEASE</version>
    <relativePath/>
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <mysql.version>8.0.31</mysql.version>
    <mybatisplus.version>3.4.1</mybatisplus.version>
</properties>

<!--预先锁定依赖版本号-->
<dependencyManagement>
    <dependencies>
        <!--SpringCloudAlibaba-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.2.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <!-- MybatisPlus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatisplus.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

微服务依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
    </dependency>
</dependencies>

用户服务的配置文件

server:
  port: 8080
spring:
  application:
    name: user-service #当前应用服务的名称。可以随意设置,但是不能重复。通常拿模块名作为服务名
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud_user
    username: root
    password: root
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 
logging:
  level:
    com.itheima.user: debug
  pattern:
    dateformat: MM-dd HH:mm:ss.SSS

订单服务的配置文件

server:
  port: 7070
spring:
  application:
    name: order-service
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:///cloud_order
    username: root
    password: root
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
logging:
  level:
    com.itheima.order: debug
  pattern:
    dateformat: MM-dd HH:mm:ss.SSS

用户服务的其它代码

实体类,Mapper接口,Service,Controller,引导类:略

订单服务的其它代码

实体类,Mapper接口,Service,Controller:略

引导类:不需要RestTemplate了,也不需要配置负载均衡策略

@EnableDiscoveryClient
@SpringBootApplication
@MapperScan("com.itheima.order.mapper")
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

2. Feign入门【重点】

步骤

Feign要在调用者一方配置

  1. 锁定SpringCloud依赖版本,并导入openfeign的起步依赖

  2. 创建Feign的Client接口

  3. 在引导类上添加注解@EnableFeignClients("Client接口所在的包名")

  4. 使用Client进行远程调用

实现

1) 添加依赖

给父工程添加SpringCloud依赖的版本锁定。修改父工程的pom.xml,在dependencyManagement里dependencies中添加:

<!-- springCloud -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Hoxton.SR10</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

在order-service中添加open-feign的依赖坐标

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

2) 创建Feign客户端

创建一个UserClient接口,用于配置Feign调用user-service的功能

要求:

  • 接口上添加注解@FeignClient("要调用的服务名")

  • 接口里要有方法

    • 每个方法对应一个请求接口

    • 在方法上添加注解,设置方法的路径。

  • 最终要求:

    • @FeignClient的配置的服务名 + 方法上配置的路径 和 要调用的方法路径相同

    • 例如下边代码中配置的:http://user-service/user/{id}

package com.itheima.order.client;

import com.itheima.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("user-service")
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

        

3) 启用Feign支持

修改引导类,添加注解@EnableFeignClients("Client接口所在的包名")

使用Feign后,不需要再使用RestTemplate了,要把order-service中所有RestTemplate相关的代码全部删除

package com.itheima.order;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@MapperScan("com.itheima.order.mapper")
@EnableFeignClients("com.itheima.order.client")
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

4) 修改调用代码

修改OrderService类,使用UserClient调用用户服务

package com.itheima.order.service;

import com.itheima.order.client.UserClient;
import com.itheima.order.mapper.OrderMapper;
import com.itheima.order.pojo.Order;
import com.itheima.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserClient userClient;

    public Order findById(Long id) {
        Order order = orderMapper.findById(id);

        //使用UserClient调用用户服务
        User user = userClient.findById(order.getUserId());
        order.setUser(user);

        return order;
    }
}

测试

3. Feign配置Ribbon

1 说明

Feign默认已经使用Ribbon做了负载均衡,不需要做额外的配置,还使用Ribbon原本的配置即可

2 配置

配置示例如下:

user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  

4. Feign配置日志

1 说明

在之前的开发中,我们通过修改logging.level来控制日志输出的级别。然后这项配置不会对Feign生效

因为@FeignClient注解的客户端都是接口,我们实际上是通过这个接口的代理对象来进行远程调用的。而每个代理对象都会生成一个新的Feign.Logger实例对象,我们需要额外指定这个日志级别才可以。

步骤:

  1. 修改配置文件,设置整体的日志级别

  2. 创建Feign配置类,注册Logger.Level用于设置Feign的日志级别

2 步骤

1) 设置整体的日志级别

修改order-service的配置文件,设置日志级别为debug

logging:
  level:
    com.itheima: debug

2) 配置Feign的日志级别

以下两种方式,用哪种都行

方式一:@Bean方式

单独为Feign配置一个日志类,设置日志级别

package com.itheima.order.config;

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

@Configuration
public class FeignConfig {
    /**
     * Feign的日志级别,是通过Logger.Level枚举来指定的
     * 它支持4种日志级别:
     *      1. NONE:不输出任何日志,是默认值
     *      2. BASIC:仅输出请求的方式、URL以及响应状态码、执行时间
     *      3. HEADERS:在BASIC基础上,额外输出请求头和响应头信息
     *      4. FULL:输出所有请求和响应的明细,包括头信息、请求体、元数据
     */
    @Bean
    public Logger.Level feignLog(){
        return Logger.Level.FULL;
    }
}

方式二:配置文件方式

修改配置文件application.yaml,添加如下配置:

feign:
  client:
    config:
      default:
        loggerLevel: FULL

3) 测试效果

5. Feign使用优化

1 说明

Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:

  • URLConnection:默认实现,不支持连接池

  • Apache HttpClient :支持连接池

  • OKHttp:支持连接池

因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。

这里我们用Apache的HttpClient来演示,步骤如下:

  1. 添加httpclient的依赖坐标

  2. 配置httpclient连接池

2 步骤

1) 引入依赖

在order-service的pom文件中引入Apache的HttpClient依赖:

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

2) 配置连接池

在order-service的application.yml中添加配置:

feign:
  httpclient:
    enabled: true # 开启feign对HttpClient的支持,默认是true
    max-connections: 200 # 最大的连接数,默认200
    max-connections-per-route: 50 # 每个路径的最大连接数,默认50

3) 测试效果

接下来,在FeignClientFactoryBean中的loadBalance方法中打断点:

Debug方式重启order-service服务,可以看到这里的client,底层就是Apache HttpClient:

 

6. 小结

如果要使用Feign发起远程调用:

  1. 添加依赖:锁定SpringCloud的依赖版本,再添加openfeign的依赖坐标

  2. 编写Feign的接口

    调用某个服务的所有方法,全部写在一个接口里。

    比如有一个UserClient接口,里边所有方法都是用于向user服务发请求调用的

@FeignClient("目标服务名")
public interface UserClient{
    
    @GetMapping("/user/{id}")
    User xxx(@PathVariable("id") Long id);
}

 

  3. 修改引导类,添加@EnableFeignClients("包名")

Feign的原理:Feign会根据我们编写的接口,生成了代理对象。在代理对象里

  • 帮我们构造HTTP请求并发出去

    如果要发GET请求,方法上就加@GetMapping;其它请求方式一样

    调用方法时的实参,想要Feign帮我们作为什么样的参数,就要在形参上加注解。注意:这些注解不能省略

    • @PathVariable:Feign会把调用方法时的实参,绑定到请求路径的变量里

    • @RequestParam:Feign会把调用方法时的实参,作为表单参数发出去

    • @RequestBody:Feign会把调用方法时的实参,通常是以json形式放在请求体里发出去

  • 帮我们接收HTTP响应转换成 方法返回值 对应的类型

Feign的负载均衡:已经集成了Ribbon,用法和之前一模一样

  • 不做任何配置:也有负载均衡效果。默认的负载均衡策略是:轮询

  • 如果要修改负载均衡策略:

    方式1:修改消弱者的配置文件,设置负载均衡策略

    方式2:使用@Bean把负载均衡策略对象放到IoC容器里

  • 如果要实现饥饿加载:修改配置文件,开启饥饿加载,并设置哪些服务需要饥饿加载

Feign运行时要打印日志:

  1. 修改配置文件,设置全局的日志级别为debug

  2. 修改配置文件,设置Feign的日志级别

    feign.client.config.default.loggerLevel,值有4个选项:

    • NONE:不打印日志

    • BASIC:只打印请求行、响应行

    • HEADERS:打印请求行、请求头, 响应行、响应头

    • FULL:打印请求行、头、体, 响应行、头、体

Feign的优化:

  • Feign底层默认使用的URLConnection技术,在HTTP请求时没有使用连接池技术,所以性能较低

  • 性能优化:把Feign底层改用HttpClient,支持连接池。步骤:

    1. 添加httpclient依赖坐标

    2. 修改配置文件,开启httpclient的支持。 feign.httpclient.enabled=true

二、网关Gateway

本章节学习目标:

  • 了解网关的作用
  • 能够使用Gateway搭建网关
  • 能够使用GatewayFilter
  • 能够自定义GlobalFilter

1. 网关简介

1 网关简介

在微服务架构中,一个系统会被拆分为很多个微服务。那么作为消费者要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在消费者一端记录每个微服务的地址,然后分别去调用。

这样的架构,会存在着诸多的问题:

  • 客户端多次请求不同的微服务,需要有微服务的地址,增加客户端代码或配置编写的复杂性

  • 认证复杂,每个服务都需要独立认证。

  • 存在跨域请求,在一定场景下处理相对复杂

上面的这些问题可以借助API网关来解决。所谓的API网关,就是指系统的统一入口。它封装了应用程序的内部结构,为客户端提供统一服务。

一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。

添加上API网关之后,系统的架构图变成了如下所示:

2 Gateway简介

Spring Cloud Gateway是Spring基于Spring5.0、SpringBoot2.0、Project Reactor等技术开发的网关技术

  • 旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

  • 它不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控和限流。

  • 它是用于代替NetFlix Zuul的一套解决方案:webflux

Spring Cloud Gateway组件的核心是一系列的过滤器,通过过滤器可以将客户端的请求转发到应用的微服务(这个过程叫路由)。Spring Cloud Gateway是站在整个微服务最前沿的防火墙和代理器,隐藏微服务节点的ip信息、从而加强安全保护。

Spring Cloud Gateway本身也是一个微服务,需要注册到注册中心

Spring Cloud Gatewa的核心功能是:路由和过滤

 

2. Gateway入门【重点】

1 核心概念

路由Route

一个路由的配置信息,由一个id、一个目的地url、一组断言工厂、一组过滤器组成。

断言Predicate

断言是一种判断规则;如果客户端的请求符合要求的规则,则这次请求将会被路由到目的地

Spring Cloud Gateway的断言函数输入类型是Spring5.0框架中的ServerWebExchange,它允许开发人员自定义匹配来自HTTP请求中任何信息

过滤器Filter

Spring Cloud Gateway中的Filter可以对请求和响应进行过滤修改。是一个标准的Spring WebFilter。它分为两类:

  • Gateway Filter:局部过滤器(路由过滤器),应用于单个路由或者一组路由,通常由SpringCloudGateway内置好

  • Global Filter:全局过滤器,应用于所有路由

2 入门示例

说明

浏览器通过api网关,将以/user开头的请求转发到用户微服务

步骤
  1. 创建一个模块:网关模块,导入gateway的依赖

  2. 创建引导类:开启服务注册@EnableDiscoveryClient

  3. 创建配置文件:

    • 网关的端口

    • 设置服务名称

    • 设置注册中心的地址

    • 配置网关的路由:给每个微服务设置路由信息

实现

1) 创建模块导入依赖

<dependencies>
    <!-- gateway -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    
    <!-- nacos-discovery -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

2) 创建引导类

package com.itheima;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

3) 编写配置文件

server:
  port: 10000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #注册中心地址
    gateway:
      routes: #路由配置,是个数组
        - id: user-service # 路由id
          uri: lb://user-service #路由目的地的地址: lb 表示从注册中心拉取服务列表,并启用负载均衡
          predicates: #断言,什么样的请求可以到达目标地
            - Path=/user/**

测试

3. Gateway断言

我们在配置文件中写的predicates断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件。例如Path=/user/**是按照路径匹配,这个规则是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的,像这样的断言工厂在SpringCloudGateway还有十几个,而我们需要掌握的只有Path

所有断言工厂的使用方式都是 在网关的路由配置中,使用predicates配置的:

spring:
  cloud:
    gateway:
      routes:
        - id: 路由唯一标识
          uri: lb://user-service #路由目的地的地址
          predicates: #断言,可以配置多个
            - Path=/user/** # - 断言名称=配置值

其它断言工厂参考:Spring Cloud Gateway

4. Gateway过滤器【重点】

1 说明

Gateway的过滤器会对请求或响应进行拦截,完成一些通用操作。在Gateway中, Filter的生命周期(执行时机)只有两个:

  • PRE: 这种过滤器在请求被路由之前调用,可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等

  • POST:这种过滤器在路由到微服务以后执行,可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等

 

Gateway的Filter可分为两种

  • GatewayFilter:应用到单个路由上,是局部过滤器,必须要配置到配置文件

    它需要实现GatewayFilterFactory接口,并且需要在配置文件中配置才会生效;

    GatewayFilter也可以配置为默认过滤器,针对所有路由进行过滤

  • GlobalFilter:应用到所有的路由上,是全局过滤器,不需要配置到配置文件

    它不需要在配置文件中配置,只要实现GlobalFilter接口即可

所有的过滤器都可以参考官方手册 Spring Cloud Gateway

2 GatewayFilter

在SpringCloud Gateway中内置了很多不同类型的网关路由过滤器,

  • 这些过滤器如果配置到单个路由下,就只针对这个路由进行过滤

  • 如果配置到default-filters下,就针对所有路由进行过滤

常见的内置局部过滤器

网关过滤器列表如下:

局部过滤器使用示例

在网关中给用户服务和订单服务做了路由配置,要求:

  • 当浏览器访问用户服务时,添加一个响应头:abc=user service

  • 当浏览器访问订单服务时,添加一个响应头:aaa=order service is strong

  • 当浏览器访问任意服务时,添加一个响应头:company=itcast

配置过滤器

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        - id: user-service #用户服务的路由配置
          uri: lb://user-service
          predicates:
            - Path=/user/**
          filters:
            - AddResponseHeader=abc, user service is strong
        - id: order-service #订单服务的路由配置
          uri: lb://order-service
          predicates:
            - Path=/order/**
          filters:
            - AddResponseHeader=aaa, order service works great
      default-filters: #添加到这里的过滤器,对所有路由都生效
        - AddResponseHeader=company, itcast

测试效果

  • 重启网关服务

  • 打开浏览器F12的Network进行抓包

访问网址 http://localhost:10000/order/101,可以看到有两个响应头

访问网址 http://localhost:10000/user/1,可以看到有两个响应头

3 GlobalFilter全局过滤器

内置全局过滤器

全局过滤器作用于所有路由,而且无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。

SpringCloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理。如下:

自定义全局过滤器【重点】
说明

内置的过滤器已经可以完成大部分的功能,但是对于企业开发的一些业务功能处理,还是需要我们自己编写过滤器来实现的。

示例
  • 全局过滤器类必须实现GlobalFilter接口,重写filter方法,在filter方法里实现过滤逻辑

  • 全局过滤器类可以实现Ordered接口,重写getOrder方法,如果需要设置过滤器执行顺序的话

  • 类上要加注解@Component

@Component
public class DemoGlobalFilter implements Ordered, GlobalFilter {
    /**
     * 执行过滤的方法
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //如果要处理请求,就从exchange里获取request对象
        ServerHttpRequest request = exchange.getRequest();
        //  获取请求路径
        System.out.println("本次请求路径:" + request.getURI());
        //  获取请求头
        System.out.println("请求头Host:" + request.getHeaders().getFirst("Host"));


        //如果要处理响应,就从exchange里获取response对象
        ServerHttpResponse response = exchange.getResponse();
        //  设置响应状态码
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        //  设置响应cookie
        response.addCookie(ResponseCookie.from("cookieName", "cookieValue").build());
        //  结束本次请求,并返回响应
        // return response.setComplete();

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

    /**
     * 设置过滤器的执行顺序,值越小,执行的越早
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

 

练习:校验token

下面,我们一起通过代码的形式自定义一个过滤器,实现用户鉴权

  • 如果本次请求携带了请求头Authorization(token值),则放行;

  • 否则不放行,并且返回状态码401

package com.itheima.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
public class AuthGlobalFilter implements GlobalFilter , Ordered{
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		//获取请求头Authorization
        List<String> authorization = exchange.getRequest().getHeaders().get("Authorization");
        //如果获取不到Authorization
        if (authorization == null || authorization.size() == 0) {
            System.out.println("鉴权失败");
            //设置响应状态码
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            //结束本次调用
            return exchange.getResponse().setComplete();
        }

        //放行到下一个过滤器
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        //数值越小,执行的优先级越高
        return 0;
    }
}

4 过滤器执行顺序【了解】

当一次请求进入网关后,网关会:

  1. 找到所有能拦截本次请求的所有过滤器,包括:GatewayFilter、GlobalFilter

  2. 根据所有过滤器的Order排序值进行排序,值越小,优先级越高,执行的越早

    GlobalFilter全局过滤器的排序值:通过实现Ordered接口或者添加@Order注解来指定Order值

    GatewayFilter局部过滤器排序值:由框架指定order值,默认按照声明的顺序从1开始递增

  3. 如果过滤器的Order值相同,优先级:GlobalFilter > defaultFilter > GatewayFilter

5. 跨域问题

1 浏览器的同源策略

什么是同源策略

1995年,同源策略由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个同源策略。它是指:一个页面,只允许访问与页面同源的某些资源。

  • 所谓的同源包含:同协议、同域名(同IP)、同端口。假如有一个资源是http://www.itcast.cn/a.html,那么:

    https://www.itcast.cn/user/1:不同源,因为协议不同

    http://itcast.cn/user/1:不同源,因为域名不同

    http://www.itcast.cn:81/user/1:不同源,因为端口不同

    http://www.itcast.cn/user/1:同源,因为同协议、同域名、同端口

  • 被同源限制的资源有:

    • Cookie、LocalStorage 和 IndexDB:只能同源的页面进行访问

    • DOM和js对象 :只能同源的页面才能获得

    • AJAX :只能向同源的资源发Ajax请求

什么是跨域问题

如果http://localhost:80/index.html页面上要发起一个Ajax请求,请求的目的地是:http://localhost:8080/user/1,这就是一个跨域Ajax请求了。

受限于浏览器的同源策略,这次请求是必定发送不成功的

但是目前流行的开发方式是前后端分离,即前端资源使用nginx部署到单独的服务器上,服务端项目部署到其它服务器上,这样的情况下,跨域请求就不可避免了。我们该如何规避浏览器的同源策略,允许浏览器跨域发送Ajax请求呢?

2 模拟跨域问题

  1. 把资料里的index.html放到Nginx的html目录里,nginx端口使用80

   2. 启动Nginx,打开浏览器访问http://localhost/index.html

点击页面上的按钮,发送一次Ajax请求。使用抓包工具可以看到报错

3 解决跨域问题

只需要在网关里添加如下配置即可:

spring:
  cloud:
    gateway:
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: "*" # 允许哪些网站的跨域请求。 *表示任意网站
            allowedMethods: # 允许的跨域ajax的请求方式
            - "GET"
            - "POST"
            - "DELETE"
            - "PUT"
            - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

6. 小结

搭建服务网关,前提:网关也是一个微服务,也需要整合注册中心Nacos

  1. 添加依赖:nacos-discovery注册中心相关的依赖,网关的依赖

  2. 添加配置:

    本身的访问端口

    整合注册中心需要的配置:应用服务名,注册中心地址

    网关本身的路由等配置

  3. 修改引导类:整合注册中心,所以需要添加@EnableDiscoveryClient

网关的过滤器分为:

  • GatewayFilter:网关Gateway本身提供了大量的GatewayFilter,我们可以直接配置使用,不用写Java代码

  • GlobalFilter:通常是用于自定义过滤器的

GatewayFilter的使用:

  • 网关Gateway提供了大概30个GatewayFilter,我们可以直接使用

  • 只要修改配置文件:

    给每个路由增加过滤器:在路由配置里增加

    给所有路由增加过滤器

spring:
  cloud:
    gateway:
      default-filters:
        - 过滤器名称=配置的参数值
        - 过滤器名称=配置的参数值
      routes:
        - id: 路由id
          uri: 路由目的地lb://目标服务名
          predicates:
            - Path=/xxx/**
          filters:
            - 过滤器名称=配置的参数值
            - 过滤器名称=配置的参数值

GlobalFilter的创建:

  • 创建类,实现Ordered和GlobalFilter接口

    重写Ordered接口的getOrder方法,返回int值。值越小,优先级越高

    重写GlobalFilter接口的filter方法,在方法里编写过滤逻辑

    • exchange.getRequest():获取请求信息对象

      request.getURI().getPath():获取本次请求的资源路径

      request.getHeaders().getFirst(String name):获取本次请求的请求头的值

    • exchange.getResponse():获取响应信息对象

      在方法里要放行:return chain.filter(exchange);

      在方法里不放行:

      • response.setStatus(HttpStatus.枚举项)

      • return response.setComplete();

  • 在类上添加@Component

跨域问题:

  • 涉及浏览器的同源策略:多个资源同协议、同域名(ip)、同端口 是同源的;任意一个不同,就是跨域

  • 浏览器默认情况,访问跨域资源,会出现跨域问题CORS。解决方式:

    在网关的配置文件里,添加跨域的配置

三、配置中心Nacos

1. 配置中心简介

1 微服务的配置问题

首先我们来看一下,微服务架构下关于配置文件的一些问题:

  1. 配置文件相对分散,不利于维护。

    在一个微服务架构下,配置文件会随着微服务的增多变的越来越多,而且分散在各个微服务中,不好统一配置和管理。

  2. 配置文件不方便区分环境。

    微服务项目可能会有多个环境,例如:测试环境、预发布环境、生产环境。每一个环境所使用的配置理论上都是不同的,一旦需要修改,就需要我们去各个微服务下手动维护,这比较困难。

  3. 配置文件无法实时更新。

    我们修改了配置文件之后,必须重新启动微服务才能使配置生效,这对一个正在运行的项目来说是非常不友好的。

基于上面这些问题,我们就需要配置中心的加入来解决这些问题。

  1. 可以统一管理配置文件

  2. 配置文件可以区分环境。给每个微服务设置多个配置文件,在启动微服务时,可以设置拉取指定的配置文件

    比如:一个微服务,在配置中心提供多个配置文件。一个开发环境的配置文件,一个测试环境的配置文件,一个生产环境的配置文件

    然后:在启动微服务时,可以指定要拉取哪个环境的配置文件

  3. 配置文件可以实时更新,不需要重启微服务

2 配置问题的解决方案

配置中心的思路是:

  • 首先把项目中各种配置全部都放到一个集中的地方进行统一管理。

  • 当各个服务需要获取配置的时候,就来配置中心的接口拉取自己的配置。

  • 当配置中心中的各种参数有更新的时候,也能通知到各个服务实时的过来同步最新的信息,使之动态更新。

SpringCloudAlibaba Nacos本身就可以管理配置文件。

我们只要把配置文件放到nacos上,微服务就可以从nacos里拉取配置、实现配置的动态刷新了

2. 配置中心Nacos入门【重点】

SpringCloud本身提供了一种配置中心:SpringCloudConfig,使用相对麻烦

SpringCloudAlibaba提供了配置中心:Nacos,使用更简单

  1. 把配置文件托管到配置中心Nacos

  2. 修改微服务

    添加依赖坐标nacos-config

    删除application.yaml,创建bootstrap.yaml, 在bootstrap.yaml里,配置 从哪拉取配置文件

  3. 启动微服务,测试功能是否正常

1 把配置文件托管到nacos

1) 新增配置

2) 设置配置信息

注意:项目的核心配置,需要热更新的配置才有放到nacos管理的必要。

基本不会变更的一些配置还是保存在微服务本地比较好。

2 从nacos上拉取配置

微服务要拉取nacos中管理的配置,并且与本地的application.yml配置合并,才能完成项目启动。

但如果尚未读取application.yml,又如何得知nacos地址呢?

因此spring引入了一种新的配置文件:bootstrap.yaml文件,会在application.yml之前被读取,流程如下:

1) 添加依赖坐标

  • 在用户服务的pom.xml中,添加nacos配置中心的坐标

  • 注意:一旦引入了nacos配置中心的坐标,就必须有bootstrap.yaml配置文件

<!--nacos配置-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2) 添加bootstrap.yaml

  • 先把用户服务的application.yaml删除掉(配置文件的所有内容,都已经托管到nacos上了)

  • 再给用户服务创建bootstrap.yaml。注意:名称必须是bootstrap

spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848 #配置中心nacos的地址
        prefix: user-service # 要加载的配置文件,{application}部分
        file-extension: yaml # 要加载的配置文件,{extension}后缀名部分
  profiles:
    active: dev # 激活的环境名称,配置文件中{profile}部分

3) 测试

打开浏览器,所有功能都可以正常使用,说明已经成功拉取到了配置参数

打开浏览器,访问 http://localhost:8080/user/company,可以看到公司名称,也说明成功拉取到了配置参数

3. 配置参数的动态刷新

Nacos支持动态刷新配置,也叫热更新:只要在nacos里修改了配置,微服务不需要重启,就会自动拉取最新的配置参数。

有两种实现方案:

  • 方案1:使用@Value获取参数值,并在bean对象上添加注解@RefreshScope

  • 方案2【推荐】:使用@ConfigurationProperties封装配置参数,会自动拉取最新配置

1) 方案1: @Value和@RefreshScope

  1. 在UserController里读取参数

    • 在UserController里使用@Value读取了company.name配置参数

    • 在UserController上添加注解@RefreshScope

@RestController
@RefreshScope
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Value("${company.name}")
    private String companyName;

    @GetMapping("/{id}")
    public User findById(@PathVariable("id") Long id) {
        return userService.findById(id);
    }

    @GetMapping("/company")
    public String company(){
        return companyName;
    }
}
  1. 打开浏览器访问 http://localhost:7070/user/company,先查看一下company.name原始值

  2. 在nacos里修改company.name的值

    company.name的值修改为“传智教育”

  3. 打开浏览器刷新 http://localhost:7070/user/company,可以看到已经得到最新的值了

2) 方案2: @ConfigurationProperties

  1. 创建Company类,用于封装配置参数

@Data
@ConfigurationProperties(prefix = "company")
public class Company {
    private String name;
}

    2. 在引导类上添加 @EnableConfigurationProperties,启动Company类

@EnableConfigurationProperties(Company.class)
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan("com.itheima.user.mapper")
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }
}

   3. 修改UserController

  去掉@RefreshScope注解

  注入Company对象

  添加方法,浏览器访问时,把Company对象返回给客户端 显示到页面上

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Value("${company.name}")
    private String companyName;

    @Autowired
    private Company company;

    @GetMapping("/{id}")
    public User findById(@PathVariable("id") Long id) {
        return userService.findById(id);
    }

    @GetMapping("/company")
    public String companyStr(){
        return companyName;
    }

    @GetMapping("/companyObj")
    public Company companyObj(){
        return company;
    }
}

  4. 功能测试

  先打开浏览器访问 http://localhost:8080/user/companyObj,查看原始参数值

  在Nacos里修改company.name的值

  再打开浏览器,直接刷新页面,可以看到参数值已经变成最新的了

4. 配置共享【拓展】

在实际开发中,一个服务通常有多个配置文件。在不同环境中,只要激活对应的配置文件即可。例如:

  • user-service-dev.yaml:作为用户服务的开发环境配置

  • user-service-test.yaml:作为用户服务的测试环境配置

  • user-service-prod.yaml:作为用户服务的生产环境配置

但是这多个环境的配置文件中,可能有大部分配置参数都是完全相同的,如果在每个文件里都复制一份的话,修改维护起来会比较麻烦,这时候可以使用共享的配置文件的:

  • 再创建一个user-service.yaml:不带环境标识的配置文件,会被所有环境共享

1. 准备多环境配置

1 准备dev和test两个配置文件

在Nacos配置中心里已经有了user-service-dev.yaml

我们再增加一个配置文件 user-service-test.yaml,内容如下:

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///cloud_user?useSSL=false
    username: root
    password: root
logging:
  level:
    com.itheima.user: debug
  pattern:
    dateformat: HH:mm:ss.SSS
company:
  name: 传智教育-test

2 准备多环境的启动链接

在idea里创建dev和test的启动链接,创建方式如下:

  • dev环境,激活dev

  • test环境,激活test

2. 多环境配置共享

1 创建共享配置文件

在Nacos的配置中心里,创建一个用户服务的共享配置文件

 

2 读取配置参数值

修改UserController,读取共享配置项aaa的值

@RestController
@RequestMapping("/user")
public class UserController {
	...略...;
    
    @Value("${aaa}")
    private String shareValue;
    
    @GetMapping("/share")
    public String share(){
        return shareValue;
    }
}
3 启动测试

同时启动两个环境的用户服务,

打开浏览器访问:

3. 配置共享的优先级

实际开发中,通常是:

  • 在项目内使用bootstrap.yaml中配置 不变的、不需要修改的参数

  • 在配置中心里配置可能变化的、可能修改的参数

当nacos、服务本地同时出现相同属性时,优先级高的生效。优先级从高到低如下:

  1. Nacos里的服务名-{profile}.yaml:Nacos里激活的某一环境的配置文件

  2. Nacos里的服务名.yaml:Nacos里的共享配置文件

  3. 本地的application-{profile}.yaml

  4. 本地的application.yaml

5. 小结

 

 

 

 

配置中心的作用:

  • 可以统一管理所有微服务的配置文件,方便维护

  • 可以实现参数的热更新

配置中心常见的技术:SpringCloudConfig、Nacos

配置中心Nacos的用法:统一管理配置文件

  1. 把配置参数托管到Nacos里。创建配置文件,DataId是 服务名-环境标识.后缀名

  2. 微服务要从配置中心拉取配置文件

    添加依赖坐标:nacos-config

    修改配置文件:不需要application.yaml了,而是需要添加bootstrap.yaml文件。在bootstrap.yaml文件里:

    • spring.cloud.nacos.config.server-addr,值是配置中心的地址

    • spring.cloud.nacos.config.prefix,值是服务名

    • spring.profiles.active,值是环境标识

    • spring.cloud.nacos.config.file-extension,值是后缀名

配置中心Nacos的用法:实现参数热更新

  • 方式1:微服务里使用@Value读取参数值,并在bean对象加上@RefreshScope

  • 方式2:微服务里使用@ConfigurationProperties读取参数值,它本身就具备参数热更新的能力

  • 参数热更新的效果:

    当在配置中心修改了参数值,微服务不需要重启,也能立即得到最新的参数值

大总结

多思考,多出声读

远程调用:微服务之间需要互相调用,进行数据的交互==>Feign

  • 使用入门

    添加依赖:添加OpenFeign的依赖坐标

    创建接口:UserClient接口

    • 接口上加@FeignClient("目标服务名")

    • 接口里方法上加@GetMapping, @PostMapping,……

    • 接口里方法形参加:

      @RequestParam:要把方法参数 作为表单参数 发出去

      @RequestBody:要把方法参数 作为请求体json发出去

      @PathVariable:要把参数 作为路径变量发出去

    • 方法返回值是:期望得到的结果。Feign会帮我们把响应结果转换成 期望的类型

    修改引导类:添加@EnableFeignClients("扫描的包名")

  • 打印日志:

    要修改配置文件,设置全局的日志级别为 debug

    要修改配置文件,设置Feign的日志级别。共有4个:NONE,BASIC,HEADERS,FULL

  • 优化性能:

    问题:Feign本身底层使用URLConnection,没有连接池。每次操作要创建连接,之后要关闭销毁连接对象

    解决:把Feign底层换成httpclient

    1. 添加httpclient的依赖坐标

    2. 修改配置文件,启用httpclient

feign:
  httpclient:
    enabled: true
    max-connections: 最大连接数
    max-connections-per-route: 每个资源路径的最大连接数

负载均衡:远程调用时,如果目标服务是集群,就需要实现负载均衡==>Ribbon

  • 负载均衡的两种方式

    提供者一方的负载均衡:Nginx。适用于整个服务的最前沿,直接面向客户端的请求

    消费者一方的负载均衡:Ribbon。适用于微服务之间互相调用时,实现负载均衡

  • Ribbon的使用:不需要额外添加依赖、不需要做任何配置,默认就有负载均衡效果。

  • Ribbon的负载均衡策略,常见的:RandomRule,RoundRobinRule,NacosRule

  • 修改负载均衡策略:

    方式1,修改消费者一方的配置文件,设置负载均衡策略

    方式2,在消费者一方,使用@Bean把负载均衡策略对象放到IoC容器里

  • 饥饿加载

    如果不开启饥饿加载,当第一次访问时,Ribbon才会从注册中心拉取服务地址列表。第一次访问通常比较慢

    可以开启饥饿加载,作用是微服务一启动,Ribbon就立即从注册中心里拉取服务地址列表。

服务保护:远程调用时,必须要防止目标服务出错导致的级联问题==>Hystrix或Sentinel

注册中心:远程调用时,需要实时获取到目标服务的地址信息==>Nacos

  • 注册中心解决了服务治理的问题

  • 使用入门:

    1. 安装开启Nacos。Nacos的管理界面地址 http://localhost:8848/nacos, 帐号nacos,密码nacos

    2. 微服务整合Nacos

      添加依赖:锁定SpringCloudAlibaba的依赖版本,再添加nacos-discovery坐标

      修改配置:

      • 应用服务名,使用spring.application.name配置

      • 注册中心地址,使用spring.cloud.nacos.discovery.server-addr配置

      修改引导类:添加@EnableDiscoveryClient

  • Nacos分级存储模型:

    • 可以把一个服务下边划分多个集群,每个集群下边有多个服务实例。同一集群的实例,部署到同一机房

      灾备(异地容灾),同集群优先访问

    • 修改配置文件,使用spring.cloud.nacos.discovery.cluster-name设置当前微服务所属集群名。实现了分级

    • 修改配置文件,使用NacosRule负载均衡策略,实现了同集群优先访问

  • Nacos的环境隔离:

    效果:

    • 不同环境的服务实例之间,是绝对隔离的,不可能互相发现、不可能互相访问;

    • 同环境的服务可以互相发现调用

    做法:

    1. 在Nacos里创建新的命名空间。设置id、名称、描述

    2. 修改配置文件,设置微服务所属的namespace。

      使用参数spring.cloud.nacos.discovery.namespace=命名空间的id

服务网关:所有微服务,要有一个统一的访问入口==>SpringCloudGateway

  • 网关的作用:

    路由:把客户端的请求,根据判断条件分发到目标微服务上

    过滤:拦截客户端的请求进行过滤处理,再决定是否放行

  • 使用入门:创建Module,然后

    添加依赖:nacos-discovery,gateway的坐标

    修改配置:nacos注册中心的配置,网关路由的配置,跨域的配置

    修改引导类:@EnableDiscoveryClient启动服务发现

  • 过滤器GatewayFilter:网关Gateway提供了大量的GatewayFilter,我们可以直接配置使用,不需要写Java代码

spring:
  cloud:
    gateway:
      default-filters:
        - 过滤器名=参数
        - 过滤器名=参数
      routes:
        - id: 路由唯一标识
          uri: 路由的目的地,写法是 lb://目标服务名
          predicates:
            - Path=/xx/**
          filters:
            - 过滤器名=参数
            - 过滤器名=参数
      globalcors: #全局跨域的配置

  • 过滤器GlobalFilter:通常用于自定义过滤器

    创建类,实现GlobalFilter、Ordered接口

    • 重写GlobalFilter接口的filter方法,在方法里编写过滤逻辑。方法里有一些常用的API

      exchange.getRequest()

      exchange.getResponse()

      request.getURI().getPath()

      request.getHeaders().getFirst("请求头名称")

      如果要放行:return chain.filter(exchange);

      如果不放行:

      • response.setStatus(HttpStatus.UNAUTHORIZED)

      • return response.setComplete();

    • 重写Ordered接口的getOrder方法,在方法里返回int值。值越小,优先级越高

    在类上添加@Component

配置中心:所有微服务的配置文件太散乱、不能热更新==>Nacos

  • 作用:

    可以统一管理所有微服务的配置文件

    可以实现配置参数的热更新

  • 用法:

    1. 把微服务的配置参数,托管到Nacos里。

      在Nacos里创建配置,DataId是 应用服务名-环境标识.后缀名

      把配置参数添加进去。通常把一些 可能会改变的、修改的参数,放到配置中心

    2. 微服务整合配置中心,从配置中心里拉取配置文件

      添加依赖:nacos-config

      创建配置:不要application.yaml,要创建bootstrap.yaml。把不变的配置放到这个配置文件里

server:
  port: 8080
spring:
  application:
    name: 应用服务名
  cloud:
    nacos:
      config:
        server-addr: localhost:8848 #Nacos注册中心的地址
        prefix: 应用服务名 
        file-extension: 后缀名
  profiles:
    active: 环境标识

参数热更新:

  • 方式1:使用@Value读取参数值,并在bean对象上加@RefreshScope

  • 方式2:使用@ConfigurationProperties读取参数值,它本身就具备参数热更新的能力

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值