微服务网关简介
Introduce
当我们实现了各种微服务后,我们的各种微服务又要如何提供给外部应用调用呢??
当然,因为是Rest API 接口 ,外部客户端直接调用微服务是没有问题的。但是出于种种原因,这并不是一个很好的选择。让客户端直接与各个微服务进行通讯,会存在以下问题。
- 客户端会多次请求不同的微服务,增加了客户端的复杂性
- 存在跨域请求,在一定场景下处理会变得相对比较复杂
- 实现认证复杂,每个微服务都需要独立认证
- 难以重构,项目迭代,可能导致微服务重新划分,如果客户端直接与微服务通讯,那么重构将会很难实施
- 如果某些微服务使用了防火墙、浏览器不友好的协议,直接访问会有一定的困难
对于上述的问题我们应该如何解决?通过服务网关即可解决。在微服务系统中 微服务资源一般不直接暴露给外部客户端访问,这样的好处是将内部的服务隐藏起来,从而解决上述问题。网关有很多重要的意义,具体体现在下面几个方面:
- 网关可以做一些身份认证、权限管理、防止非法请求操作权限等,对服务起一定保护作用
- 网关将所有的微服务统一管理,对外统一暴露,外界系统不需要知道微服务架构相互调用的复杂性,同时也避免了内部服务一些敏感信息的泄露问题。
- 易于监控,可在微服务网关收集监控数据并将其推送到外部系统进行分析
- 客户端只跟服务网关打交道,减少了客户端与各个微服务之间的交互次数
- 多渠道支持,可以根据不同客户端(WEB端、移动端、桌面端、。。)提供不同的API网关
- 网关可以用来做流量监控。在高并发下,对服务进行限流、降级
- 网关把服务从内部分离出来,方便测试
微服务网关能够实现,路由、负载均衡等多种功能。类似Nginx、反向代理的功能。在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的URL,路由到相应的服务,当添加API网关后,在第三方调用端和服务提供之间创建了一面墙,在API网关中进行权限控制,同时API网关以负载均衡的方式发送给后端服务。微服务网关架构:
一、SpringCloud Gateway 简介
springCloud 是spring Cloud 的一个全新的项目,该项目是基于Spring 5.0,spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在 为微服务架构提供一种简单有效的统一的API管理方式
SpringCloud Gateway 作为Spring Cloud 生态系统中的网关,目标是代替Zuul,在Spring Cloud 2.0 以上版本中,没有对新版本的Zuul 2.0最新高性能版本进行集成,仍然还是使用Zuul 2.0之前的Reactor 模式的老版本,而为了提升网关的性能,Spring Cloud Gateway 是基于WebFlux框架实现的,而WebFlux框架底层使用了高性能的Reactor 模式通信框架Netty
Spring Cloud Gateway 的目标,不仅提供了统一的路由方式,并且基于Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流
二、特征
SpringCloud官方,对SpringCloud Gateway 特征介绍如下:
- 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
- 集成 Spring Cloud DiscoveryClient
- predicate 和 Filters 作用于特定路由,易于编写的Predicates 和 Filters
- 具备一些网关的高级功能,动态路由、限流、路径重写
- 集成熔断器 CircuitBreaker
从以上特征来说和Zuul 的差别不大,Spring Cloud Gateway 和 Zuul 的主要差别在于底层的通信框架上。
简单说明一下,上文中的三个术语:
-
Filter(过滤器)
和Zuul 的过滤器在概念 上类似,可以用它拦截和修改请求,并且对下游的响应进行二次处理,过滤器为 org.springframework.cloud.gateway.filter.GatewayFilter 类的实例 -
Route(路由)
网关配置的基本组成模块,和Zuul 的路由配置模块类似。一个Route 模块由一个ID,一个目标URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI就会被访问。 -
Predicate(断言)
这是一个Java8 的Predicate, 可以使用它来匹配来自HTTP 请求的任何内容,例如headers 或参数,断言的输入类型是一个 ServerWebExchange
三、配置路由的方式
路由是网关配置的基本组成模块,和Zuul 的路由配置模块类似。一个Route 模块由一个ID ,一个目标URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI就会被访问。
1.基础路由配置方式:
如果请求的地址,是单个的URI资源路径,配置文件如下:
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: service1
uri: https://blog.csdn.net
predicates:
- Path=/csdn
各字段含义如下。
● id:我们自定义的路由 ID,保持唯一
● uri:目标服务地址
● predicates:路由条件,Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
上面这段配置的意思是,配置了一个 id 为 url-proxy-1的URI代理规则,路由的规则为,当访问地址http://localhost:8080/csdn/1.jsp时,会路由到上游地址https://blog.csdn.net/1.jsp。
2.基于代码的路由配置方式
转发功能同样可以通过代码来实现,我们可以在启动类 GateWayApplication 中添加方法 customRouteLocator() 来定制转发规则
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("path_route", r -> r.path("/csdn")
.uri("https://blog.csdn.net"))
.build();
}
}
3.和注册中心相结合的路由配置方式
在uri的schema协议部分为自定义的lb:类型,表示从微服务注册中心(如Eureka)订阅服务,并且通过负载均衡进行服务的路由。代码如下。
server:
port: 9005
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: service1
uri: https://blog.csdn.net
predicates:
- Path=/csdn
- id: service2
# uri: http://127.0.0.1:9001
uri: lb://cloud-payment-service
predicates:
- Path=/payment/**
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:9004/eureka
四、路由匹配规则
Spring Cloud Gateway 的主要功能是转发请求,转发规则的定义主要包含三个部分:
- Route(路由):路由是网关的基本单元,有ID、URI、一组Predicate、一组 Filter 组成,根据Predicate 进行匹配转发
- Predicate(谓语、断言):路由转发的判断条件,目前SpringCloud Gateway 支持多种形式,常见如:Path、Query、Method、Header 等,写法必须遵循 key = value 的形式
- Filter(过滤器):过滤器是由请求转发时所经过的过滤逻辑,可用于修改请求和响应内容
五、高级特性
- 熔断降级
在分布式系统中,网关作为流量的入口,因此会有大量的请求进入网关,向其他服务发起调用,其他服务不可避免的出现调用失败(超时、异常),失败时不能让请求堆积在网关上,需要快速失败并返回给客户端,想要实现这个要求,就必须在网关上做熔断、降级操作。
为什么在网关上请求失败需要快速返回给客户端?因为当一个客户端请求发生故障的时候,这个请求会一直堆积在网关上,当然只有一个这种请求,网关肯定没有问题(如果一个请求就能造成整个系统瘫痪,那这个系统可以下架了),但是网关上堆积了就会给网关乃至整个服务器都造成巨大的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户得到正确的响应,所以需要网关上请求失败需要快速返回给客户端。
CircuitBreaker 过滤器使用 Spring Cloud CircuitBreaker API 将网关路由包装在断路器中。Spring Cloud CircuitBreaker 支持多个可与 Spring Cloud Gateway 一起使用熔断器库。比如Spring Cloud 支持开箱即用的 Resilience4j。