微服务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.mzph.cn/news/1360.shtml

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

相关文章

什么是 TCP 和 UDP?Java 中如何实现 TCP 和 UDP 协议

在计算机网络中&#xff0c;TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;是两种最常用的传输层协议。它们都用于在网络上传输数据&#xff0c;但是它们之间有很多不同之处。本文将介绍TCP和UDP的基本概念&#xff0c;以及在Java中如何…

ubuntu20.04配置vscode

下载&#xff1a; https://az764295.vo.msecnd.net/stable/660393deaaa6d1996740ff4880f1bad43768c814/code_1.80.0-1688479026_amd64.debhttps://az764295.vo.msecnd.net/stable/660393deaaa6d1996740ff4880f1bad43768c814/code_1.80.0-1688479026_amd64.deb 安装&#xff1a…

Ubuntu 放弃了战斗向微软投降

导读这几天看到 Ubuntu 放弃 Unity 和 Mir 开发&#xff0c;转向 Gnome 作为默认桌面环境的新闻&#xff0c;作为一个Linux十几年的老兵和Linux桌面的开发者&#xff0c;内心颇感良多。Ubuntu 做为全世界Linux界的桌面先驱者和创新者&#xff0c;突然宣布放弃自己多年开发的Uni…

回首2023上半年:成长、思考、感恩

文章目录 每日一句正能量前言一、目标达成情况总结二、工作和学习成果总结三、下半年规划总结四、个人想法 后记附录 每日一句正能量 做一个向日葵族&#xff0c;面对阳光&#xff0c;不自艾自怜&#xff0c;每天活出最灿烂的自己。曾经拥有的&#xff0c;不要忘记。不能得到的…

day52

思维导图 比较指令结果的条件码 练习 汇编实现1-100的累加 .text .global _strat _start: mov r0,#0mov r1,#0 add_fun:add r0,r0,#1cmp r0,#100addls r1,r1,r0bls add_fun .end

Vue 项目路由、自定义指令、api方法自动引入资源(require.context使用)

前端项目&#xff08;当前我以Vue项目为例&#xff09;当我们把api挂载在main上后 // 将api挂载到vue的原型上 import api from /api Vue.prototype.$apiapi在src下会有一个api文件夹&#xff0c;结构如下&#xff1a; 通常情况下&#xff0c;api文件夹的index.js文件我们通常…

ChatGPT 最佳实践指南之:使用外部工具

Use external tools 使用外部工具 Compensate for the weaknesses of GPTs by feeding them the outputs of other tools. For example, a text retrieval system can tell GPTs about relevant documents. A code execution engine can help GPTs do math and run code. If a …

8.postgresql--Update join 和 Delete using

Update join Update join用于基于另一张表更新表数据&#xff0c;语法如下&#xff1a; UPDATE t1 SET t1.c1 new_value FROM t2 WHERE t1.c2 t2.c2;CREATE TABLE product_segment (id SERIAL PRIMARY KEY,segment VARCHAR NOT NULL,discount NUMERIC (4, 2) );INSERT INTO…

基于C/S架构工作原理序号工作步骤和理论的区别

基于C/S架构工作原理序号工作步骤和理论的区别 SSH 概念 对称加密linux 系统加密&#xff0c;就是加密和揭秘都是使用同一套密钥。 非对称加密有两个密钥&#xff1a;“私钥”和“公钥”。私钥加密后的密文&#xff0c;只能通过对应的公钥进行揭秘。而通过私钥推理出公钥的…

不满足于RPC,详解Dubbo的服务调用链路

系列文章目录 【收藏向】从用法到源码&#xff0c;一篇文章让你精通Dubbo的SPI机制 面试Dubbo &#xff0c;却问我和Springcloud有什么区别&#xff1f; 超简单&#xff0c;手把手教你搭建Dubbo工程&#xff08;内附源码&#xff09; Dubbo最核心功能——服务暴露的配置、使用…

数据可视化——用python绘制简单的折线图

文章目录 前言JSON使用 pyecharts 模块绘制折线图下载 pyecharts 模块使用 pyecharts 模块绘制简单的折线图添加配置选项 前言 前面我们已经学习了python的基础语法和面向对象&#xff0c;那么接下来我们将学习python编程语言的过人之处——数据的可视化之折线图。 JSON 说到…

C/C++内存泄漏原因分析与应对方法

内存泄漏 一、内存泄漏的危害&#xff1a; 内存泄漏会导致当前应用程序消耗更多的内存&#xff0c;使得其他应用程序可用的内存更少了。 如果有个进程可用的内存不够&#xff0c;就会触发Linux操作系统的直接/后台内存回收&#xff08;即将一些内存页的数据写到磁盘里&#…

springboot服务端接口公网远程调试,并实现HTTP服务监听

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

Argo CD 入门扫盲使用

目录 一、什么是 argo cd 二、为什么使用 argo cd 三、argo cd 架构图 四、Argo CD 使用 1、安装 Argo CD 2、安装 Argo CD CLI 3、发布 Argo CD 服务 4、获取 Argo CD 密码 5、准备 Git 仓库 6、创建 Argo CD App 7、版本升级 8、版本回滚 一、什么是 argo cd A…

数据结构(王道)——线性表的存储结构之循环表

一、循环单链表 定义&#xff1a; 循环单链表代码实现 创建并初始化、判断循环单链表是否为空、判断结点p是否为循环单链表的表尾结点的代码操作。 二、循环双链表 定义&#xff1a; 循环双链表代码实现 创建并初始化、判断循环双链表是否为空、判断结点p是否为循环双链表的…

JVM重点整理

一、虚拟机架构图 二、类加载过程 类加载器的作用&#xff1a;负责把class文件加载到内存中 类加载过程&#xff1a; 加载&#xff1a; 通过类的全限定名获取此类的二进制字节流文件的编码结构---->运行时的内存结构内存中生成一个class对象 链接&#xff1a; 验证&#x…

智能电表远程抄表系统原理

智能电表远程抄表系统是现代智能电网建设的重要组成部分&#xff0c;它利用物联网技术实现电表数据的远程采集、传输和处理&#xff0c;提高了电力公司的抄表效率&#xff0c;同时也为用户提供了更加便捷、准确的用电服务。本文将从远程智能电表抄表系统的工作原理、特点、应用…

每天一道C语言编程:排队买票

题目描述 有M个小孩到公园玩&#xff0c;门票是1元。其中N个小孩带的钱为1元&#xff0c;K个小孩带的钱为2元。售票员没有零钱&#xff0c;问这些小孩共有多少种排队方法&#xff0c;使得售票员总能找得开零钱。注意&#xff1a;两个拿一元零钱的小孩&#xff0c;他们的位置互…

精益生产有哪些管理工具?

精益生产有哪些管理工具&#xff1f; 一、什么是精益生产 智能制造是落实我国制造强国战略的重要举措&#xff0c;加快推进智能制造&#xff0c;是加速我国工业化和信息化深度融合、推动制造业供给侧结构性改革的重要着力点&#xff0c;对重塑我国制造业竞争新优势具有重要意义…

优化类问题建模解析

模型建立阶段 线性规划模型&#xff1a;目标函数和约束条件均为线性 整数规划或0-1规划&#xff1a;决策变量取值被限制为整数或0、1 动态优化模型&#xff1a;以时间为划分阶段的动态过程优化问题 非线性规划模型&#xff1a;目标函数或约束条件中包括非线性函数 多目标规划模…