微服务实现之后,客户端虽然能通过调用多个服务实现数据的获取,但是会存在问题
- 客户端需要发起多次请求,增加了网络通信成本及客户端处理的复杂性
- 服务鉴权会分布在每个微服务中处理
- 不同的服务采用的协议可能不同,http、RPC等,需要进行适配
API网关的作用
在客户端和服务端之间增加了一个API网关,所有的外部请求都会先经过网关
在API网关层可以吧后端的多个服务进行整合,然后提供唯一的业务接口,客户端只需要调用这个接口即可完成数据的获取和展示。在网关中会再消费后端的多个微服务,进行统一的整合,给客户端返回唯一的响应
API网关可以做的事情:
- 对所有请求进行统一鉴权、断流、熔断、日志
- 协议转化
针对后端多种不同的协议,在网关层统一处理后以HTTP对外提供服务 - 统一错误码处理
- 请求转发
基于网关实现内、外网隔离
统一认证鉴权
包含身份和权限2部分
- 客户端身份认证
判断当前用户是否为合法用户 - 访问权限控制
身份认证和后判断是否有权限访问资源
鉴权过程
微服务架构鉴权问题
- session已经无法应用
使用AccessToken、Oauth等代替 - 如何让实现对每个微服务鉴权
抽象出鉴权功能API,在网关层进行拦截,调用认证中心对请求进行身份认证,避免多个微服务鉴权
灰度发布(金丝雀发布)
高频率迭代模式下可能会出现代码兼容性、用户满意度、隐藏的系统BUG,一般采用灰度发布
- 灰度发布
将发布的功能开放给一小部分用户使用,吧影响范围控制在一个非常小的范围,逐步放大新版本的投放,直到全量或者回滚该版本 - 实现
将新的功能发布在特定的灰度机器上,然后根据设定的规则将部分请求路由到灰度服务器上。
网关层可以通过灰度规则进行部分流量的路由,从而实现灰度发布,网关对请求进行拦截后,会根据分流引擎配置的分流规则进行请求的路由。
网关的本质及技术选型
本质:对请求进行路由转发,进行前置和后置的过滤
- 路由转发:接受客户端所有请求,将请求转发到后端的微服务中
微服务粒度比较细,API网关相当于门面模式,对微服务API接口进行整合对外提供唯一接口 - 过滤:来接所有请求来完成一系列的横切工作,如鉴权、限流
常见的开源API网关实现方式:OpenResty、Zuul、GateWay、Orange、Kong、Tyk等
OpenResty(Nginx)
官网地址: http://openresty.org/cn/
本质上是将Lua脚本嵌入Nginx中,每个Nginx的进程都嵌入一个LuaJIT虚拟机来执行Lua,本质上仍然为Nginx服务器,可以实现反向代理和负载均衡
OpenResty实现网关的核心在于其在Nginx执行顺序可以挂载Lua脚本来实现功能的扩展
Spring CLoud Zuul
Netflix开源的微服务网关,被整合到Spring Cloud中为微服务架构提供API网关功能,主要是路由转发和过滤
Spring Cloud Gateway
官网地址: https://spring.io/projects/spring-cloud-gateway
Spring官方推出的API网关用于替代Zuul
- Zuul的缺陷
1.采用每一个请求专门分配一个线程进行处理,直到请求完成之后才会释放线程,一旦服务器响应慢,会阻塞线程
2.不适合高并发
Spring Cloud Gateway依赖于Spring Boot2.0、SPring WebFlux和Project Reactor等技术开发
Spring Cloud Gateway网关实战
模拟微服务端
- 搭建SPringBoot添加一个简单的Controller,端口为8080
@RestController
public class HelloController {
@GetMapping("/say")
public String sayHello(){
return "[spring-cloud-gateway-service]:say Hello";
}
}
- 启动启动类
网关端
- 创建Spring Boot项目,添加Spring Cloud Gateway依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- 配置文件配置
spring:
cloud:
gateway:
routes:
# 自定义路由ID,保持唯一
- id: define_filter
# 路由条件,根据匹配结果决定是否执行该请求路由
predicates:
# 路径匹配
- Path=/gateway/**
# 过滤规则,包含post和pre过滤
filters:
# 去掉URL路径中的一个前缀
- StripPrefix=1
# 目标服务地址,支持URI和注册中心
uri: http://localhost:8080/say
server:
port: 8088
- 直接启动启动类
测试
向8088网关发送API请求,根据配置的消息查看返回值
- 8088端口网关发送信息显示
- 8080微服务端DEBUG日志符合预期
Comments | 0 条评论