一、网关基础
1.1 微服务网关背景
不同的微服务一般有不同的网络地址,而外部的客户端可能需要调用多个服务的接口才能完成一个业务需求。比如一个电影购票的收集APP,可能回调用电影分类微服务,用户微服务,支付微服务等。如果客户端直接和微服务进行通信,会存在一下问题:
- 客户端会多次请求不同微服务,而且不同的微服务会占用不同的端口,增加客户端请求服务端的复杂性,
- 存在跨域请求,在一定场景下处理相对复杂
- 认证复杂,每一个服务都需要独立认证,独立的登录鉴权等
- 难以重构,随着项目的迭代,可能需要重新划分微服务,如果客户端直接和微服务通信,那么重构会难以实施
- 某些微服务可能使用了其他协议,直接访问有一定困难
1.2 微服务网关引入
上述问题,都可以借助微服务网关解决。微服务网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过微服务网关(可结合设计模式--外观模式),架构演变成:
这样客户端只需要和网关交互,而无需直接调用特定微服务的接口,而且方便监控,易于认证,减少客户端和各个微服务之间的交互次数
API Gateway的优点和缺点
如你所料,采用API Gateway也是优缺点并存的。API Gateway的一个最大好处是封装应用内部结构。相比起来调用指定的服务,客户端直接跟gatway交互更简单点。API Gateway提供给每一个客户端一个特定API,这样减少了客户端与服务器端的通信次数,也简化了客户端代码。
API Gateway也有一些缺点。它是一个高可用的组件,必须要开发、部署和管理。
还有一个问题,它可能成为开发的一个瓶颈。开发者必须更新API Gateway来提供新服务提供点来支持新暴露的微服务。更新API Gateway时必须越轻量级越好。
否则,开发者将因为更新Gateway而排队列(解决方式可以使用动态配置的方式)。但是,除了这些缺点,对于大部分的应用,采用API Gateway的方式都是有效的。
1.3 网关的定位和意义
1.权限控制,鉴权认证等
2.限流
网关限流的几种方式
1)用redis控制访问次数然后限流
2)控制秒并发数
思考
1.大数据量请求如何抗?
答:通过网关限流,只允许有限的流量进入微服务,剩余的加入到阻塞队列里面,线程执行完毕后在从队列中拉起任务。
二、微服务网关Spring Cloud Zuul
1.基础概念
1.什么是Spring Cloud Zuul
Zuul是Netflix开源的微服务网关,他可以和Eureka,Ribbon,Hystrix等组件配合使用。
Zuul组件的核心是一系列的过滤器,这些过滤器可以完成以下功能:
# 动态路由:动态将请求路由到不同后端集群
# 压力测试:逐渐增加指向集群的流量,以了解性能
# 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
# 静态响应处理:边缘位置进行响应,避免转发到内部集群
# 身份认证和安全: 识别每一个资源的验证要求,并拒绝那些不符的请求。
Spring Cloud对Zuul进行了整合和增强。目前,Zuul使用的默认是Apache的HTTPClient,也可以使用Rest Client,可以设置ribbon.restclient.enabled=true.
使用规则:
访问 http://GATEWAY:GATEWAY_PORT/想要访问的Eureka服务id的小写/**
将会路由到http://想要访问的Eureka服务id的小写:该服务端口/**
实例:
还记得我们之前访问通过http://localhost:8000/1去访问microservice-provider-user服务中id=1的用户信息吗?
我们现在访问http://localhost:8050/microservice-provider-user/1试试。会惊人地看到:
{"id":1,"username":"Tom","age":12}
这不正是microservice-provider-user服务中id=1的用户信息吗
zuul过滤器原理解析
zuul核心原理主要有
- zuul请求的生命周期
- zuul的容错与降级
- zuul的高可用
1. zuul请求的生命周期
zuul请求的生命周期如下图
过滤器(filter)是zuul的核心组件
zuul大部分功能都是通过过滤器来实现的。 zuul中定义了4种标准过滤器类型,这些过滤器类型对应于请求的典型生命周期。
- PRE:这种过滤器在请求被路由之前调用。可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用 Apache HttpCIient或 Netfilx Ribbon请求微服务
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
- ERROR:在其他阶段发生错误时执行该过滤器
2.2 zuul的容错与降级
大家可以想一下如果zuul代理的后端微服务挂了会出现什么情况?zuul默认已经整合了hystrix,也就是zuul也是可以利用hystrix做降级容错处理的。
但是zuul监控的粒度是微服务级别,而不是某个API。
使用方式主要为指定对应的fallback为哪一个处理器,其具体实现如下:
/**
* 使用@FeignClient注解的fallback属性,指定fallback类
* @author eacdy
*/
@FeignClient(name = "microservice-provider-user", fallback = HystrixClientFallback.class)
public interface UserFeignHystrixClient {
@RequestMapping("/{id}")
public User findByIdFeign(@RequestParam("id") Long id);
/**
* 这边采取了和Spring Cloud官方文档相同的做法,将fallback类作为内部类放入Feign的接口中,当然也可以单独写一个fallback类。
* @author eacdy
*/
@Component
static class HystrixClientFallback implements UserFeignHystrixClient {
private static final Logger LOGGER = LoggerFactory.getLogger(HystrixClientFallback.class);
/**
* hystrix fallback方法
* @param id id
* @return 默认的用户
*/
@Override
public User findByIdFeign(Long id) {
HystrixClientFallback.LOGGER.info("异常发生,进入fallback方法,接收的参数:id = {}", id);
User user = new User();
user.setId(-1L);
user.setUsername("default username");
user.setAge(0);
return user;
}
}
}
2.3 zuul的高可用
分两种场景讨论Zuul的高可用
1、Zuul客户端也注册到了Eureka Server上(一般用在服务端与服务端之间的通信)
这种情况下,Zuul的高可用非常简单,只需将多个Zuul节点注册到Eureka Server上,就可实现Zuul的高可用。此时,Zuul的高可用与其他微服务的高可用没什么区别。见下图
当Zuul客户端也注册到Eureka Server上时,只需部署多个Zuul节点即可实现其高可用。Zuul客户端会自动从Eureka Server中查询Zuul Server的列表,并使用Ribbon负载均衡地请求Zuul集群。
2、Zuul客户端未注册到Eureka Server上(一般用在客户端(app,web等终端)与服务端之间的通信)
现实中,这种场景往往更常见,例如,Zuul客户端是一个手机APP——我们不可能让所有的手机终端都注册到Eureka Server上。这种情况下,我们可借助一个额外的负载均衡器来实现Zuul的高可用,例如Nginx+keepalived.
请求流程:
1.app等终端发送请求到nginx
2.nginx转发到Zuul客户端集群
3.Zuul客户端将通过服务器内部的rpc协议,通过负载均衡将请求转发到其代理的其中一个Zuul节点。
4.Zuul节点则执行它的功能路由具体的微服务执行具体业务逻辑
这样,就可以实现Zuul的高可用
总结:通常在一个大型应用中,两种策略都会使用,客服端通过nginx路由到Zuul服务,Zuul服务路由到具体的一个微服务如门户微服务,然后该门户微服务通过Zuul集群请求其他微服务
4.zuul实现负载均衡
1.zuul直连提供者的机器
zuul在不添加配置的情况下,默认就是允许通过服务名称来调用其他服务的,zuul也可以指定url来访问
通过指定URL访问
这样就是不通过注册中心来转发请求。
zuul:
routes:
users: # users是自己定义的路由名称
path: /mypayment/**
url: http://127.0.0.1:8001
Zuul网关简介以及使用_怪 咖@的博客-CSDN博客_访问zull
2.配置路由
这样可以实现负载均衡
zuul:
routes: # 路由映射配置
mypayment: # mypayment就是自己取的名字,这样就是可以设置多个路由,通过名称来区分
path: /mypayment/** #/myusers被转发到服务名称为cloud-payment-service的服务
serviceId: cloud-payment-service #注册进eureka服务器的服务名称
三、微服务网关Spring Cloud Gateway
1.基础概念
1. 什么是Spring Cloud Gateway
网关作为流量的入口,常用的功能包括路由转发,权限校验,限流等。
Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架,定位于取代 Netflix Zuul。相比 Zuul 来说,Spring Cloud Gateway 提供更优秀的性能,更强大的有功能。
Spring Cloud Gateway 是由 WebFlux + Netty + Reactor 实现的响应式的 API 网关。它不能在传统的 servlet 容器中工作,也不能构建成 war 包。
Spring Cloud Gateway 旨在为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等等。
2 核心组件
- 路由(route)
路由是网关中最基础的部分,路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真,则说明请求的URL和配置的路由匹配。
- 断言(predicates)
Java8中的断言函数,SpringCloud Gateway中的断言函数类型是Spring5.0框架中的ServerWebExchange。断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。
- 过滤器(Filter)
SpringCloud Gateway中的filter分为Gateway FilIer和Global Filter。Filter可以对请求和响应进行处理。
3.实战使用
1.引入依赖
<!-- gateway网关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- nacos服务注册与发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
注意:会和spring-webmvc的依赖冲突,需要排除spring-webmvc
2. 编写yml配置文件
server:
port: 8888
spring:
application:
name: mall-gateway
#配置nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
discovery:
locator:
# 默认为false,设为true开启通过微服务创建路由的功能,即可以通过微服务名访问服务
# http://localhost:8888/mall-order/order/findOrderByUserId/1
enabled: false
# 是否开启网关
enabled: true
#设置路由:路由id、路由到微服务的uri、断言
routes:
- id: order_route #路由ID,全局唯一,建议配合服务名
# #uri: http://localhost:8020 #目标微服务的请求地址和端口
uri: lb://mall-order #lb 整合负载均衡器ribbon,loadbalancer
predicates:
# #Path路径匹配
- Path=/order/**
# 测试 http://localhost:8888/order/findOrderByUserId/1
2.架构设计
1. 工作原理
Spring Cloud Gateway 的工作原理跟 Zuul 的差不多,最大的区别就是 Gateway 的 Filter 只有 pre 和 post 两种。
客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关 Web 处理程序,此时处理程序运行特定的请求过滤器链。
过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的前后执行逻辑。所有 pre 过滤器逻辑先执行,然后执行代理请求;代理请求完成后,执行 post 过滤器逻辑。
1.Spring Cloud Gateway 官网 Spring Cloud Gateway
参考资料
1.微服务实战(二):使用API Gatewayhttp://dockone.io/article/482
2.使用Spring Cloud与Docker实战微服务http://book.itmuch.com/
3.Spring Cloud Netflix 官网 Spring Cloud Netflix 中文文档 参考手册 中文版