网关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-orderuri: http://localhost:9001predicates:- 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: ---loadbalancedpredicates: # 断言 如果断言满足要求,则转发到uri指定的真实地址.- Path=/product/** # 如果客户的请求路径以product开头,则满足该断言要求,则转发的uri真实地址。- id: shop-orderuri: lb://shop-orderpredicates:- 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);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("minAge", "maxAge");}@Overridepublic 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;};}@Validatedpublic static class Config {@NotNullprivate int minAge;@NotNullprivate 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 为原始请求添加Header Header的名称及值
AddRequestParameter 为原始请求添加请求参数 参数名称及值
AddResponseHeader 为原始响应添加Header Header的名称及值
DedupeResponseHeader 剔除响应头中重复的值 需要去重的Header名称及去重策略
Hystrix 为路由引入Hystrix的断路器保护HystrixCommand的名称
FallbackHeaders 为fallbackUri的请求头中添加具体的异常信息 Header的名称
PrefixPath 为原始请求路径添加前缀 前缀路径
PreserveHostHeader 为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host
RequestRateLimiter 用于对请求限流,限流算法为令牌桶 keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus
RedirectTo 将原始请求重定向到指定的URL http状态码及重定向的url
RemoveHopByHopHeadersFilter 为原始请求删除IETF组织规定的一系列Header 默认就会启用,可以通过配置指定仅删除哪些Header
RemoveRequestHeader 为原始请求删除某个Header Header名称
RemoveResponseHeader 为原始响应删除某个Header Header名称
RewritePath 重写原始的请求路径 原始路径正则表达式以及重写后路径的正则表达式
RewriteResponseHeader 重写原始响应中的某个Header Header名称,值的正则表达式,重写后的值
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 {@Overridepublic 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));}//优先级 值越小优先级越高@Overridepublic 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 {@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);}
}

【SpringCloud】04 网关springcloud gateway相关推荐

  1. springcloud五大神兽之Gateway

    ① 什么是网关? API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层. 网关的出现原因是伴随微服务架构的出现而出现,因为不同的微服务一般有不同的网络地址(ip ...

  2. 跟着狂神学SpringCloud(Rest环境搭建+Eureka服务注册与发现+ribbon+Feign负载均衡+Hystrix+服务熔断+Zuul路由网关+SpringCloud config分布)

    跟着狂神学SpringCloud SpringCloud 回顾之前的知识- JavaSE 数据库 前端 Servlet Http Mybatis Spring SpringMVC SpringBoot ...

  3. gateway网关_SpringCloud技术指南系列(十二)API网关之Gateway使用

    SpringCloud技术指南系列(十二)API网关之Gateway使用 一.概述 API网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架 ...

  4. Centos/Linux下如何查看网关地址/Gateway地址

    Centos/Linux下如何查看网关地址/Gateway地址? Linux下查看网关的命令还是很多的,不过如果IP是DHCP获取,那么有些命令是不适用的,当然也有通用的查询网关命令. 1.ifcon ...

  5. 包容网关 Inclusive Gateway

    包容网关 Inclusive Gateway 什么是包容网关? 包容网关(Inclusive Gateway)就是并行网关(Parallel Gateway)和排他网关(Exclusive Gatew ...

  6. 带你入门SpringCloud统一配置 | SpringCloud Config

    前言 在微服务中众多服务的配置必然会出现相同的配置,如果配置发生变化需要修改,一个个去修改然后重启项目的方案是绝对不可取的.而 SpringCloud Config 就是一个可以帮助你实现统一配置选择 ...

  7. 带你入门SpringCloud 之 通过SpringCloud Bus 自动更新配置

    前言 在<带你入门SpringCloud统一配置 | SpringCloud Config>中通过 SpringCloud Config 完成了统一配置基础环境搭建,但是并没有实现配置修改 ...

  8. 微服务升级_SpringCloud Alibaba工作笔记0001---新一代网关spring gateway和zuul的关系说明

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 zuul内部发生了大的分歧,所以逐步不再支持,现在统一使用新一代网关gateway zuul已经不 ...

  9. 中转网关 (Transit Gateway) Connect连接类型集成FortiGate安全服务

    中转网关(Transit Gateway)Connect 功能介绍 SD-WAN或软件定义的广域网长期以来一直用于通过公共Internet连接数据中心和分支机构.在现在的网络设计中,这些网络还需要扩展 ...

最新文章

  1. UVA10020(最小区间覆盖)
  2. 【错误记录】Android Studio 的 Flutter 代码界面没有 Logcat 面板 ( 2021年08月28日最新解决方案 )
  3. datatables屏蔽警告弹窗
  4. 期末复习、化学反应工程科目(第六、七章)
  5. 技术脱钩后软硬件磨合优化不失为一条出路
  6. 一次堆外内存泄露的排查过程
  7. WDLINUX (Centos5.8) 安装 bcmath
  8. 论文降重,你都用了什么奇特的方法?
  9. c语言注释部分两侧的分界符号分别是,单片机C语言练习题
  10. C++ API中文文档分享
  11. 人脸识别技术及其各种用例
  12. 用eclipse和androidstudio和基于高德地图API开发的附近购平台的java服务端和android客户端数据库用mysql包括程序设计图
  13. android2.2 模拟器,网易MuMu模拟器2.2.29官方版
  14. linux内核5.8.1,Linus Torvalds宣布大规模更新Linux内核5.8
  15. SOIC8E (EXPOSED PAD)
  16. 古剑飞仙手游Linux系统服务器架设教程
  17. jquery实现数字抽奖(版本2)
  18. 函数:GetDistance,计算两个经度纬度之间距离
  19. Winodows subsystem for Linux(WSL)的安装及GUI图形界面启用
  20. 【Excel / WPS表格】如何按列进行合并单元格?或者说按行进行合并单元格?

热门文章

  1. 自动扫雷c语言,ctypes
  2. S7-200Smart 软件下载地址,仿真下载地址
  3. 斯坦福兔子和其他图形学模型数据下载
  4. 80386为32位机
  5. C语言多线程运行时间计算
  6. 基于FFmpeg的视频播放器之一:开篇
  7. java 调用c效率高_java通过JNI调用C语言写的函数,能提高运行效率吗?
  8. AD 限定登录计算机,限制AD账户可以登录哪些计算机
  9. 从Npm Script到Webpack,6种常见的前端构建工具对比
  10. 机器人焊枪动作与编程实验_机器人实验指导用书.doc