之前我们介绍了 zuul 网关服务,今天聊聊 spring cloud gateway 作为 spring cloud 的亲儿子网关服务。很多的想法都是参照 zuul,为了考虑 zuul 迁移到 gateway 提供了一个便利的条件。
gateway 他的核心功能也是和 zuul 类似。但是他的实现方式与 zuul 却有些不一样,他的核心是基于 Spring Boot 2.x,Spring WebFlux 和 Project Reactor 构建的。
-
Spring WebFlux 响应式 Web 框架。
- Spring WebFlux 是基于响应式流的,因此可以用来建立异步的、非阻塞的、事件驱动的服务。它采用 Reactor 作为首选的响应式流的实现库,不过也提供了对 RxJava 的支持。
由于响应式编程的特性,Spring WebFlux 和 Reactor 底层需要支持异步的运行环境,比如 Netty 和 Undertow;也可以运行在支持异步 I / O 的
- Servlet 3.1 的容器之上,比如 Tomcat(8.0.23 及以上)和 Jetty(9.0.4 及以上)。
-
spring-webflux 上层支持两种开发模式:
- 类似于 Spring WebMVC 的基于注解(@Controller、@RequestMapping)的开发模式;
- Java 8 lambda 风格的函数式开发模式。
- Spring WebFlux 也支持响应式的 Websocket 服务端开发。
所以 spring cloud gateway 不是基于阻塞的 web 开发。他与传统的 Servlet 是存在冲突的。在创建功能的时候要排除掉传统的 Servlet jar 包引用
工作原理
客户端向 Spring Cloud Gateway 发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关 Web 处理程序。该处理程序运行通过特定于请求的筛选器链发送请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前或之后执行逻辑。执行所有“前置”过滤器逻辑,然后发出代理请求。发出代理请求后,将执行“发布”过滤器逻辑。
注意: 在没有端口的路由中定义的 URI 将分别将 HTTP 和 HTTPS URI 的默认端口分别设置为 80 和 443
- Predicate 断言:这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
- Route 路由转发 它由一个 serverID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
- Filter 请求过滤 对 web 资源进行拦截,做一些处理后再交给处理器处理
修改之前工程的 pom 文件总 pom 里面我们有一个 spring-boot-starter-web 工程引用,删除掉。在服务里面单独依赖。上面已经讲述过,传统 Servlet 的 jar 包冲突问题。
在服务消费者和 服务提供者分别添加
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
我们创建工程 cloud-gateway , 修改 pom
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
创建 bootstrap.yml
server:
port: 9000
spring:
profiles:
active: dev
application:
name: cloud-gateway-demo
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null
cloud:
nacos:
discovery:
server-addr: 47.99.209.72:8848
# ${prefix}-${spring.profile.active}.${file-extension}
config:
server-addr: 47.99.209.72:8848
file-extension: yaml
gateway:
discovery:
locator:
# 是否与服务发现组件进行结合,通过 serviceId 转发到具体的服务实例。默认 false,# 为 true 代表开启基于服务发现的路由规则。enabled: true
# 配置之后访问时无需大写
lower-case-service-id: true
routes:
- id: cloud-discovery-server
uri: lb://cloud-discovery-server
predicates:
# 路径匹配,以 api 开头,直接配置是不生效的,看 filters 配置
- Path=/server/**
filters:
# 前缀过滤,默认配置下,我们的请求路径是 http://localhost:9000/myshop-service-consumer-item/** 这时会路由到指定的服务
# 此处配置去掉 1 个路径前缀,再配置上面的 Path=/api/**,就能按照 http://localhost:9000/api/** 的方式访问了
- StripPrefix=1
- id: cloud-discovery-client
uri: lb://cloud-discovery-client
predicates:
# 路径匹配,以 api 开头,直接配置是不生效的,看 filters 配置
- Path=/client/**
filters:
# 前缀过滤,默认配置下,我们的请求路径是 http://localhost:9000/myshop-service-consumer-item/** 这时会路由到指定的服务
# 此处配置去掉 1 个路径前缀,再配置上面的 Path=/api/**,就能按照 http://localhost:9000/api/** 的方式访问了
- StripPrefix=1
创建 main 启动类
package com.xian.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
*
* @Author: xlr
* @Date: Created in 上午 11:08 2019/11/4
*/
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayServerApplication {public static void main(String[] args) {SpringApplication.run(GatewayServerApplication.class, args);
}
}
启动服务 命令行 curl http://localhost:9000/client/client/test
服务已经整合完毕。路由功能转发已经实现。配置文件的一些字段的说明也在注释上说明。
下一篇讲述一下 Spring Cloud Gateway 断言
如何喜欢可以关注分享本公众号。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。转载请附带公众号二维码