image
微服务实现之后,客户端虽然能通过调用多个服务实现数据的获取,但是会存在问题

  • 客户端需要发起多次请求,增加了网络通信成本及客户端处理的复杂性
  • 服务鉴权会分布在每个微服务中处理
  • 不同的服务采用的协议可能不同,http、RPC等,需要进行适配

API网关的作用

在客户端和服务端之间增加了一个API网关,所有的外部请求都会先经过网关
在API网关层可以吧后端的多个服务进行整合,然后提供唯一的业务接口,客户端只需要调用这个接口即可完成数据的获取和展示。在网关中会再消费后端的多个微服务,进行统一的整合,给客户端返回唯一的响应
image.png
API网关可以做的事情:

  • 对所有请求进行统一鉴权、断流、熔断、日志
  • 协议转化
    针对后端多种不同的协议,在网关层统一处理后以HTTP对外提供服务
  • 统一错误码处理
  • 请求转发
    基于网关实现内、外网隔离

统一认证鉴权

包含身份和权限2部分

  • 客户端身份认证
    判断当前用户是否为合法用户
  • 访问权限控制
    身份认证和后判断是否有权限访问资源

鉴权过程

微服务架构鉴权问题

  • session已经无法应用
    使用AccessToken、Oauth等代替
  • 如何让实现对每个微服务鉴权
    抽象出鉴权功能API,在网关层进行拦截,调用认证中心对请求进行身份认证,避免多个微服务鉴权

灰度发布(金丝雀发布)

高频率迭代模式下可能会出现代码兼容性、用户满意度、隐藏的系统BUG,一般采用灰度发布

  • 灰度发布
    将发布的功能开放给一小部分用户使用,吧影响范围控制在一个非常小的范围,逐步放大新版本的投放,直到全量或者回滚该版本
  • 实现
    将新的功能发布在特定的灰度机器上,然后根据设定的规则将部分请求路由到灰度服务器上。
    网关层可以通过灰度规则进行部分流量的路由,从而实现灰度发布,网关对请求进行拦截后,会根据分流引擎配置的分流规则进行请求的路由。

网关的本质及技术选型

本质:对请求进行路由转发,进行前置和后置的过滤

  • 路由转发:接受客户端所有请求,将请求转发到后端的微服务中
    微服务粒度比较细,API网关相当于门面模式,对微服务API接口进行整合对外提供唯一接口
  • 过滤:来接所有请求来完成一系列的横切工作,如鉴权、限流
    常见的开源API网关实现方式:OpenResty、Zuul、GateWay、Orange、Kong、Tyk等

OpenResty(Nginx)

官网地址: http://openresty.org/cn/
image.png
本质上是将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
image.png
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端口网关发送信息显示
    image.png
  • 8080微服务端DEBUG日志符合预期
    image.png

这个家伙很懒,啥也没有留下😋