网关可提供请求路由与组合协议转换安全认证服务鉴权流量控制日志监控等服务。可选的网关有不少,比如 Nginx、高性能网关 OpenResty、Linkerd 以及 Spring Cloud Gateway。

如果是真的追求高性能,那肯定是选择 Nginx 或者 OpenResty 无疑了, 但是对性能要求不是很高的话,并且又在用 Spring Cloud 系列,那当然就要选择 Spring Cloud Gateway 了。

网关的基础就是路由功能,通俗解释就是地址转发,将一个请求地址转发到实际的服务地址。比如请求的是 http://xxx.com/api 的路由地址,实际上会被转发到 http://xxx.com:8888 上来,这就是个最简单的路由方式。

我们可以理解为 Spring Cloud Gateway 就是针对进来的请求做各种判断和处理,比如说判断请求的合法性、权限验证,请求地址改写,请求参数、头信息、cookie 信息的分析和改写,请求速率控制,日志留存等。而这些都可以方便的通过 Predicate 和 GatewayFilter 来组合实现。

创建 Spring Cloud Gateway 项目

Spring Cloud 版本是 Greenwich.SR2,Spring Boot 版本 2.1.6.RELEASE,JDK 1.8。

接下来正式创建一个 Gateway 项目。

首先做两个微服务,当做路由转发的目标服务

两个微服务是以 consul 作为服务注册中心的,可以看这篇文章服务注册发现、配置中心集一体的 Spring Cloud Consul

1、创建 consul-order 服务,具体可以去 github 上看代码(https://github.com/huzhicheng/spring-cloud-study/tree/master/consul/consul-order),很简单的一个服务。创建的 RESTful Controller 如下:

@RestController
@RequestMapping(value = "order")
public class OrderController { @Value("${spring.application.name}")
private String applicationName; @GetMapping(value = "get")
public CustomerOrder getOrder(){
CustomerOrder customerOrder = new CustomerOrder();
customerOrder.setOrderId("9999");
customerOrder.setProductName("MacBook Pro");
customerOrder.setClient(applicationName);
return customerOrder;
}
}

总之,最后直接访问这个接口的地址为 http://localhost:5006/order/get

2、创建 consul-user 服务,具体代码可以到 github 上查看(https://github.com/huzhicheng/spring-cloud-study/tree/master/consul/consul-user)。创建的 RESTful Controller 内容如下:

@RestController
@RequestMapping(value = "user")
public class UserController { @GetMapping(value = "get")
public User getUserInfo(){
User user = new User();
user.setName("古时的风筝");
user.setAge(8);
user.setLocation("北京");
return user;
}
}

和上面的微服务有点区别的就是设置了 context-path

server:
port: 5005
servlet:
context-path: /user-service

之所以这样不同的设置,是因为下面要验证一个 filter。总之,最后上述接口的访问地址为:http://localhost:5005/user-service/user/get

创建一个项目,并引入 maven 包

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

配置简单的路由转发

路由配置有两种方式。一种是配置文件,另外一种是代码方式配置,WebFlux 的反应式编程方式。所以我们 pom 文件中要引入 WebFlux 的包。这是 Spring 5 的新特性。

1、先看第一种配置文件方式配置:

server:
port: 10000
spring:
application:
name: gateway
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: false # 是否将服务id转换为小写
routes:
- id: userServiceRouter
uri: lb://consul-user
predicates:
- Path=/user-service/**
- id: orderServiceRouter
uri: lb://consul-order
predicates:
- Path=/order-service/**
filters:
- StripPrefix=1
consul:
host: localhost #注册gateway网关到consul
port: 8500
discovery:
service-name: service-gateway

其中包括 Spring Boot 项目的基本配置,name、port ,还有关于 consul 的配置,要将网关服务注册到注册中心。

上面配置中创建了两条路由规则,路由规则名称通过 id 设置,分别是 userServiceRouter 和 orderServiceRouter,通过 predicates.Path 设置待转发的 url,通过 uri 设置转发后的目标地址。上面配置将以 /user-service/开头的地址转发到 lb://consul-user ,固定格式 lb + 服务id,在有注册中心的情况下要这样写,如过没有注册中心,可以直接写目标 url。

下面的路由规则中多了一个 StripPrefix 的 filter ,这个是 Gateway 的内置 filter,作用就是去掉 Path 中的指定部分,StripPrefix=1,就是以 / 分隔,去掉第一部分,比如 /a/b/c 这个地址,在 StripPrefix=1 的作用下,就会转发到 /b/c/,当 StripPrefix=2 的时候,就会转发到 /c/。

配置好上述接口,然后启动网关服务。访问规则就会有如下对应关系:

http://localhost:10000/user-service/user/get->http://localhost:5005/user-service/user/get

http://localhost:10000/order-service/order/get->http://localhost:5006/order/get

当然这只是针对每一个目标服务只有一个实例的情况,如果有多个实例,就会按照负载策略落到对应的实例中。

2、代码方式的路由配置

@Bean
public RouteLocator kiteRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("userRouter", r -> r.path("/user-service/**")
.filters(f ->
f.addResponseHeader("X-CustomerHeader", "kite"))
.uri("lb://consul-user")
)
.route("orderRouter", r -> r.path("/order-service/**")
.filters(f -> f.stripPrefix(1)).uri("lb://consul-order")
)
.build();
}

上面的这段代码和前面的配置文件的内容是同样的作用。只要实现一个返回类型为 RouteLocator,参数为 RouteLocatorBuilder类型的 Bean。

你看后面那一连串的 r.path().filters().uri() 了吗,用它们就可以简单的配置出路由规则,而且可读性也比较强。另外,Gateway 还套用了 Predicate 的规则来构建更加灵活、复杂的路由规则。Predicate 是 Java 8 增加的逻辑计算库,有 negate()、and()、or()、isEqual()几个方法。具体的代码在 PredicateSpec 和 UriSpec 这两个类里,一目了然。

PredicateSpec 里有这么多方法,都可以结合 and、or 组合起来使用。

接下来就说到 filter,Gateway 内置了很多的 filter,可以在 GatewayFilterSpec 类下找到方法封装,每一个 filter 都由一个 factory 的 apply 实现,都在 org.springframework.cloud.gateway.filter.factory包下,有必要的话可以直接看源码。 比如上面用到的 StripPrefix。还有 addResponseHeader,它的作用是在 Response 对象的 header 中添加请求头。

启动网关服务

启动网关,并访问两个接口测试,接口分别为 http://localhost:10000/user-service/user/get和http://localhost:10000/order-service/order/get,正常返回数据,则说明网关服务配置正常。

巧用 StripPrefix filter

微服务多了之后,路由的转发规则也就多了,比方说订单相关请求要转发到订单微服务集群,用户相关请求要转发到用户微服务集群,最终开放给终端的接口也要能表明是哪个微服务的,除了接口文档里说明之外,接口本身最好也能明确标识。

一种方式是在微服务的配置文件中配置上server.servlet.context-path

还有一种方式就是在路由规则的 path 中配置,然后加上 StripPrefix 配置,选择性的去掉请求 url 中的某些部分。比如我们请求 Gateway的地址为 order-service/order/get,则经过 StripPrefix(1) 之后,会把请求地址变为 order/get,然后根据路由规则定向到具体的微服务地址或者特定的 url。

本篇就介绍 Spring Cloud Gateway 的基本用法,后续还会有关于集成安全认证、鉴权、限流、日志等相关内容,敬请关注。

不要吝惜你的「推荐」呦

欢迎关注,不定期更新本系列和其他文章

古时的风筝 ,进入公众号可以加入交流群

网关我选 Spring Cloud Gateway的更多相关文章

  1. Spring Cloud Gateway服务网关

    原文:https://www.cnblogs.com/ityouknow/p/10141740.html Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gatewa ...

  2. 网关服务Spring Cloud Gateway(一)

    Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ...

  3. 微服务网关 Spring Cloud Gateway

    1.  为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...

  4. Spring Cloud gateway 网关四 动态路由

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

  5. spring cloud:服务网关 Spring Cloud GateWay 入门

    Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ...

  6. Spring Cloud Gateway 整合阿里 Sentinel网关限流实战!

    大家好,我是不才陈某~ 这是<Spring Cloud 进阶>第八篇文章,往期文章如下: 五十五张图告诉你微服务的灵魂摆渡者Nacos究竟有多强? openFeign夺命连环9问,这谁受得 ...

  7. Spring Cloud Gateway VS Zuul 比较,怎么选择?

    Spring Cloud Gateway 是 Spring Cloud Finchley 版推出来的新组件,用来代替服务网关:Zuul. 那 Spring Cloud Gateway 和 Zuul 都 ...

  8. SpringCloud无废话入门05:Spring Cloud Gateway路由、filter、熔断

    1.什么是路由网关 截至目前为止的例子中,我们创建了一个service,叫做:HelloService,然后我们把它部署到了两台服务器(即提供了两个provider),然后我们又使用ribbon将其做 ...

  9. Spring Cloud gateway 五 Sentinel整合

    微服务当前这么火爆的程度,如果不能学会一种微服务框架技术.怎么能升职加薪,增加简历的筹码?spring cloud 和 Dubbo 需要单独学习.说没有时间?没有精力?要学俩个框架?而Spring C ...

随机推荐

  1. cogs 2652. 秘术「天文密葬法」(0/1分数规划 长链剖分 二分答案 dp

    http://cogs.pro:8080/cogs/problem/problem.php?pid=vSXNiVegV 题意:给个树,第i个点有两个权值ai和bi,现在求一条长度为m的路径,使得Σai ...

  2. gulp的介绍和手动安装

    gulp, 前端自动化工具, 文件操作, 项目上线之前,将碎片文件合并,将ES6转成ES5,文件压缩,快速搭建服务器... gulp基于node环境 gulp就是node的一个非内置的小模块 gulp ...

  3. XSS漏洞之加载远程js文件

    这次在对一个系统渗透测试过程中,发现一个XSS漏洞,可弹窗,并且没有httponly 但是在尝试加载远程js文件的时候发现,script标签被过滤掉了,准确的说应该是服务器后端在识别到输入内容有< ...

  4. 013 turtle程序语法元素分析

    目录 一.概述 二.库引用与import 2.1 库引用 2.2 使用from和import保留字共同完成库引用 2.3 两种库引用方法比较 2.4 使用import和as保留字共同完成库引用 三.t ...

  5. 每天学会一点点(枚举enum)

    枚举的特点: enum和class.interface的地位一样 使用enum定义的枚举类默认继承了java.lang.Enum,而不是继承Object类.枚举类可以实现一个或多个接口. 枚举类的所有 ...

  6. FreeSql (三十二)Aop

    FreeSql AOP 已有的功能介绍,未来为会根据用户需求不断增强. 审计 CRUD 马云说过,996是修福报.对于多数程序员来说,加班是好事...起码不是闲人,不会下岗. 当如果因为某个 sql ...

  7. 《Java 8 in Action》Chapter 10:用Optional取代null

    1965年,英国一位名为Tony Hoare的计算机科学家在设计ALGOL W语言时提出了null引用的想法.ALGOL W是第一批在堆上分配记录的类型语言之一.Hoare选择null引用这种方式,& ...

  8. Python文件访问编码格式问题UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position xx: 解决方案

    1.Python读取文件 # .打开文件 file = open("ReadMe") # .读取文件类容 text = file.read() print(text) # .关闭文 ...

  9. Kali Linux 安装open-vm-tools

    Kali Linux是基于Debian的Linux发行版,集成了精心挑选的渗透测试和安全审计的工具,供渗透测试和安全设计人员使用.(以及一些各种颜色的hacker  ^-^) 首先需要安装好虚拟机(V ...

  10. jmeter运行第三方java项目

    自己写了个简化系统操作的小工具,因为不想给别人用的时候占用本地资源于是写的是纯java项目,后面放到jmeter中通过beanshell sampler调用. java源码不贴了,把写好的项目导出成可 ...