微服务Gateway网关(自动定位/自定义过滤器/解决跨域)+nginx反向代理gateway集群

目录

Gateway网关

1.0.为什么需要网关?

1.1.如何使用gateway网关

1.2.网关从注册中心拉取服务

1.3.gateway自动定位

1.4.gateway常见的断言

1.5.gateway内置的过滤器

1.6.自定义过滤器-全局过滤器

1.7.解决跨域问题

2.nginx反向代理gateway集群

2.1.配置文件


继  nacos注册中心+Ribbon负载均衡+完成openfeign的调用(超详细步骤) 文章扩展Gateway网关

常见的API网关:

 Ngnix+lua

使用nginx的反向代理和负载均衡可实现对api服务器的负载均衡及高可用、lua是一种脚本语言,可以来编写一些简单的逻辑, nginx支持lua脚本

Kong

基于Nginx+Lua开发,性能高,稳定,有多个可用的插件(限流、鉴权等等)可以开箱即用。 问题:

只支持Http协议;二次开发,自由扩展困难;提供管理API,缺乏更易用的管控、配置方式。

Zuul 1.0----老的微服务项目

Netflix开源的网关,功能丰富,使用JAVA开发,易于二次开发 问题:缺乏管控,无法动态配

置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如Nginx

Netflix提出理论---Zuul2.0 远远超过1.0---实际的产品没有出来。

Spring Cloud Gateway

Spring公司为了替换Zuul而开发的网关服务,将在下面具体介绍。

注意:SpringCloud alibaba技术栈中并没有提供自己的网关,我们可以采用Spring Cloud Gateway来做网关

Gateway网关

Gateway简介

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

1.0.为什么需要网关?

Gateway网关是我们服务的守门神,所有微服务的统一入口。

网关的核心功能特性

  • 请求路由

  • 权限控制

  • 限流

架构图:

  • 权限控制
  • 网关作为微服务入口,需要校验用户是是否有请求资格,如果没有则进行拦截。

  • 路由和负载均衡
  • 一切请求都必须先经过gateway,但网关不处理业务,而是根据某种规则,把请求转发到某个微服务,这个过程叫做路由。当然路由的目标服务有多个时,还需要做负载均衡。

  • 限流
  • 当请求流量过高时,在网关中按照下流的微服务能够接受的速度来放行请求,避免服务压力过大。

1.1.如何使用gateway网关

(1).创建一个网关微服务模块并引用依赖

 <dependencies><!--引入gateway依赖--><!--不能再引入spring-boot-starter-web依赖,因为web依赖中存在tomcat服务器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency></dependencies>

(2).创建配置文件

#端口号
server:port: 81#服务名称
spring:application:name: qy165-gateway#配置路由转发规则cloud:gateway:routes:- id: qy165-product            #路由的标识  唯一即可   默认按照UUID生成uri: http://localhost:8001   #真实路由转发的地址predicates:                  #断言:只要满足断言条件才会帮你转发到相应的url地址- Path=/product/**- id: qy165-orderuri: http://localhost:9001predicates:- Path=/order/**

(3).启动类

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

测试

发现uri地址是一个死数据,未来可以是集群。

如何解决?

我们也可以把网关交于注册中心来管理,那么网关就可以从注册中心拉取服务信息。

1.2.网关从注册中心拉取服务

(1).在网关微服务中引入nacos注册中心依赖

<!--nacos注册中心的依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>

(2).修改网关的配置

#端口号
server:port: 81#服务名称
spring:application:name: qy165-gateway#配置路由转发规则cloud:gateway:routes:- id: qy165-product            #路由的标识  唯一即可   默认按照UUID生成uri: lb://qy165-product      #真实路由转发的地址:lb://微服务的名称predicates:                  #断言:只要满足断言条件才会帮你转发到相应的url地址- Path=/product/**- id: qy165-orderuri: lb://qy165-orderpredicates:- Path=/order/**#指定注册中心的地址nacos:discovery:server-addr: localhost:8848register-enabled: false        #只拉取不注册

思考: 如果未来有1w个微服务,那么就需要在gateway中配置1w微服务的路由

解决方案: 可以使用gateway自动定位功能

1.3.gateway自动定位

修改配置文件

#端口号
server:port: 81#服务名称
spring:application:name: qy165-gateway#指定注册中心的地址nacos:discovery:server-addr: localhost:8848register-enabled: false        #只拉取不注册#开启微服务自动定位功能cloud:gateway:discovery:locator:enabled: true

 测试

原理:  

1.4.gateway常见的断言

基于Datetime类型的断言工厂

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

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

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

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

演示:

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

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

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

演示: 

-RemoteAddr=172.16.7.128/24   (24--代表同一个域内都可以访问)

基于Cookie的断言工厂

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

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

-Cookie=chocolate, ch.

基于Header的断言工厂

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

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

演示: 

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

基于Host的断言工厂

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

-Host=**.testhost.org

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

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

-Method=GET

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

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

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

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

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

-Query=baz, ba.

基于路由权重的断言工厂

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

routes:

-id: weight_route1 uri: host1 predicates:

-Path=/product/**

-Weight=group3, 1

-id: weight_route2 uri: host2 predicates:

-Path=/product/**

-Weight= group3, 9

1.5.gateway内置的过滤器

演示: 

后置过滤器

演示: 

前置过滤器

1.6.自定义过滤器-全局过滤器

  • 认证判断
  • 权限校验
  • 黑白名单
  • 跨域配置

认证判断

  • 当客户端第一次请求服务时,服务端对用户进行信息认证(登录)
  • 认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证
  • 以后每次请求,客户端都携带认证的token
  • 服务端对token进行解密,判断是否有效。

如上图,对于验证用户是否已经登录鉴权的过程可以在网关统一检验。

检验的标准就是请求中是否携带token凭证以及token的正确性。

如何定义全局过滤器:

引依赖

        <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.15</version></dependency>

配置文件加入

#过滤器路径
filter:whitePaths:          #白名单路径- "/product/login"- "/product/aaa"blackPaths:          #黑名单路径- "/product/bbb"

 创建FilterUrl黑白名单

@Component
@ConfigurationProperties(prefix = "filter")
public class FilterUrl {private Set<String> whitePaths=new HashSet<>();private Set<String> blackPaths=new HashSet<>();public Set<String> getWhitePaths() {return whitePaths;}public void setWhitePaths(Set<String> whitePaths) {this.whitePaths = whitePaths;}public Set<String> getBlackPaths() {return blackPaths;}public void setBlackPaths(Set<String> blackPaths) {this.blackPaths = blackPaths;}
}

创建LoginFilter全局过滤器:

package com.wqg.gateway.filter;import com.alibaba.fastjson.JSON;
import com.wqg.gateway.vo.FilterUrl;
import org.springframework.beans.factory.annotation.Autowired;
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.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;/*** @ fileName:LoginFilter* @ description:* @ author:wqg* @ createTime:2023/7/17 15:23*/
@Component
public class LoginFilter implements GlobalFilter , Ordered {@Autowiredprivate FilterUrl filterUrl;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();//过滤的业务代码//1.获取请求路径String path = request.getPath().toString();//判断该路径是否放行路径if(filterUrl.getWhitePaths().contains(path)){return chain.filter(exchange);}//获取请求头String token = request.getHeaders().getFirst("token");//查看redis中是否存在该tokenif(StringUtils.hasText(token)&&"admin".equals(token)){//放行return chain.filter(exchange);}//响应json数据Map<String, Object> map = new HashMap<>();map.put("msg", "未登录");map.put("code", 403);//JSON转换byte[] bytes = JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8);//调用bufferFactory方法,生成DataBuffer对象DataBuffer buffer = response.bufferFactory().wrap(bytes);//调用Mono中的just方法,返回要写给前端的JSON数据return response.writeWith(Mono.just(buffer));}//Ordered:优先级  值越小,优先级越高@Overridepublic int getOrder() {return 0;}}

1.7.解决跨域问题

(1) 第一种写个跨域配置类

package com.wqg.gateway.config;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 CorConfig {//处理跨域@Beanpublic 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);}
}

(2)第二种跨域解决写在配置文件中

#端口号
server:port: 81#服务名称
spring:application:name: qy165-gateway#配置路由转发规则cloud:gateway:#解决跨域globalcors:add-to-simple-url-handler-mapping: truecors-configurations:'[/**]':                 #拦截的请求allowedOrigins:        #允许跨域的请求- "*"allowedMethods:        #运行跨域的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*"     #允许请求中携带的头信息allowCredentials: true  #是否允许携带cookiemaxAge: 36000           #跨域检测的有效期,单位sroutes:- id: qy165-product            #路由的标识  唯一即可   默认按照UUID生成uri: lb://qy165-product      #真实路由转发的地址:lb://微服务的名称predicates:                  #断言:只要满足断言条件才会帮你转发到相应的url地址- Path=/product/**
#            - After=2023-12-31T23:59:59.789+08:00[Asia/Shanghai]  #要求在2023-12-31以后才可以访问该微服务
#            - RemoteAddr=172.16.7.128  #只允许ip为172.16.7.128访问
#            - Header=token,\d+
#          filters:
#            - SetStatus=250  #修改原始响应的状态码
#            - StripPrefix=1- id: qy165-orderuri: lb://qy165-orderpredicates:- Path=/order/**#指定注册中心的地址nacos:discovery:server-addr: localhost:8848register-enabled: false        #只拉取不注册#过滤器路径
filter:whitePaths:          #白名单路径- "/product/login"- "/product/aaa"blackPaths:          #黑名单路径- "/product/bbb"

 上面的方案选择一个就行

2.nginx反向代理gateway集群

2.1.配置文件

(1) nginx.conf配置

(2) 模拟gateway集群 

(3) 最后分别启动gateway服务即可 

测试

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Upsource的下载安装使用

一&#xff0c;下载 下载地址&#xff1a; https://www.jetbrains.com/upsource/下载并解压到指定的文件夹 ├── api ├── apps ├── backups # 备份目录 ├── bin # 应用目录 ├── conf # 配置文件 ├── data ├── internal ├── launcher ├── lib ├─…

Java集合详解

1. 集合基础 1.1 集合概述 1.2 ArrayList构造方法和添加方法 1.3 ArrayList集合常用方法 1. 集合基础 1.1 集合概述 集合类的特点:提供一种存储空间可变的存储横型&#xff0c;存储的数据容量可以发生改变 ArrayList ArrayList< >: 可调整大小的数组实现 < >:是…

TextView 必填项pro版

优点 基本解决对齐方式,可以设置前缀隐藏和显示 /*** https://blog.csdn.net/u013982652/article/details/94404711* Android自定义TextView实现必填项前面的*号* 另一种实现方式(推荐使用这种,有非必填情况的话不会有对齐问题)* <p>* <cn.mvp.mlibs.weight.MiRequire…

【Fiddler】Fiddler实现mock测试(模拟接口数据)

软件接口测试过程中&#xff0c;经常会遇后端接口还没有开发完成&#xff0c;领导就让先介入测试&#xff0c;然后缩短项目时间&#xff0c;有的人肯定会懵&#xff0c;接口还没开发好&#xff0c;怎么介入测试&#xff0c;其实这就涉及到了我们要说的mock了。 一、mock原理 m…

CentOS 安装字体 微软雅黑

fc-list命令查看已经安装的字体 fc-list :langzh命令可以查看已安装的中文字体 找到windows系统里面的字体 上传到服务器 /usr/share/fonts/winFonts 下&#xff0c;winFonts目录是自己建立的&#xff0c;名称无要求 如果C:\Windows\Fonts下的字体没法直接传输将这个文件夹复…

Leetcode-每日一题【24.两两交换链表中的节点】

题目 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4]输出&#xff1a;[…

rust 引用怎么用

本来好好的引用&#xff0c;被 rust 玩坏了&#xff0c;搞得自己都不会使用引用了&#xff0c;我们还是从简单的例子入手&#xff0c;来探索使用引用可能遇到额问题。 下面的示例代码编译不通过&#xff0c;在 s1 赋值给变量 s2 的过程中&#xff0c;字符串 neojos 值的所有权…

dede tag彩色随机大小的样式修改方法

dede tag彩色随机大小的样式修改方法&#xff0c;打开include/common.func.php 在最下面添加以下代码&#xff1a; //TAG彩色 jinmengqiang.cn function getTagStyle() { $minFontSize8; //最小字体大小,可根据需要自行更改 $maxFontSize18; //最大字体大小,可根据需要自行更改…

Unity 上传文件到阿里云 对象存储OSS服务器

首先登录阿里云 免费试用–对象存储OSS --点击立即试用&#xff0c;可以有三个月的免费试用 创建Buket 新建AccessKey ,新建完成后&#xff0c;会有一个CSV文件&#xff0c;下载下来&#xff0c;里面有Key &#xff0c;代码中需要用到 下载SDK 双击打开 sln文件&#xff0…

STM32(HAL库)通过ADC读取MQ2数据

目录 1、简介 2、CubeMX初始化配置 2.1 基础配置 2.1.1 SYS配置 2.1.2 RCC配置 2.2 ADC外设配置 2.3 串口外设配置 2.4 项目生成 3、KEIL端程序整合 3.1 串口重映射 3.2 ADC数据采集 3.3 主函数代 3.4 效果展示 1、简介 本文通过STM32F103C8T6单片机通过HAL库方式对M…

解决Git fatal: refusing to merge unrelated histories报错

问题描述 当在远程建立了一个仓库&#xff0c;并且远程的仓库已经初始化了的情况&#xff0c;使用 git remote add origin gitgithub.com:xxx/xxx.git命令添加远程仓库后&#xff0c;执行git pull,然后提示如下&#xff1a; 大致意思就是需要关联我们的本地和远程分支。按照…

Nginx正向代理和反向代理详解

目录 一、什么是正向代理&#xff1f; 二、什么是反向代理&#xff1f; 三、正向代理和反向代理的作用 一、什么是正向代理&#xff1f; 正向代理&#xff0c;“它代理的是客户端”&#xff0c;是一个位于客户端和目标服务器之间的服务器&#xff0c;为了从目标服务器取得内…