微服务框架springcloud使用
2022-12-03 00:12:34

微服务是一种经过良好架构设计的分布式架构方案,微服务架构特征:

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发
  • 面向服务:微服务对外暴露业务接口
  • 自治:团队独立、技术独立、数据独立、部署独立
  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题
image-20221224234402956

微服务远程调用

image-20221224234908523

远程调用方式

image-20221224235018434
  1. 在order服务中注册RestTemplate

    1
    2
    3
    4
    @Bean
    public RestTemplate restTemplate(){
    return new RestTemplate();
    }
  2. 服务远程调用RestTemplate

    1
    2
    3
    4
    5
    6
    7
    8
    @Resource
    private RestTemplate restTemplate;
    /**
    * 查询用户信息
    */
    private User restTemplateFindById( Long id ){
    return restTemplate.getForObject( "http://localhost:8080/user/"+id, User.class );
    }
  3. user服务接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
    * 路径: /user/110
    *
    * @param id 用户id
    * @return 用户
    */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id,
    @RequestHeader(value = "msg",required = false) String msg) {
    log.info( msg );
    return userService.queryById(id);
    }

Eureka注册中心

image-20221225000528790

Eureka原理

Eureka架构中,微服务角色有两类:

  • EurekaServer:服务端,注册中心
    • 记录服务信息
    • 心跳监控
  • EurekaClient:客户端
    • Provider:服务提供者,例如案例中的 user-service
      • 注册自己的信息到EurekaServer
      • 每隔30秒向EurekaServer发送心跳
    • consumer:服务消费者,例如案例中的 order-service
      • 根据服务名称从EurekaServer拉取服务列表
      • 基于服务列表做负载均衡,选中一个微服务后发起远程调用

搭建EurekaServer

  1. 引入依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    <version>2.2.7.RELEASE</version>
    </dependency>
  2. 启动类添加 @EnableEurekaServer 注解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @EnableEurekaServer
    @SpringBootApplication
    public class EurekaApplication {

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

    }
  3. 添加yml配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    server:
    port: 10010 #服务端口
    spring:
    application:
    name: eurekaservice #服务名称
    eureka:
    client:
    service-url: #eureka地址信息
    defaultZone: http://localhost:10010/eureka/

服务注册

user-service 注册到EurekeServer

  1. user-service 项目项目中导入依赖

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
  2. 添加yml配置

    1
    2
    3
    4
    5
    6
    7
    spring:
    application:
    name: userservice #服务名称
    eureka:
    client:
    service-url: #eureka地址信息
    defaultZone: http://localhost:10010/eureka/

服务发现

服务拉取是基于服务名称获取服务列表,然后在对服务列表做负载均衡

  1. 修改OrderService的代码,修改访问的url路径,用服务名代替ip、端口:

    1
    2
    3
    4
    5
    6
    /**
    * 查询用户信息
    */
    private User restTemplateFindById( Long id ){
    return restTemplate.getForObject( "http://userservice/user/" + id, User.class );
    }
  2. OrderService启动类上的RestTemplate上添加@LoadBalanced 注解开启负载均衡

    1
    2
    3
    4
    5
    6
    7
    8
    /**
    * LoadBalanced 开启负载均衡
    */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
    return new RestTemplate();
    }

Ribbon 负载均衡

image-20221225003829282

Ribbon的负载均衡策略规则是有 IRule 的接口来定义的,每个子接口都是一种规则

image-20221225004356598
  • 内置负载均衡规则类

    • RoundRobinRule

    简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则

    • AvailabilityFilteringRule

      对以下两种服务器进行忽略:

      1. 在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加
      2. 并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的 clientName clientConfigNameSpace ActiveConnectionsLimit属性进行配置
      • WeightedResponseTimeRule

        为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择

        • ZoneAvoidanceRule

          以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询

        • BestAvailableRule

          1
          忽略那些短路的服务器,并选择并发数较低的服务器
        • RandomRule

          随机选择一个可用的服务器

        • RetryRule

          1
          重试机制的选择逻辑
      • 修改负载均衡规则

        • 通过Bean 设置

          1
          2
          3
          4
          5
          6
          7
          8
          /**
          * 负载均衡随机策略
          * 可使用yml文件配置
          */
          @Bean
          public IRule randomRule(){
          return new RandomRule();
          }
        • 配置文件设置

          1
          2
          3
          userservice:
          ribbon: #负载均衡的规则,表示加权规则,yml配置优先级第一,Java代码第二,默认的最后
          NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机访问
      • 饥饿加载

        Ribbon默认是采用懒加载,需要第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时

        • 饥饿加载配置

          1
          2
          3
          4
          5
          6
          #饥饿加载配置,系统默认懒加载
          ribbon:
          eager-load:
          enabled: true #开启饥饿加载,默认false
          clients: #指定饥饿加载服务器名称
          - userservice

    Nacos注册中心

    启动初始化配置

    启动命令

    1
    2
    3
    4
    startup.cmd -m standalone
    # 启动时指定端口号
    -Dserver.port=8848
    #可在nacos的.cmd文件同目录下创建yml文件,启动时会优先目录下的配置

    image-20221225011917941

    父工程引入Spring Cloud Alibaba管理依赖

    1
    2
    3
    4
    5
    6
    7
    <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>

    导入nacos依赖

    1
    2
    3
    4
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    配置nacos服务地址

    1
    2
    3
    4
    spring:
    cloud:
    nacos:
    server-addr: localhost:8848

    访问nacos查看服务

    image-20221225012138295

    Nacos服务分级存储模型

    image-20221225144309341

    服务跨集群调用

    服务调用尽可能的选择本地集群的服务,跨集群调用延迟较高,本地集群不可用时,再去访问其他集群

    服务集群属性配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    spring:
    cloud:
    nacos:
    server-addr: localhost:8848 #nacos服务地址
    discovery:
    cluster-name: CZ #集群名称
    #设置负载均衡的IRule为nacos
    userservice:
    ribbon: #负载均衡的规则,表示加权规则,yml配置优先级第一,Java代码第二,默认的最后
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #优先访问本地集群
    image-20221225145227525

    根据权重负载均衡

    服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,可以通过设置 nacos 的权重来控制访问频率,权重大的访问频率越高 ,将性能好的机器承担更多的用户请求

    • 权重值通常在0-1之间
    • 权重值越大被访问概率越高
    • 权重值为0时不会被访问

    环境隔离 namespace

    Naocs 中服务存储和数据存储的最外层namespace 做外层隔离,在Nacos 控制台命名空间创建namespace 用来隔离不同环境

    image-20221225152106043 image-20221225152436216

    添加namespace

    1
    2
    3
    4
    5
    spring:
    cloud:
    nacos:
    discovery:
    namespace: 7c0f4809-32f3-4ad6-9e10-0c1816161ebd #namespace环境id
    1. 不同namespace的服务不能相互访问
    2. 每个namespace都有唯—id,可在添加时设置,也可使用默认生成的id
    3. 服务设置namespace时要写id而不是名称

    Nacos的注册和推送

    image-20221225154402081

    服务注册到Nacos时,可以选择注册为临时或非临时实例,临时实例宕机时,会从Nacos的服务列表中剔除,而非临时实例则不会

    1
    2
    3
    4
    5
    spring:
    cloud:
    nacos:
    discovery:
    ephemeral: true #临时实列配置

    NacosEureke- 共同点

    • 都支持服务注册和服务拉取
    • 都支持服务提供者心跳方式做健康检测
    • 区别

      • Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
      • 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
      • Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
      • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式

    Nacos 配置管理

    统一配置管理

    image-20221225161301098
    1. 配置更改热更新

      可以将一些关键参数,需要运行时调整的参数放到Nacos配置中心,一般都是自定义配置

      image-20221225160722455 image-20221225161459559

      image-20221225162501214

    2. 配置获取步骤

      image-20221225161738191

    3. 服务配置

      1. 导入Nacos客户端管理依赖

        1
        2
        3
        4
        <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
      2. 在微服务的resource目录下新建bootstrap.yml引导文件

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        spring:
        application:
        name: userservice
        profiles:
        active: dev #环境
        cloud:
        nacos:
        server-addr: localhost:8848 #nacos地址
        config:
        file-extension : yaml #文件后缀
    4. 配置demo

      Nacos中的配置文件变更后,微服务无需重启就可以感知。不过需要通过下面两种配置实现:

      • @Value注入的变量所在类上添加注解@RefreshScope
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      @Slf4j
      @RestController
      @RequestMapping("/user")
      @RefreshScope
      public class UserController {
      /**
      * pattern:
      * dateformat: MM-dd HH:mm:ss
      */
      @Value( "${pattern.dateformat}" )
      private String dateFormat;

      /**
      * 是否读取bootstrap文件
      */
      @GetMapping("/now")
      public String now(){
      log.info( dateFormat );
      return LocalDateTime.now().format(
      DateTimeFormatter.ofPattern( dateFormat )
      );
      }
      }
      • 使用@ConfigurationProperties注解
      1
      2
      3
      4
      5
      @Component
      @ConfigurationProperties("pattern")
      public class PatternProperties {
      private String dateformat;
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      @Slf4j
      @RestController
      @RequestMapping("/user")
      public class UserController {
      @Resource
      private PatternProperties patternProperties;

      @GetMapping("/now")
      public String now(){
      log.info( dateFormat );
      return LocalDateTime.now().format(
      DateTimeFormatter.ofPattern( patternProperties )
      );
      }
      }

    多环境配置共享

    微服务启动时会从Nacos读取多个配置文件

    • [spring.application.name]-[spring.profiles.active].yaml,例如: userservice-dev.yaml
    • [spring.application.name].yaml,例如: userservice.yaml

    无论profile如何变化,[spring.application.name].yaml这个文件一定会加载,因此多环境共享配置可以写入这个文件

    image-20221225164427343

    多种环境配置的优先级

    image-20221225164633913

    Nacos集群搭建

    1. Nacos反向代理

      1. 进入nacosconf目录,修改配置文件cluster.conf.example,重命名为cluster.conf添加端口信息

        1
        2
        3
        127.0.0.1:8845
        127.0.0.1.8846
        127.0.0.1.8847
      2. 然后修改application.properties文件,添加数据库配置(35行)

        1
        2
        3
        4
        5
        6
        7
        spring.datasource.platform=mysql

        db.num=1

        db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
        db.user.0=root
        db.password.0=123
      3. nacos文件夹复制三份,分别命名为:nacos1nacos2nacos3,然后分别修改三个文件夹中的application.properties中的端口信息

        1
        server.port=8845
      4. 启动节点

        1
        startup.cmd
    2. Nginx配置

      1. 修改conf/nginx.conf文件,设置反向代理和负载均衡

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        upstream nacos-cluster {
        server 127.0.0.1:8845;
        server 127.0.0.1:8846;
        server 127.0.0.1:8847;
        }

        server {
        listen 80;
        server_name localhost;

        location /nacos {
        proxy_pass http://nacos-cluster;
        }
        }
      2. java代码中的端口号改为nginx代理的端口号

    Http客户端Feign

    Feign 概述

    • 可插拔的注解支持,包括 Feign 注解和AX-RS注解
    • 支持可插拔的 HTTP 编码器和解码器
    • 支持 Hystrix 和它的 Fallback
    • 支持 Ribbon 的负载均衡
    • 支持 HTTP 请求和响应的压缩。Feign 是一个声明式的 WebService 客户端,它的目的就是让 Web Service 调用更加简单。它整合了 Ribbon 和 Hystrix,从而不需要开发者针对 Feign 对其进行整合。Feign 还提供了 HTTP 请求的模板,通过编写简单的接口和注解,就可以定义好 HTTP 请求的参数、格式、地址等信息。Feign 会完全代理 HTTP 的请求,在使用过程中我们只需要依赖注入 Bean,然后调用对应的方法传递参数即可

    RestTemplate方式调用存在的问题

    1
    2
    3
    private User restTemplateFindById( Long id ){
    return restTemplate.getForObject( "http://userservice/user/" + id, User.class );
    }
    • 代码可读性差,编程体验不统一
    • 参数复杂URL难以维护

    导入依赖

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    在启动类上添加 @EnableFeignClients 注解开启Feign功能

    1
    2
    3
    4
    5
    6
    7
    8
    @SpringBootApplication
    @EnableFeignClients(clients = UserClient.class,defaultConfiguration = UserClientFallbackFactory.class)
    public class OrderApplication {

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

    编写Feign客户端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @FeignClient( value = "userservice")
    public interface UserClient {

    /**
    * 查询user服务的用户信息
    */
    @GetMapping("/user/{id}")
    User findById( @PathVariable("id") Long id );
    }

    使用Feign客户端替代RestTemplate

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Service
    public class OrderService {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
    // 1.查询订单
    Order order = orderMapper.findById( orderId );
    //查询用户信息
    order.setUser( this.feignFindById( order.getUserId() ) );
    return order;
    }

    private User feignFindById( Long id ){
    return userClient.findById( id );
    }

    }

    自定义Feign配置

    Feign运行自定义配置来覆盖默认配置

    类型 作用 说明
    feign.Logger.Level 修改日志级别 包含四种不同的级别:NONE、BASIC、HEADERS、FULL
    feign.codec.Decoder 响应结果的解析器 http远程调用的结果做解析,例如解析json字符串为java对象
    feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送
    feign. Contract 支持的注解格式 默认是SpringMVC的注解
    feign. Retryer 失败重试机制 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

    自定义Feign日志

    1. yml文件配置

      • 全局 生效

        1
        2
        3
        4
        5
        feign:
        client:
        config:
        dedfault: #全局配置,如果写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #日志级别
      • 局部生效

        1
        2
        3
        4
        5
        feign:
        client:
        config:
        userservice: #全局配置,如果写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #日志级别
    2. java代码配置

      1
      2
      3
      4
      5
      6
      public class DefaultFeignConfiguration {
      @Bean
      public Logger.Level level(){
      return Logger.Level.BASIC;
      }
      }
      • 全局配置,把它放到@EnableFeignClients这个注解中

        1
        @EnableFeignClients(defaultConfiguration=DefaultFeignConfiguration.class)
      • 局部配置,把它放到@FeignClient这个注解中

        1
        FeignClient(value="userservice", configuration=DefaultFeignConfiguration.class)

    Feign性能优化

    Feign底层的客户端实现

    • URLConnection 默认实现,不支持连接池.
    • Apache HttpClient 支持连接池
    • OKHttp 支持连接池

    优化Feign的性能主要包括

    1. 使用连接池代替默认的URLConnection
    2. 日志级别,最好用basicnone

    连接池配置

    导入依赖

    1
    2
    3
    4
    5
    <!--httpClient的依赖 -->
    <dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
    </dependency>

    配置连接池

    1
    2
    3
    4
    5
    6
    7
    8
    9
    feign:
    client:
    config:
    default: # default全局的配置
    loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
    httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

    Feign最佳实践

    image-20221225175948373 image-20221225180104056

    当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:

    1. 指定FeignClient所在包

      1
      @EnableFeignClients(basePackages = "com.hg.feign.clients")
    2. 指定FeignClient字节码

      1
      @EnableFeignClients(clients = {UserClient.class})

    统一网关Gateway

    image-20221225213134241

    网关功能

    • 身份认证和权限校验
    • 服务路由、负载均衡
    • 请求限流

    搭建网关服务

    创建新的module,引入SpringCloudGateway的依赖和Nacos的服务发现依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!--网关-->
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--nacos服务发现依赖-->
    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    编写路由配置和Nacos地址

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    server:
    port: 10010 # 网关端口
    spring:
    application:
    name: gateway # 服务名称
    cloud:
    nacos:
    server-addr: localhost:8848 # nacos地址
    gateway:
    routes: # 网关路由配置
    - id: user-service # 路由id,自定义,只要唯一即可
    # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
    uri: lb://userservice # 路由的目标地址 lb就是根据服务名负载均衡,后面跟服务名称
    predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
    - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
    - id: order-service
    uri: lb://orderservice
    predicates:
    - Path=/order/**
    image-20221225214103879

    路由断言工厂Route Predicate Factory

    网关路由可以配置的内容包括

    • 路由id 路由唯一标示
    • uri 路由目的地,支持lbhttp两
    • predicates 路由断言,判断请求是否符合要求,符合则转发到路由目的地
    • filters 路由过滤器,处理请求或响应

    Spring提供了11中基本的Predicate工厂

    名称 说明 示例
    After 某个时间点后的请求 - After=2037-01-20T17:42:47.789-07:00[America/Denver]
    Before 某个时间点之前的请求 - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
    Between 两个时间点之前的请求 - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
    Cookie 求必须包含某些cookie - Cookie=chocolate, ch.p
    Header 请求必须包含某些header - Header=X-Request-Id, \d+
    Host 请求必须是访问某个host(域名) - Host=.somehost.org,.anotherhost.org
    Method 请求方式必须是指定方式 - Method=GET,POST
    Path 请求路径必须符合指定规则 - Path=/red/{segment},/blue/**
    Query 请求参数必须包含指定参数 - Query=name, Jack或者- Query=name
    RemoteAddr 请求者的ip必须是指定范围 - RemoteAddr=192.168.1.1/24
    Weight 权重处理

    路由过滤器GatewayFilter

    GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理

    image-20221225220721378

    Spring提供了31种不同的路由过滤器工厂

    名称 说明
    AddRequestHeader 给当前请求添加一个请求头
    RemoveRequestHeader 移除请求中的一个请求头
    AddResponseHeader 给响应结果中添加一个响应头
    RemoveResponseHeader 从响应结果中移除有一个响应头
    RequestRateLimiter 限制请求的流量

    demo 给所有进入userservice的请求添加一个请求头

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    server:
    port: 10010 # 网关端口
    spring:
    application:
    name: gateway # 服务名称
    cloud:
    nacos:
    server-addr: localhost:8848 # nacos地址
    gateway:
    routes: # 网关路由配置
    - id: user-service # 路由id,自定义,只要唯一即可
    # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
    uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
    predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
    - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
    filters:
    - AddRequestHeader=msg,SpringCloud!!! #请求头
    default-filters: #默认过滤器对所有的路由生效
    - AddRequestHeader=msg,SpringCloud!!!

    全局过滤器 GlobalFilter

    全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。定义方式是实现GlobalFilter接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    //@Order(1)
    @Component
    public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter( ServerWebExchange exchange, GatewayFilterChain chain ) {
    //获取请求参数
    ServerHttpRequest request = exchange.getRequest();
    MultiValueMap<String, String> queryParams = request.getQueryParams();

    String authorization = queryParams.getFirst( "authorization" );

    //判断参数值是否等于admin
    if ( "admin".equals( authorization ) ) {
    //放行
    return chain.filter( exchange );
    }
    //拦截
    //设置状态码
    exchange.getResponse().setStatusCode( HttpStatus.UNAUTHORIZED );
    return exchange.getResponse().setComplete();
    }

    /**
    * 过滤器优先级
    * @return 值越小,优先级越高
    */
    @Override
    public int getOrder() {
    return -1;
    }
    }

    全局过滤器的优先级可以使用 @Order 来设置,也可以实现Ordered 重写getOrder()方法来设置

    过滤器的执行顺序

    • 请求进入网关会碰到三类过滤器 当前路由的过滤器DefaultFilterGlobalFilter
    • 请求路由后,会将当前路由过滤器DefaultFilter、GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器
    image-20221225223128057
    • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前
    • GlobalFilter通过实现Ordered接口,或者添加**@Order注解来指定order值**,由我们自己指定
    • 路由过滤器和defaultFilterorderSpring指定,默认是按照声明顺序从1递增
    • 当过滤器的order值一样时,会按照defaultFilter >路由过滤器>GlobalFilter的顺序执行
    image-20221225223612114

    跨域

    • 域名不同 www.taobao.comwww.taobao.org www.jd.com
    • 域名相同,端口不同: localhost:8080localhost8081
    • localhost127.0.0.1 也是跨域

    网关跨域问题处理 CORS 方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    spring:
    cloud:
    gateway:
    globalcors: # 全局的跨域处理
    add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
    corsConfigurations:
    '[/**]':
    allowedOrigins: # 允许哪些网站的跨域请求
    - "http://localhost:8090"
    - "http://www.leyou.com"
    allowedMethods: # 允许的跨域ajax的请求方式
    - "GET"
    - "POST"
    - "DELETE"
    - "PUT"
    - "OPTIONS"
    allowedHeaders: "*" # 允许在请求中携带的头信息
    allowCredentials: true # 是否允许携带cookie
    maxAge: 360000 # 这次跨域检测的有效期