当前位置:网站首页>Gateway服务网关
Gateway服务网关
2022-06-30 18:21:00 【RB_VER】
概念
spring cloud全家桶有个很重要的组件就是网关,在1.x版本中都是采用的Zuul网关,在2.x版本中,zuul的升级一直跳票,spring cloud最后自己研发了一个网关替代zuul,那就是spring cloud gateway。
spring cloud gateway是spring cloud的一个全新项目,基于spring 5.0+spring boot 2.0和project reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。
spring cloud gateway作为spring cloud生态系统中的网关,目标是替代zuul,在spring cloud 2.0以上版本中,没有对新版本的zuul 2.0以上最新高性能版本进行集成,仍然使用的zuul 1.x非reactor模式的老版本。而为了提升网关性能,spring cloud gateway是基于webflux框架实现的,而webflux框架底层则使用了高性能的reactor模式通信框架netty。
spring cloud gateway的目标提供统一的路由方式且基于filter链的方式提供了网关基本的功能,例如:安全、监控/指标、限流。
功能:反向代理、鉴权、流量控制、熔断、日志监控。

spring cloud gateway具有如下特性:
- 基于spring framework 5,project reactor和spring boot 2.0进行构建;
- 动态路由:能够匹配任何请求属性;
- 可以对路由指定predicate(断言)和filter(过滤器);
- 集成hystrix的断路器功能;
- 集成spring cloud服务发现功能;
- 易于编写的predicate和filter;
- 请求限流功能;
- 支持路径重写。
传统的web框架,比如说:struts2,springmvc等都是基于servlet API与servlet容器基础上运行的。但是,在servlet 3.x之后有了异步非阻塞的支持。而webflux是一个典型非阻塞异步的框架,它的核心是基于reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如netty、undertow及支持servlet 3.1的容器上。非阻塞式+函数式编程。
spring webflux是spring 5.0引入的新的响应式框架,区别于springmvc,它不需要依赖servlet API,它是完全异步非阻塞的,并且基于reactor来实现响应式流规范。
gateway核心概念
route(路由)
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由。
predicate(断言)
参考Java 8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。
filter(过滤)
指的是spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

web请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。predicate就是匹配的条件;filter可以理解为一个拦截器,有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。
搭建微服务网关
创建cloud-gateway-gateway9527模块
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud2022</artifactId>
<groupId>com.qrxqrx.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-gateway-gateway9527</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.qrxqrx.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_route # 路由的id,没有固定规则但是要求唯一,建议配合服务名
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言,路径匹配进行路由
- id: payment_route2 # 路由的id,没有固定规则但是要求唯一,建议配合服务名
uri: http://localhost:8001 # 匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** # 断言,路径匹配进行路由
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
GatewayMain9527
package com.qrxqrx.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class,args);
}
}
Gateway网关路由的两种配置方式
- 在yml文件中配置(如上)
- 代码中注入RouteLocator的bean
GatewayConfig
package com.qrxqrx.springcloud.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes().route("path_route_qrx1",
r -> r.path("/payment/get/**")
.uri("http://localhost:8001")).build();
}
}
配置动态路由
默认情况下,gateway会根据注册中心注册的微服务列表,以微服务名为路径创建动态路由进行转发,从而实现动态路由的功能。
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启动态路由
routes:
- id: payment_route # 路由的id,没有固定规则但是要求唯一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的路由地址
uri: lb://cloud-payment-service # 动态路由
predicates:
- Path=/payment/get/** # 断言,路径匹配进行路由
- id: payment_route2 # 路由的id,没有固定规则但是要求唯一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的路由地址
uri: lb://cloud-payment-service # 动态路由
predicates:
- Path=/payment/lb/** # 断言,路径匹配进行路由
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
Predicate的使用

spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启动态路由
routes:
- id: payment_route # 路由的id,没有固定规则但是要求唯一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的路由地址
uri: lb://cloud-payment-service # 动态路由
predicates:
- Path=/payment/get/** # 断言,路径匹配进行路由
# ZonedDateTime zbj = ZonedDateTime.now();
# System.out.println(zbj);
- After=2022-06-30T16:17:33.876+08:00[Asia/Shanghai] # 在此时间之后访问才有效果
- Cookie=name,qrx
# Cookie Route Predicate需要两个参数,一个是cookie name,一个是正则表达式。
# 路由规则会通过获取对应的cookie name值和正则表达式去匹配,如果匹配上就会执行路由,如果没有匹配上则不执行。
# 测试:curl http://localhost:9527/payment/lb --cookie "username=zzyy"
- Header=X-Request-Id,\d+
# 两个参数:一个属性名称和一个正则表达式,属性值匹配则执行
# 测试:curl http://localhost:9527/payment/lb --H "X-Request-Id:123"
- Host=www.qrxqrx.com
# 测试:curl http://localhost:9527/payment/lb --H "Host:www.qrxqrx.com"
- Method=GET
- Query=username,qrx
# 测试:curl http://localhost:9527/payment/lb?username=qrx
Filter的使用
路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能指定路由进行使用。
按生命周期分:
- pre
- post
按种类分: - GatewayFilter
- GlobalFilter
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 开启动态路由
routes:
- id: payment_route # 路由的id,没有固定规则但是要求唯一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的路由地址
uri: lb://cloud-payment-service # 动态路由
predicates:
- Path=/payment/get/** # 断言,路径匹配进行路由
- id: payment_route2 # 路由的id,没有固定规则但是要求唯一,建议配合服务名
# uri: http://localhost:8001 # 匹配后提供服务的路由地址
uri: lb://cloud-payment-service # 动态路由
predicates:
- Path=/payment/lb/** # 断言,路径匹配进行路由
filters:
- AddRequestParameter=X-Request-Id,1024 # 过滤器工厂会在匹配的请求头加上一对请求头,名称为X-Request-Id,值为1024
自定义过滤器
package com.qrxqrx.springcloud.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.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Date;
@Component
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("----come in MyLogGatewayFilter----"+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
if (uname == null) {
log.info("++++username is null! illegal!");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
测试:http://localhost:9527/payment/lb?uname=xxx
边栏推荐
- Courage to be hated: Adler's philosophy class: the father of self inspiration
- js 字符串截取方法汇总
- 20220607跌破建议零售价,GPU市场正全面走向供过于求...
- Kubernetes----Pod配置容器启动命令
- Ansi/ul 94 class 5-V vertical combustion test
- 如何利用 xUnit 框架对测试用例进行维护?
- Brief introduction of Feature Engineering in machine learning
- Pyth-Solana链上联通现实的桥梁
- 「经验」爬虫在工作中的实战应用『理论篇』
- MySQL function to get the full path
猜你喜欢

美国服务器租用和托管服务哪个好?
![Delete duplicate elements in the sorting linked list ii[unified operation of linked list nodes --dummyhead]](/img/dd/7df8f11333125290b4b30183cfff64.png)
Delete duplicate elements in the sorting linked list ii[unified operation of linked list nodes --dummyhead]

PC wechat multi open

拓维信息使用 Rainbond 的云原生落地实践

商业智能BI与业务管理决策思维之四:业务成本分析

Browser window switch activation event visibilitychange

BeanUtils.copyProperties() 对比 mapstruct

传统微服务框架如何无缝过渡到服务网格 ASM

How to use the low code platform of the Internet of things for service management?

Entropy - conditional entropy - joint entropy - mutual information - cross entropy
随机推荐
联想YOGA 27 2022,超强配置全面升级
Video content production and consumption innovation
传统微服务框架如何无缝过渡到服务网格 ASM
DTD modeling
Practical application of "experience" crawler in work "theory"
Word——Word在试图打开文件时遇到错误的一种解决办法
nats集群部署
Introduction to Po mode "suggestions collection"
Pyth-Solana链上联通现实的桥梁
Construction and practice of full stack code test coverage and use case discovery system
基于 actix、async-graphql、rbatis、pgsql/mysql 构建 GraphQL 服务(4)-变更服务
【DesignMode】单例模式(singleton pattern)
拓維信息使用 Rainbond 的雲原生落地實踐
openGauss数据库源码解析系列文章—— 密态等值查询技术详解(上)
Evolution of screen display technology
嵌入式软件开发新趋势:DevOps
基于UDP协议设计的大文件传输软件
How to use xUnit framework to maintain test cases?
MySQL download and installation tutorial
How to open a futures account safely? Which futures companies are more reliable now?