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

news2024/11/19 17:34:08

目录

一、远程调用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;
    }
}

测试

  • 依次启动user-service,order-service

  • 打开浏览器输入 http://localhost:7070/order/101 ,可以正常访问

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) 测试效果

  • 依次启动user-service、order-service

  • 打开浏览器访问 http://localhost:7070/order/101

  • 查看控制台日志

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/**

测试
  • 依次启动user-service、api-gateway

  • 打开浏览器输入 http://localhost:10000/user/1,发现可以查询到id为1的用户

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 启动测试

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

打开浏览器访问:

  • 开发环境dev:http://localhost:8080/user/share,页面上可以看到共享的配置项“共享配置值”

  • 测试环境test:http://localhost:8081/user/share,页面上可以看到共享的配置项“共享配置值”

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读取参数值,它本身就具备参数热更新的能力

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1629319.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于深度学习神经网络的AI图片上色DDcolor系统源码

第一步&#xff1a;DDcolor介绍 DDColor 是最新的 SOTA 图像上色算法&#xff0c;能够对输入的黑白图像生成自然生动的彩色结果&#xff0c;使用 UNet 结构的骨干网络和图像解码器分别实现图像特征提取和特征图上采样&#xff0c;并利用 Transformer 结构的颜色解码器完成基于视…

xfce4 panel 不能显示QQ,钉钉的状态图标

有一段时间不能显示了&#xff0c;之前刚装完系统的时候很长时间内都是好的&#xff0c;所以刚开始肯定是支持显示这些状态图标的。就是因为不能显示的原因&#xff0c;所以还装了lxQt桌面&#xff0c;这个桌面确实不错。不过还是有时会怀念xfce4&#xff0c;想看看能不能解决这…

面经总结(二)(数据库)

数据库常识&#xff1a; 1、数据库系统包含什么&#xff1f; 包含了数据库、数据库管理系统、数据库管理员和应用程序。 数据库&#xff08;DB)&#xff1a;顾名思义是存放数据的仓库&#xff0c;实现数据的持久化。 数据库管理系统&#xff08;DBMS)&#xff1a;类似于操作系…

利用ollama和open-webui本地部署通义千问Qwen1.5-7B-Chat模型

目录 1 安装ollama 2 安装open-webui 2.1 镜像下载 3 配置ollama的模型转换工具环境 3.1 下载ollama源码 3.2 下载ollama子模块 3.3 创建ollama虚拟环境 3.4 安装依赖 3.5 编译量化工具 7 创建ollama模型 8 运行模型 参考文献&#xff1a; 1 安装ollama curl -fsSL …

(GEE)2000-2020年黄河流域时序渐变图及高程模型计算 JavaScript版

文章目录 一. 选取目标区域二. NDVI实现三. 高程模型DEM实现四. 时序图五. 植被覆盖类型六. 参考文献 首先推荐吴秋生老师团队开源的便捷构建网站&#xff1a;适用于地理空间应用的Streamlight 吴秋生老师团队的工具请自行探索。本文讲解基于GEE云开发平台实现&#xff0c;基于…

关于springboot内置tomcat最大请求数配置的一些问题

前言 springboot内置了tomcat。那么一个springboot web应用&#xff0c;最大的请求链接数是多少呢&#xff1f;很早以前就知道这个是有个配置&#xff0c;需要的时候&#xff0c;百度一下即可。但&#xff0c;事实并非如此&#xff0c;有几个问题我想大多数人还真不知道。比如…

机械图纸管理系统,如何选择适合的机械图纸管理系统?

机械图纸管理系统是一种专门用于管理和跟踪机械制造过程中的图纸、设计文件和相关信息的软件系统。例如&#xff1a;彩虹图纸管理系统&#xff0c;这种系统能够有效地整合和管理工程图纸、零部件清单、技术规范、工艺流程等各种数据&#xff0c;为企业提供全面的图纸管理和协作…

typescript:vscode的settings配置文件配置ts语法提示

typescript&#xff1a;vscode的settings配置文件配置ts语法提示 1 找到vscode左下角的齿轮按钮 2 点击Settings&#xff08;或者快捷键ctrl,&#xff09;&#xff1a; 点击右上角的Open Settings(JSON)按钮打开配置文件&#xff1a; 或者ctrlshiftp&#xff0c;搜索settings&…

嵌入式全栈开发学习笔记---Linux基本命令1

目录 cd加路径 相对路径是什么 绝对路径是什么 cd后面没有路径 cd- ls -l ls -a ls -al ls加路径 Linux的命令是数不清的&#xff0c;就像很多应用软件一样&#xff0c;随时都有可能被开发出来。 但是我们目前阶段只需要掌握基本的命令就可以了。 上一篇博文中我已经…

元宇宙APP搭建重点,会用到哪些三方服务?

元宇宙APP的搭建是一个综合性的项目&#xff0c;涉及到众多关键要素和第三方服务。以下是一些元宇宙APP搭建的重点&#xff0c;以及可能用到的第三方服务&#xff1a; 一、搭建重点 技术框架的选择与搭建&#xff1a;元宇宙APP需要稳定、高效的技术框架来支撑其运行。这包括前…

插入排序,搞起来,一路狂奔,数组插入

一点喽 目录 编程实现&#xff1a;程序功能是在一个有序序列中插入一个数后&#xff0c;该数列依然有序 输入测试数据&#xff1a;2 3 5 7 8 23 34 56 78 90 25 程序运行结果&#xff1a;插入之后的数组为 2 3 5 7 8 23 25 34 56 78 90 第一个就…

如何增强交友、婚恋平台、金融等平台的安全性

运营商二要素核验是一种数字身份验证方法&#xff0c;主要使用用户的手机号码和姓名作为核验要素。这两个要素被认为是最基本的用户身份信息&#xff0c;通过运营商的数据库来核实其真实性。 在实际操作中&#xff0c;用户需要提供手机号码和姓名进行验证。应用系统会调用接口…

unity的特性AttriBute详解

unity的特性AttriBute曾经令我大为头疼。因为不动使用的法则&#xff0c;但是教程都是直接就写&#xff0c;卡住就不能继续学下去。令我每一次看到&#xff0c;直接不敢看了。 今天使用文心一言搜索一番&#xff0c;发现&#xff0c;恐惧都是自己想象的&#xff0c;实际上这个…

Docker之存储配置与管理

一、容器本地配置与Docker存储驱动 每个容器都被自动分配了本地存储&#xff0c;也就是内部存储。容器由一个可写容器层和若干只读镜像层组成&#xff0c;容器的数据就存放在这些层中。 容器本地存储采用的是联合文件系统。这种文件系统将其他文件系统合并到一个联合挂载点&a…

Unity类银河恶魔城学习记录15-5,6 p157 Audio time limiter p158 Area sound

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili​​ AreaSound.cs using System.Collections; using System.Collections.G…

Spring boot + Redis + Spring Cache 实现缓存

学习 Redis 的 value 有 5 种常用的数据结构 Redis 存储的是 key-value 结构的数据。key 是字符串类型&#xff0c;value 有 5 种常用的数据结构&#xff1a; Redis 的图形化工具 Another Redis Desktop Manager Spring Data Redis Redis 的 Java 客户端。 Spring Cache Spr…

Pycharm新建工程时使用Python自带解释器的方法

Pycharm新建工程时使用Python自带解释器的方法 新建Project时最好不要新建Python解释器&#xff0c;实践证明&#xff0c;自己新建的Python解释器容易出现各种意想不到的问题。 那么怎样使用Python安装时自带的解释器呢&#xff1f; 看下面的三张截图大家就清楚了。 我的Pyth…

avl excite python二次开发1--python解释器需用内置解释器aws_cmd

avl excite python二次开发1--python解释器需用内置解释器aws_cmd 1、python解释器问题1.1、用外置python解释器&#xff0c;import WSInterface会失败(WSInterface.pyd)1.2、用内置解释器aws_cmd运行py脚本1.3 用内置解释器aws_python执行脚本三级目录 1、python解释器问题 1…

Python_AI库 matplotlib扩展知识

Python_AI库 matplotlib扩展知识 在数据分析和处理的领域里&#xff0c;可视化是一种不可或缺的手段。通过图形化的展示&#xff0c;我们可以更直观地理解数据的分布、趋势和关系。而matplotlib&#xff0c;作为Python中最为流行的数据可视化库之一&#xff0c;以其强大的功能…

Anti Rookit -- 检测隐藏进程

Anti Rookit 一&#xff1a;检测隐藏进程 引言 检测隐藏进程除了众所周知的枚举进程ID之外&#xff0c;还有枚举句柄表的方式。不过今天给大家带来的是第三种方法。 探究 应用层通过接口 C r e a t e P r o c e s s \textcolor{cornflowerblue}{CreateProcess} CreateProcess…