【SpringCloud】04 网关springcloud gateway

news2024/11/27 8:24:40

网关springcloud gateway

上面的架构,会存在着诸多的问题:

  1. 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性

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

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

在这里插入图片描述

网关可以做什么?

  1. 路由转发。
  2. 身份认证。
  3. 统一跨域解决。
  4. 黑白名单ip
  5. 敏感词
  6. 限流

1. 常用的网关

  1. nginx:它可以当网关

  2. zuul:早期的微服务就是使用的该组件作为网关,但是它的底层使用的servlet。它的效率非常慢。而且它是netflix的产品。 netflix预计产品zuul2, 但是zuul2夭折。

  3. springcloud gateway:它是spring公司出品的网关。它的效率是zuul的1.6倍。

2. springcloud gateway

Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控和限流。

3. 如何使用

其实网关 它也是一个微服务,那么我们也可以创建网关微服务。

在这里插入图片描述

引入spring-cloud-starter-gateway

<dependencies>
    <!--这里引入了gateway的依赖后,不能引用spring-boot-starter-web依赖。
        因为:gateway它使用的是netty服务器。
        spring-boot-starter-web里面内置了tomcat服务器.
    -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
</dependencies>

(2)创建主启动类

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

(3)修改配置文件

# 配置路由
spring:
  cloud:
    gateway:
      routes:
        - id: shop-product #路由的唯一标识。如果没有给定默认按照UUID生成
          uri: http://localhost:8001 #真实转发的地址
          predicates: # 断言 如果断言满足要求,则转发到uri指定的真实地址.
            - Path=/product/** # 如果客户的请求路径以product开头,则满足该断言要求,则转发的uri真实地址。

        - id: shop-order
          uri: http://localhost:9001
          predicates:
            - Path=/order/**

(4)启动gateway

(5)演示
在这里插入图片描述

4. gateway负载均衡转发

上面配置文件有没有需要改进的?

  • 我们真实转发的地址,万一搭建是一个集群。 我们观察到gateway本身也是一个微服务,是否可以从注册中心拉取相关的微服务,然后访问该服务呢。
    在这里插入图片描述

(1)引入nacos注册中心的依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

(2)修改配置文件
在这里插入图片描述
测试:
在这里插入图片描述

5. 简洁版

# 配置路由
spring:
  cloud:
    gateway:
      routes:
        - id: shop-product #路由的唯一标识。如果没有给定默认按照UUID生成
          uri: lb://shop-product #真实转发的地址 lb: ---loadbalanced
          predicates: # 断言 如果断言满足要求,则转发到uri指定的真实地址.
            - Path=/product/** # 如果客户的请求路径以product开头,则满足该断言要求,则转发的uri真实地址。

        - id: shop-order
          uri: lb://shop-order
          predicates:
            - Path=/order/**

思考: 如果这时增加新的微服务, 需要修改网关的路由配置。

改为自动路由发现。

(1)修改gateway的配置文件
在这里插入图片描述
(2)访问网关
在这里插入图片描述

6. gateway流程

在这里插入图片描述

6.1 断言的种类

l 基于Datetime类型的断言工厂

此类型的断言根据时间做判断,主要有三个:

AfterRoutePredicateFactory: 接收一个日期参数,判断请求日期是否晚于指定日期

BeforeRoutePredicateFactory: 接收一个日期参数,判断请求日期是否早于指定日期

BetweenRoutePredicateFactory: 接收两个日期参数,判断请求日期是否在指定时间段内

-After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]

l 基于远程地址的断言工厂

RemoteAddrRoutePredicateFactory:接收一个IP地址段,判断请求主机地址是否在地址段中

-RemoteAddr=192.168.1.1/24

l 基于Cookie的断言工厂

CookieRoutePredicateFactory:接收两个参数,cookie 名字和一个正则表达式。 判断请求

cookie是否具有给定名称且值与正则表达式匹配。

-Cookie=chocolate, ch.

l 基于Header的断言工厂

HeaderRoutePredicateFactory:接收两个参数,标题名称和正则表达式。 判断请求Header是否

具有给定名称且值与正则表达式匹配。 key value

-Header=X-Request-Id, \d+

l 基于Host的断言工厂

HostRoutePredicateFactory:接收一个参数,主机名模式。判断请求的Host是否满足匹配规则。

-Host=**.testhost.org

l 基于Method请求方法的断言工厂

MethodRoutePredicateFactory:接收一个参数,判断请求类型是否跟指定的类型匹配。

-Method=GET

l 基于Path请求路径的断言工厂

PathRoutePredicateFactory:接收一个参数,判断请求的URI部分是否满足路径规则。

-Path=/foo/{segment}基于Query请求参数的断言工厂

QueryRoutePredicateFactory :接收两个参数,请求param和正则表达式, 判断请求参数是否具

有给定名称且值与正则表达式匹配。

-Query=baz, ba.

l 基于路由权重的断言工厂

WeightRoutePredicateFactory:接收一个[组名,权重], 然后对于同一个组内的路由按照权重转发

routes:

-id: weight_route1 uri: host1 predicates:

-Path=/product/**

-Weight=group3, 1

-id: weight_route2 uri: host2 predicates:

-Path=/product/**

-Weight= group3, 9

如果上面的内置断言无法满足需求 可以自定义断言。【了解】

案例: 年龄必须在18~65之间才能访问我指定的微服务。

自定义断言类

package com.aaa.predicate;

import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

import javax.validation.constraints.NotNull;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起2
 * @create: 2022-11-21 16:27
 **/
@Component
public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {


    public AgeRoutePredicateFactory() {
        super(AgeRoutePredicateFactory.Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("minAge", "maxAge");
    }
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {

        return (serverWebExchange)->{
            ServerHttpRequest request = serverWebExchange.getRequest();
            //获取传递的年龄
            String age = request.getHeaders().getFirst("age");
            if(StringUtils.hasText(age)){
                int a = Integer.parseInt(age);
                if(a>=config.getMinAge()&&a<=config.getMaxAge()){
                    return true;
                }
            }
            return false;
        };
    }

    @Validated
    public static class Config {
        @NotNull
        private int minAge;
        @NotNull
        private int maxAge;

        public int getMinAge() {
            return minAge;
        }

        public void setMinAge(int minAge) {
            this.minAge = minAge;
        }

        public int getMaxAge() {
            return maxAge;
        }

        public void setMaxAge(int maxAge) {
            this.maxAge = maxAge;
        }
    }
}

在这里插入图片描述
在这里插入图片描述

小结:
在这里插入图片描述
gateway:网关,路由转发

ribbon: 实现负载均衡

openfeign: 完成服务之间的调用。

nacos: 注册中心

6.2 gateway中的过滤器

为请求到达微服务前可以添加相应的请求设置, 响应后为响应结果添加一些设置。

gateway内部含有很多种过滤。
https://www.cnblogs.com/zhaoxiangjun/p/13042189.html

过滤器工厂作用参数
AddRequestHeader为原始请求添加HeaderHeader的名称及值
AddRequestParameter为原始请求添加请求参数参数名称及值
AddResponseHeader为原始响应添加HeaderHeader的名称及值
DedupeResponseHeader剔除响应头中重复的值需要去重的Header名称及去重策略
Hystrix为路由引入Hystrix的断路器保护HystrixCommand的名称
FallbackHeaders为fallbackUri的请求头中添加具体的异常信息Header的名称
PrefixPath为原始请求路径添加前缀前缀路径
PreserveHostHeader为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host
RequestRateLimiter用于对请求限流,限流算法为令牌桶keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus
RedirectTo将原始请求重定向到指定的URLhttp状态码及重定向的url
RemoveHopByHopHeadersFilter为原始请求删除IETF组织规定的一系列Header默认就会启用,可以通过配置指定仅删除哪些Header
RemoveRequestHeader为原始请求删除某个HeaderHeader名称
RemoveResponseHeader为原始响应删除某个HeaderHeader名称
RewritePath重写原始的请求路径原始路径正则表达式以及重写后路径的正则表达式
RewriteResponseHeader重写原始响应中的某个HeaderHeader名称,值的正则表达式,重写后的值
SaveSession在转发请求之前,强制执行WebSession::save操作
secureHeaders为原始响应添加一系列起安全作用的响应头无,支持修改这些安全响应头的值
SetPath修改原始的请求路径修改后的路径
SetResponseHeader修改原始响应中某个Header的值Header名称,修改后的值
SetStatus修改原始响应的状态码HTTP 状态码,可以是数字,也可以是字符串
StripPrefix用于截断原始请求的路径使用数字表示要截断的路径的数量
Retry针对不同的响应进行重试retries、statuses、methods、series
RequestSize设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large请求包大小,单位为字节,默认值为5M
ModifyRequestBody在转发请求之前修改原始请求体内容修改后的请求体内容
ModifyResponseBody修改原始响应体的内容修改后的响应体内容
Default为所有路由添加过滤器过滤器工厂名称及值

Tips:每个过滤器工厂都对应一个实现类,并且这些类的名称必须以GatewayFilterFactory结尾,这是Spring Cloud Gateway的一个约定,例如AddRequestHeader对应的实现类为AddRequestHeaderGatewayFilterFactory。

举例: StripPrefix 用于截断原始请求的路径。
在这里插入图片描述
测试:
在这里插入图片描述
例子: 设置响应的状态码2500
在这里插入图片描述
在这里插入图片描述

6.3 自定义全局过滤器

例子: 认证过滤。

内置的过滤器已经可以完成大部分的功能,但是对于企业开发的一些业务功能处理,还是需要我们自己编写过滤器来实现的,那么我们一起通过代码的形式自定义一个过滤器,去完成统一的认证校验。

开发中的鉴权逻辑:

  • 当客户端第一次请求服务时,服务端对用户进行信息认证(登录)

  • 认证通过,将用户信息进行加密形成token[jwt],返回给客户端,作为登录凭证

  • 以后每次请求,客户端都携带认证的token [携带请求头]

  • 服务端对token进行解密,判断是否有效。

在这里插入图片描述

package com.aaa.filter;

import com.alibaba.fastjson.JSON;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: qy156-shop-parent
 * @description:
 * @author: 闫克起2
 * @create: 2022-11-22 15:07
 **/
@Component
public class LoginFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //判断请求路径是否为放行。
        String path = request.getPath().toString();
        if("/login".equals(path)){
            return chain.filter(exchange);//放行
        }
        //获取请求头的token值。
        String token = request.getHeaders().getFirst("token");
        if(StringUtils.hasText(token)){
             //校验token是否有效
             if("admin".equals(token)){
                 return chain.filter(exchange);//放行
             }
        }

        //3.1设置状态码
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        //3.2封装返回数据
        Map<String, Object> map = new HashMap<>();
        map.put("msg", "未登录");
        map.put("code", "NOTLOGING");

        //3.3作JSON转换
        byte[] bytes = JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8);

        //3.4调用bufferFactory方法,生成DataBuffer对象
        DataBuffer buffer = response.bufferFactory().wrap(bytes);

        //4.调用Mono中的just方法,返回要写给前端的JSON数据
        return response.writeWith(Mono.just(buffer));
    }

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

7. 统一跨域解决

第一种通过配置文件

spring:
 cloud:
     gateway:
       globalcors:
         cors-configurations:
           '[/**]':
             allowedOrigins: "*"
             allowedHeaders: "*"
             allowedMethods: "*"
       default-filters:
        		- DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST

第二种写一个配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;

@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

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

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

相关文章

【QT】编译QtWebEngine(Build QtWebEngine from source)Win10+QT5.7.1_x64+VS2015

1、前言 关于QtWebEngine是干什么的&#xff0c;怎么用的&#xff0c;不在此赘述。 1.1、为什么要编译QtWebEngine QT默认的QtWebEngine是不支持mp3、mp4解码的&#xff0c;也就是说&#xff0c;如果想要在QT浏览网页的时候支持在线播放音视频&#xff0c;就需要让QtWebEngi…

前端品优购项目准备工作

网站制作流程&#xff1a; 初稿审核&#xff1a;网页美工会制作原型图和psd效果图 品优购项目规划&#xff1a; 1 品优购项目整体介绍 描述&#xff1a;电商网站&#xff0c;要完成PC端首页&#xff0c;列表页&#xff0c;注册页面的制作 2 品优购项目学习目的 电商类网站比…

nRF Connect for Desktop[自己的APP环境搭建]

本文源码仓库地址:https://github.com/NordicSemiconductor/pc-nrfconnect-ble/blob/main/package.json nRF Connect for Desktop是nordic自己做的一个PC端的蓝牙工具,配合nordic的dongle可以实现蓝牙的很多功能,要浏览本文要有如下知识储备: 1.nRF Connect for Desktop的APP是…

ELFK集群部署与Logstash的过滤模块

ELFK集群部署与Logstash的过滤模块ELFK集群部署与Logstash的过滤模块一、ELFK集群部署&#xff08;FilebeatELK&#xff09;Filebeatfilebeat 结合 logstash 带来好处&#xff1a;1.1 部署ELK集群1.2 安装Filebeat&#xff08;Apache节点&#xff09;1.3 设置 filebeat 的主配置…

TimeSformer:Is Space-Time attention all you need for video understanding?

【实践】CV领域的Transformer模型TimeSformer实现视频理解 - 飞桨AI Studio本项目选取CV中的transformer模型TimeSformer进行项目开发&#xff0c;在UCF101数据集上训练、验证、评估 - 飞桨AI Studiohttps://aistudio.baidu.com/aistudio/projectdetail/3413254?contributionT…

Zookeeper系列文章-Curator

之前我们讲解了Zookeeper安装与Zookeeper常用命令讲解 linux安装Zookeeper3.5.7详解_兜兜转转m的博客-CSDN博客 Zookeeper系列文章—入门_兜兜转转m的博客-CSDN博客 由于我们需要利用Java进行开发&#xff0c;因此我们使用Curator对Zk进行操控 导入依赖&#xff0c;由于使用…

作业-11.22

1、TCP服务器和客户端交互 服务器 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #define ERR_MSG(msg) do{\ …

Java基础—反射

反射 我们来探讨Java中的一些动态特性&#xff0c;包括反射、注解、动态代理、类加载器等。利用这些特性&#xff0c;可以优雅地实现一些灵活通用的功能&#xff0c;它们经常用于各种框架、库和系统程序中&#xff0c;比如&#xff1a; 1&#xff09;14.5节介绍的Jackson&…

MAC苹果电脑关闭系统完整性保护SIP

苹果电脑从 macOS 10.11 开始引入了系统完整性保护机制SIP&#xff08;System Integrity Protection&#xff09;&#xff0c;目的是帮助普通用户避免恶意 app 通过用户授权的方式获得所有系统权限。通过 System Integrity Protection&#xff0c;苹果实现了对第三方软件的限制…

SpringBoot SpringBoot 开发实用篇 5 整合第三方技术 5.14 SpringBoot 整合 quartz

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇5 整合第三方技术5.14 SpringBoot 整合 quartz5.14.1 任务【定时任务…

Linux-cut

cut命令介绍 cut命令将文件的每一行剪切字节&#xff0c;字符和字段&#xff0c;并将这些字节&#xff0c;字符和字段写到标准输出 提取列&#xff0c;cut命令不能提取空格&#xff0c;可以是制表符或者其他字符 cut [选项][文件] 选项&#xff1a; -b&#xff1a;以字节为单…

2.5、信道的极限容量!

2.5、信道的极限容量&#xff01; 2.5.1、因素影响 由于信号在传输过程中会受到各种因素的影响 例如&#xff1a;这是一个数字信号 当它通过实际的信道后&#xff0c;波形会产生失真。 失真不严重时&#xff0c;在输出端还可根据已失真的波形还原出发送的码元 当失真严重…

G1D20-AnacondaCSKE综述AttacKG终于配好环境啦KG book CTF

先下一个anaconda emmmpipenv install requirements.txt好像不太好用&#xff0c;还不如pycharm中的自动安装 先读论文啦~ 一、CS KE综述 &#xff08;一&#xff09;NER systems 1、判别式模型&生成式模型 判别式模型&#xff1a;学习P&#xff08;Y|X&#xff09;&am…

C语言-结构体(7)

目录 思维导图&#xff1a; 1. 结构体的声明 1.1 结构的基础知识 1.2 结构的声明 1.3 结构成员的类型 1.4 结构体变量的定义和初始化 2. 结构体成员的访问 3. 结构体传参 写在最后&#xff1a; 思维导图&#xff1a; 1. 结构体的声明 1.1 结构的基础知识 结构是一些…

python一键去PDF水印,只需十行代码,超级简单...

用python制作去除 pdf 文件水印脚本前因后果去除水印原理代码剖析1、先查看PDF文档中的水印rgb值是多少2、pdf转换成图片&#xff0c;并去除水印3、图片转为pdf代码整合总结前因后果 弟弟最近要考试&#xff0c;临时抱佛脚在网上找了一堆学习资料复习&#xff0c;这不刚就来找…

机器学习-sklearn-高斯混合模型-学习笔记

文章目录前言一、如何估计参数二、二分类原生代码实现三、sklearn实现模型总结前言 学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1rB4y1v7dA/?spm_id_from333.788&vd_sourceaf83080eba7b379d3fda36e341bdb195 使用高斯混合模型的原因&#xff1a; 模…

03137计算机网络原 - 物理层

物理层 基础概念 OSI模型最底层 功能 为在链路实体间传送比特流而对物理连接的 接通 维持 和 拆除 提供机械,电气,功能和规程方面的方法作用 尽可能屏蔽现有多种多样的硬件设备,传输媒体和通信手段的差异。确保原始数据可以在各种物理媒介上传输任务特性 机械特性 指明接…

Linux环境变量与程序地址空间

Linux环境变量与程序地址空间 文章目录Linux环境变量与程序地址空间1.环境变量1.1 环境变量概念与深入理解1.2 代码获取环境变量的方法1.3 系统调用获取和设置环境变量的方法2.程序地址空间2.1 程序地址空间图(准确来说是进程地址空间图)2.2 程序地址空间的验证2.3 进程地址空间…

概率论中的几个重要悖论问题

1. 蒙提霍尔问题&#xff08;三门问题&#xff09; 三门问题&#xff08;Monty Hall problem&#xff09;亦称为蒙提霍尔问题、蒙特霍问题或蒙提霍尔悖论&#xff0c;大致出自美国的电视游戏节目Lets Make a Deal。问题名字来自该节目的主持人蒙提霍尔&#xff08;Monty Hall&…

【笑小枫的SpringBoot系列】【十八】SpringBoot中的Properties配置

本文简介&#x1f3a8; 随着我们的演示功能越来越多&#xff0c;里面的配置也越来越多&#xff0c;我们怎么更好的来管理这些配置呢&#xff1f; 实际项目中&#xff0c;我们肯定会有开发环境、测试环境、生产环境&#xff0c;我们又该怎么便捷的配置这些环境呢&#xff1f; …