Gateway新一代网关
1、概述简介
-
官网
-
技术选型
1、Zuul1.x模型
2、我们为什么选择Gateway?
-
1.netflix不太靠谱,zuul2.0一直跳票,迟迟不发布
-
SpringCloud Gateway具有如下特性
- 基于Spring Framework 5, Project Reactor和Spring Boot 2.0进行构建;
- 动态路由:能够匹配任何请求属性;
- 可以对路由指定Predicate (断言)和Filter (过滤器) ;
- 集成Hystrix的断路器功能;
- 集成Spring Cloud服务发现功能;
- 易于编写的Predicate (断言)和Filter (过滤器) ;
- 请求限流功能;
- 支持路径重写。
-
SpringCloud Gateway与Zuul的区别
-
Gateway模型
1、WebFlux是什么
-
什么是Gateway网关?
1、Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和Project Reactor等技术。
2、Gateway旨在提供一种简单而有效的方式来对API进行路由,提供一些强大的过滤器功能,例如:熔断、限流、重试等
3、SpringCloud Gateway是Spring Cloud的一个全新项目,纡Spring 5.0+ Spring Boot 2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一 的API路由管理方式。
4、SpringCloud Gateway作为Spring Cloud生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty
5、SpringCloud Gateway的目标提供统一的路由方式且基 于Filter链的方式提供了网关基本的功能,例如:安全,监控/指标, 和限流。
-
官网源码设置
- 概括
SpringCloud Gateway使用的是Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架
-
作用
1、反向代理
2、鉴权
3、流量控制
4、熔断
5、日志监控
6、…
-
微服务架构中网关在哪里
2、三大核心概念
-
Route(路由)
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如断言为true则匹配该路由
-
Predicate(断言)
参考的是Java8的java.util.function.Predicate
开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由 -
Filter(过滤)
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改.
3、Gateway工作流程
- 官网总结
-
核心逻辑
路由转发+执行过滤器链
4、入门配置
-
新建Module
cloud-gateway-gateway9527
-
POM
<dependencies> <!--gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--eureka client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--引入自定义的api通用包,可使用Payment支付Entity--> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-common</artifactId> <version>${project.version}</version> </dependency> <!--一般基础配置类--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </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>
注意去点配置的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
-
YML
server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: routes: - id: payment_routh #payment_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/get/** #断言,路径相匹配的进行路由 - id: payment_routh2 #payment_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** #断言,路径相匹配的进行路由 eureka: instance: hostname: cloud-gateway-service client: fetch-registry: true register-with-eureka: true service-url: #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址 # defaultZone: http://eureka7002.com:7002/eureka/ # 单机版eureka defaultZone: http://eureka7001.com:7001/eureka/
-
主启动类
@SpringBootApplication @EnableEurekaClient public class GatewayMain9527 { public static void main(String[] args) { SpringApplication.run(GatewayMain9527.class,args); } }
-
9527网关如何做路由映射呢???
1、cloud-provider-payment8001看看controller的访问地址
http://localhost:8001/payment/get/31
http://localhost:8001/payment/lb
2、我们目前不想暴露8001端口,希望在8001外面套一层9527
-
配置yaml网关
如上图yml配置所示;
-
测试
1、启动7001
2、启动8001 cloud-provider-payment8001
3、启动9527
访问说明
添加网关前
http://localhost:8001/payment/get/31
添加网关后
http://localhost:9527/payment/get/31
-
Gateway网关路由有两种配置方式:
1、如上图yml配置文件
2、代码中注入RouteLocator的Bean
-
官网案例
-
个人案例
-
通过9527网关访问到外网的百度新闻网址
-
编码cloud-gateway-gateway9527
-
增加配置类
@Configuration public class GateWayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) { RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes(); routes.route("path_route_atguigu", r -> r.path("/guoji") .uri("https://news.baidu.com/guoji")) .route("path_route_atguigu1", r -> r.path("/guonei") .uri("https://news.baidu.com/guonei")).build(); return routes.build(); } }
- 测试
-
-
5、通过服务名实现动态
默认情况下Gatway会根据注册中心注册的服务列表, 以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能
-
启动:
一个eureka7001+两个服务提供者8001/8002
-
POM
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
-
yml
需要注意的是uri的协议lb,表示启用Gateway的负载均衡功能.
lb://serverName是spring cloud gatway在微服务中自动为我们创建的负载均衡uri
-
测试
http://localhost:9527/payment/lb
6、Predicate
- 是什么
- 常用的Route Predicate
1.After Route Predicate
2.Before Route Predicate
3.Between Route Predicate
public class zoneTime {
public static void main(String[] args) {
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
}
}
4.Cookie Route Predicate
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
- After=2020-04-15T18:23:00.156+08:00[Asia/Shanghai]
- Cookie=username,clq
测试
5.Header Route Predicate
- Header=X-Request-Id, \d+
#请求头需要有X-Request-Id属性名,值为整数正则表达式
- id: payment_routh2 #payment_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名
uri: lb://cloud-provider-service
# uri: http://localhost:8001 #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
# - After=2020-04-15T18:23:00.156+08:00[Asia/Shanghai]
# - Cookie=username,clq
- Header=X-Request-Id, \d+
6.Host Route Predicate
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
# - After=2020-04-15T18:23:00.156+08:00[Asia/Shanghai]
# - Cookie=username,clq
# - Header=X-Request-Id, \d+
- Host=**.atguigu.com
7.Method Route Predicate
- id: payment_routh2 #payment_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名
uri: lb://cloud-provider-service
# uri: http://localhost:8001 #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
# - After=2020-04-15T18:23:00.156+08:00[Asia/Shanghai]
# - Cookie=username,clq
# - Header=X-Request-Id, \d+
- Host=**.atguigu.com
- Method=GET
8.Path Route Predicate
9.Query Route Predicate
- Host=**.atguigu.com
- Method=GET
- Query=username
10.RemoteAddr Route Predicat
11.Weight Route Predicate
小总结
Predicate就是为了实现一组匹配规则, 让请求过来找到对应的Route进行处理
7、Filter的使用
- 是什么
-
Spring Cloud Gateway的filter
1、生命周期,Only Two
pre ,post
2、种类,Only Two
-
GatewayFilter
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#gatewayfilter-factories
-
GlobalFilter
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/#global-filters
-
-
常用的GatewayFilter
AddRequestParameter
- id: payment_routh2 #payment_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名 uri: lb://cloud-provider-service # uri: http://localhost:8001 #匹配后提供服务的路由地址 -filters: - AddRequestParameter=X-Request-Id,1024 predicates: - Path=/payment/lb/** #断言,路径相匹配的进行路由 # - After=2020-04-15T18:23:00.156+08:00[Asia/Shanghai] # - Cookie=username,clq # - Header=X-Request-Id, \d+ # - Host=**.atguigu.com - Method=GET,POST - Query=username
-
自定义过滤器
自定义全局GlobalFilter
1、两个主要接口介绍
implments GlobalFilter,OrderId
2、作用
-
全局日志记录
-
统一网关鉴权
3、案例代码
-
代码
@Component @Slf4j @Order(0) public class MyLogGateWayFilter implements GlobalFilter{ @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("%%%%%%%%%%%%%%%%用户名为null,非法用户"); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } }
-
测试
启动
-
正确
http://localhost:9527/payment/lb?uname=z3
错误
地址无法访问