【SpringCloud-5】gateway网关

网关是干啥用的就不用再说了。 sringcloud中的网关,第一代是zuul,但是性能比较差(1.x是阻塞式的,2.x是基于Netty的),然后有了第二代GateWay,基于Reactor模型 异步非阻塞。

 springcloud网关就是一系列的filter,在请求到达真实服务的前后,进行拦截处理。

 

GateWay核⼼逻辑:路由转发+执⾏过滤器链

客户端向GateWay发出请求,然后在GateWay Handler Mapping中 找到与请求相匹配的路由,将其发送到GateWay Web Handler;Web Handler再通过指定的过滤器链来将请求发送到我们实际的服务执⾏业务逻辑,然后返回。

Filter “pre” 类型过滤器中可以做参数校验、权限校验、流量监控、⽇志输出、协议转换等,在“post” 类型的过滤器中可以做响应内容、响应头的修改、⽇志的输出、流量监控等。

 

GateWay搭建使用:

引入依赖:

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--GateWay 网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--引入webflux-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <!--日志依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <!--测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--lombok工具-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

        <!-- Actuator可以帮助你监控和管理Spring Boot应用-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

yml配置:

server:
  port: 9002
eureka:
  client:
    serviceUrl: # eureka server的路径
      defaultZone: http://lagoucloudeurekaservera:8761/eureka/,http://lagoucloudeurekaserverb:8762/eureka/ #把 eureka 集群中的所有 url 都填写了进来,也可以只写一台,因为各个 eureka server 可以同步注册表
  instance:
    #使用ip注册,否则会使用主机名注册了(此处考虑到对老版本的兼容,新版本经过实验都是ip)
    prefer-ip-address: true
    #自定义实例显示格式,加上版本号,便于多版本管理,注意是ip-address,早期版本是ipAddress
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
spring:
  application:
  name: lagou-cloud-gateway
  cloud:
    gateway:
      routes: # 路由可以有多个
        - id: service-autodeliver-router # 我们自定义的路由 ID,保持唯一
          #uri: http://127.0.0.1:8096  # 目标服务地址  自动投递微服务(部署多实例)  动态路由:uri配置的应该是一个服务名称,而不应该是一个具体的服务实例的地址
#uri以 lb: //开头(lb代表从注册中⼼获取服务)
          uri: lb://lagou-service-autodeliver                                                                    # gateway网关从服务注册中心获取实例信息然后负载后路由
          predicates:                                         # 断言:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默 认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
            - Path=/autodeliver/**
        - id: service-resume-router      # 我们自定义的路由 ID,保持唯一
          #uri: http://127.0.0.1:8081       # 目标服务地址
          #http://localhost:9002/resume/openstate/1545132

          #http://127.0.0.1:8081/openstate/1545132
          uri: lb://lagou-service-resume
          predicates:                                         # 断言:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默 认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
            - Path=/resume/**
          filters:
            - StripPrefix=1

注意:上面yml中有个配置:- StripPrefix=1,就是指定了一个StripPrefix过滤器,它的作用是除去url中的第1个前缀。 假如url为 /resume/test/xxx,真实访问到服务的url就没有/resume了。    另外,还有一个过滤器PrefixPath作用相反,如果配置: -  PrefixPath=/user,那么真实访问的url会在最前面加上/user。

GateWay路由规则:

置了很多 Predicates功能,实现了各种路由匹配规则(通过 Header、请求参数等作为条件)匹配到对应的路由。

 下面来具体看看每一种如何配置:

  • 时间点后匹配(请求时间在该时间点后的):
    • spring:
        cloud:
          gateway:
            routes:
              - id: after_route
                uri: https://example.org
                predicates: 
                  - After=2017-01-20T17:42:47.789-07:00[America/Denver]
  • 时间点前匹配:
    • spring:
        cloud:
          gateway:
            routes:
              - id: before_route
                uri: https://example.org
                predicates: 
                  - Before=2017-01-20T17:42:47.789-07:00[America/Denver]
  • 时间区间匹配:
    • spring:
        cloud:
          gateway:
            routes:
              - id: between_route
                uri: https://example.org
                predicates: 
                  - Between=2017-01-20T17:42:47.789-07:00[America/Denver],
      2018-01-20T17:42:47.789-07:00[America/Denver]
  • 指定cookie匹配(cookie中有authToken的):
    • spring:
        cloud:
          gateway:
            routes:
              - id: cookie_route
                uri: https://example.org
                predicates: 
                  - Cookie=authToken
  • 指定header匹配:
    • spring:
        cloud:
          gateway:
            routes:
              - id: header_route
                uri: https://example.org
                predicates: 
                  - Header=X-Request-Id
  • 指定host匹配:
    • spring:
        cloud:
          gateway:
            routes:
              - id: host_route
                uri: https://example.org
                predicates: 
                  - Host=Host=**.somehost.org,**.anotherhost.org
  • 指定method匹配:
    • spring:
        cloud:
          gateway:
            routes:
              - id: method_route
                uri: https://example.org
                predicates: 
                  - Method=GET,POST
  • 请求路径匹配:
    • spring:
        cloud:
          gateway:
            routes:
              - id: path_route
                uri: https://example.org
                predicates: 
                  - Path=/red/{segment},/blue/{segment}
  • 请求包含某参数匹配:
    • spring:
        cloud:
          gateway:
            routes:
              - id: query_route
                uri: https://example.org
                predicates: 
                  - Query=green
  • 远程地址匹配:
    • spring:
        cloud:
          gateway:
            routes:
              - id: remoteaddr_route
                uri: https://example.org
                predicates: 
                  - RemoteAddr=192.168.1.1/24
  • 动态路由-就是除了gateway自带的,我们可以自己定义,就像上面yml文件中那样

GateWay 过滤器:
 
作用时机划分:
pre:
前置过滤器,请求到达服务之前作用。我们可利⽤这种过滤器实现身份验证、在集群中选择 请求的微服务、记录调试信息等。
post:
后置过滤器,请求从服务返回之后作用。这种过滤器可⽤来为响应添加标准的 HTTP Header 、收集统计信息和指标、将响应从微服务发送给客户端等。
作用范围划分:
GateWayFilter:应用到单个路由。
GlobalFilter:应用到所有路由。
GlobalFilter用的最多,下面自定义一个全局过滤器(实现GlobalFilter即可):
当请求过来时,判断发送请求的客户端的 ip ,如果在⿊名单中,拒绝访问。
package com.lagou.edu.filter;

import lombok.extern.slf4j.Slf4j;
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.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;

/**
 * 定义全局过滤器,会对所有路由生效
 */
@Slf4j
@Component  // 让容器扫描到,等同于注册了
public class BlackListFilter implements GlobalFilter, Ordered {

    // 模拟黑名单(实际可以去数据库或者redis中查询)
    private static List<String> blackList = new ArrayList<>();

    static {
        blackList.add("0:0:0:0:0:0:0:1");  // 模拟本机地址
    }

    /**
     * 过滤器核心方法
     * @param exchange 封装了request和response对象的上下文
     * @param chain 网关过滤器链(包含全局过滤器和单路由过滤器)
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 思路:获取客户端ip,判断是否在黑名单中,在的话就拒绝访问,不在的话就放行
        // 从上下文中取出request和response对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        // 从request对象中获取客户端ip
        String clientIp = request.getRemoteAddress().getHostString();
        // 拿着clientIp去黑名单中查询,存在的话就决绝访问
        if(blackList.contains(clientIp)) {
            // 决绝访问,返回
            response.setStatusCode(HttpStatus.UNAUTHORIZED); // 状态码
            log.debug("=====>IP:" + clientIp + " 在黑名单中,将被拒绝访问!");
            String data = "Request be denied!";
            DataBuffer wrap = response.bufferFactory().wrap(data.getBytes());
            return response.writeWith(Mono.just(wrap));
        }

        // 合法请求,放行,执行后续的过滤器
        return chain.filter(exchange);
    }


    /**
     * 返回值表示当前过滤器的顺序(优先级),数值越小,优先级越高
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

过滤器定义好后,无须其他配置。 只要被spring容器扫描到成为一个bean,即可生效。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++智能指针

RAII RAII&#xff08;Resource Acquisition Is Initialization&#xff09;是一种利用对象生命周期来控制程序资源的技术 不需要显示的释放资源对象的资源在其生命周期类保持有效 通常控制的资源&#xff1a;动态申请的内存、文件描述符、互斥量、网络连接等 在对象构造时…

多线程/std::thread线程退出方式详解

文章目录 概述不 join 也不 detach执行了detach并不能万事大吉建议使用 join 函数 概述 这里默认你已经了解 std::thread 类的基本使用&#xff0c;和WinAPI多线程编程中 “如何优雅的退出线程” 等相关知识。阅读该文前&#xff0c;建议先看看《多线程 /C 11 std::thread 类深…

python、pyqt5实现人脸检测、性别和年龄预测

摘要&#xff1a;这篇博文介绍基于opencv&#xff1a;DNN模块自带的残差网络的人脸、性别、年龄识别系统&#xff0c;系统程序由OpenCv, PyQt5的库实现。如图系统可通过摄像头获取实时画面并识别其中的人脸表情&#xff0c;也可以通过读取图片识别&#xff0c;本文提供完整的程…

【IIS建站教程】windows本地搭建web服务,内网穿透发布公网访问

✨个人主页&#xff1a;bit me&#x1f447; 目 录 &#x1f43e;1.前言&#x1f490;2.Windows网页设置&#x1f338;2.1 Windows IIS功能设置&#x1f337;2.2 IIS网页访问测试 &#x1f340;3. Cpolar内网穿透&#x1f339;3.1 下载安装Cpolar&#x1f33b;3.2 Cpolar云端设…

【Leetcode60天带刷】day36——56. 合并区间,738.单调递增的数字

​ 题目&#xff1a; 56. 合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a;…

菜鸡shader:L4三色环境光原理妙用并在ue4中实现

三色环境光的拓展运用 我的上一篇博客写了关于三色环境光的原理&#xff0c;这次就来简单拓展一下。最重要的核心思想其实就是取法线向量的第二个分量&#xff0c;因为它控制方法是指向xz平面的上或者下。 所以这次要用这个原来来单独摘出上层环境光&#xff0c;乘上菲涅尔&a…

ASP.NET Core Web API之Token验证

在实际开发中&#xff0c;我们经常需要对外提供接口以便客户获取数据&#xff0c;由于数据属于私密信息&#xff0c;并不能随意供其他人访问&#xff0c;所以就需要验证客户身份。那么如何才能验证客户的身份呢&#xff1f;今天以一个简单的小例子&#xff0c;简述ASP.NET Core…

交叉熵、Focal Loss以及其Pytorch实现

交叉熵、Focal Loss以及其Pytorch实现 本文参考链接&#xff1a;https://towardsdatascience.com/focal-loss-a-better-alternative-for-cross-entropy-1d073d92d075 文章目录 交叉熵、Focal Loss以及其Pytorch实现一、交叉熵二、Focal loss三、Pytorch1.[交叉熵](https://pyto…

Python 动态生成系统数据库设计到word文档

背景 经常需要交付一些系统文档而且基本都是word的&#xff0c;其中又有系统数据库介绍模块&#xff0c; 看着数据库里的几百张表于是我开始怀疑人生, 所以咱手写一个 涉及知识 pymysql 操作数据库 -tkinter GUI图形库threading 线程queue 阻塞队列pandas python数据计算…

layui(5)——内置模块分页模块

模块加载名称&#xff1a;laypage laypage 的使用非常简单&#xff0c;指向一个用于存放分页的容器&#xff0c;通过服务端得到一些初始值&#xff0c;即可完成分页渲染&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset&quo…

RocketMQ --- 实战篇

一、案例介绍 1.1、业务分析 模拟电商网站购物场景中的【下单】和【支付】业务 1.1.1、下单 流程 用户请求订单系统下单 订单系统通过RPC调用订单服务下单 订单服务调用优惠券服务&#xff0c;扣减优惠券 订单服务调用调用库存服务&#xff0c;校验并扣减库存 订单服务调…

长尾关键词有什么作用?要怎么用?

长尾关键词很多的网站都会忽略其存在&#xff0c;其实你不要小看长尾关键词&#xff0c;他将带给网站的流量也是极其可观的&#xff0c;所说比不上那些重点关键词的流量&#xff0c;但是对提升网站的权重还是有着重要的作用。 长尾关键词有什么用&#xff1f;长尾关键词的3…

Gitlab群组及项目仓库搭建

1、新建群组 2、新建项目 3、克隆到Visualstudio 复制克隆地址&#xff0c;克隆到本地 这里会让你登录账号 可以添加成员并邀请ta进项目组 从已注册用户列表中选择 4、Git工作流 回顾一下Git工作流&#xff0c;工程人员只需要从Develop分支新建自己的分支即可。分支命名以姓名…

CadLib 4.0.2023.31601 net for Windows Crack

CadLib 4.0 for Windows&#xff1a;在 C# VB .NET 中读取、写入和显示 AutoCAD DWG 和 DXF 文件 CadLib 4.0 for Windows仅在Windows上运行&#xff0c;并且基于.NET 4.x。 CadLib 4.0读取、写入和显示 C#、VB.NET 或任何其他 .NET 语言的 AutoCAD™ DWG 和 DXF 文件。下载试…

2-css-3

一 选择器 1 结构伪类选择器 作用&#xff1a;根据元素的结构关系查找元素。 选择器说明E:first-child查找第一个E元素E:last-child查找最后一个E元素E:nth-child(N)查找第N个E元素&#xff08;第一个元素N值为1&#xff09; li:first-child {background-color: green; }2 :…

5.6.3 套接字

5.6.3 套接字 我们先以示例引入套接字的基本内容&#xff0c;我们知道在邮政通信的时候我们需要在信封上写明我们的收件地址&#xff0c;比如北京市海淀区双清路30号清华大学8444号某某某收&#xff0c;这其中我们需要一个物理地址“北京市海淀区双清路30号”&#xff0c;一个…

6.22 驱动开发作业

字符设备驱动内部实现原理 1.字面理解解析&#xff1a; 字符设备驱动的内部实现有两种情况&#xff1a; 情况1.应用层调用open函数的内部实现&#xff1a; open函数的第一个参数是要打开的文件的路径&#xff0c;根据这个路径 虚拟文件系统层VFS 可以找到这个文件在文件系统…

openeuler22.03系统salt-minion启动报“Invalid version: ‘cpython‘“错的问题处理

某日&#xff0c;检查发现一台openeuler22.03 SP1系统的服务器上之前正常运行的saltstack客户端minion未运行&#xff0c;查看服务状态&#xff0c;报"Invalid version: cpython"错&#xff0c;无法正常运行&#xff0c;本文记录问题处理过程。 一、检查salt-minion…

uniapp中小程序的生命周期

一、uni-app应用生命周期 函数名说明onLuaunch当uni-app 初始化完成时触发&#xff08;全局只触发一次&#xff09;onShow当 uni-app 启动&#xff0c;或从后台进入前台显示onHide当 uni-app 从前台进入后台onError当 uni-app 报错时触发onUniNViewMessage对 nvue 页面发送的数…

android jetpack Room的基本使用(java)

数据库的基本使用 添加依赖 //roomdef room_version "2.5.0"implementation "androidx.room:room-runtime:$room_version"annotationProcessor "androidx.room:room-compiler:$room_version"创建表 Entity表示根据实体类创建数据表&#xff0c…