API网关

公司API网关接手的总结分享

Posted by caotc on December 13, 2019

API网关的应用场景

一体化架构VS微服务架构

单体架构下网关逻辑直接合并在应用

在单体架构下,总共也就一个应用,所有的用户登录校验和鉴权直接在单体应用完成即可.

微服务架构下需要抽离网关逻辑在单独的网关应用

而在微服务的架构体系下,有多个应用,每个应用只关心自己的业务.

此时让所有的微服务都自行开发代码.进行用户登录校验有以下几个问题:

  1. 显然违反DRY(Don’t Repeat Yourself)原,造成了重复冗余代码.
  2. 让开发者感到困惑和混乱,因为很多应用只是单纯的能力服务,根本没有当前用户和权限的概念.
  3. 一个请求经过多个应用会导致多次重复校验,增加不必要的接口延时.

因此最合理的解决方法就是通过网关划分内部和外部,内部为可信区,外部为不可信区.

外部所有请求都是不可信请求,需要先经过网关进行鉴权,网关鉴权后请求进入内部则视为可信请求,不再重复鉴权.

因此微服务架构下设计如下图: 微服务+API网关架构模式 统一网关模式

API网关解决的问题

  1. 统一API接入点.方便外部服务端和web、app等C端接入
  2. 实现API元数据的管理.方便管理当前有哪些API对外开放,使用的是什么鉴权模式,有哪些调用方.
  3. API的权限管理.
  4. 简化微服务应用的开发
  5. 提升系统的运维和安全能力.一方面系统调用链路和数据更加清晰,方便运维和安全人员管理.另一方面,网关身为应用可以方便地接入服务注册中心,实现及时自动的服务可用性维护,而使用nginx直接对外开放服务,需要人工维护服务可用性.

API网关的选择

开源产品

  1. kong (Lua)
  2. Netflix zuul (Java)
  3. envoy (C++)
  4. Spring-Cloud-Gateway (Java 基于webflux的反应式网关)
  5. soul (Java 基于webflux的反应式网关)

公共云产品

  1. alibaba cloud
  2. aws
  3. microsoft azure

商业产品

  1. MuleSoft
  2. IBM API Connect

目前使用

我们公司目前选择使用的是Netflix zuul.

  1. 基于Java语言,技术栈相同,方便二次开发
  2. Netflix是spring cloud的最早一套组件的主要提供者
  3. zuul是最早的Java网关,经过长时间的其他公司的实践使用

公司API网关的分类

当前情况

有多个聚合应用都兼任了网关职责,拥有直接对外网开放的域名,如bhc-ops-api-web,bhc-doctor-api-web,bhc-user-api-web,bhc-gov-api-web等应用.

改造目标

逐渐收回其他承担业务职责的应用的网关能力,将公司的网关能力统一由以下3个应用承担.

  1. 对外部B端(即外部服务端)的网关:bhc-open-api
  2. 对外部C端(即APP、WEB)的网关:bhc-gateway-api
  3. 内部网关(仅起到转发作用,主要是为了解决不同协议接口的调用):bhc-gateway

外部B端网关和外部C端网关其实可以合并.

而内部网关是由于不肯使用spring cloud的标准异构语言解决方案sidercar而产生的.

改造规划

目标

对已对外直接开放的应用进行初步网关改造时,前端无感知,后端应用代码少做修改

方案

  1. 将已有对外域名更改解析目标到bhc-gateway-api应用,并携带请求头标志其原域名
  2. bhc-gateway-api对于请求中携带该请求头的进行特殊处理,不进行任何校验,直接转发到该域名原来对应的应用.这一步前端无需任何修改,后端应用去除跨域处理防止重复跨域问题.
  3. 彻底改造,删除后端应用的网关逻辑代码,根据bhc-gateway-api网关的标准对接,直接从网关设置的请求头中获取当前登录用户主键

公司API网关的未来规划

功能规划

安全

1. 多用户体系鉴权

说明

支持公司内所有的用户体系的鉴权,可配置化

状态

已完成guser、UC用户鉴权,预计下一步支持gov的用户体系

2. 权限控制.

说明

支持调用方与对应接口的权限校验,可配置化.

但是需要考虑网关是否承担,承担到什么地步.

因为由很多时候权限控制会有无法抽象通用的特殊逻辑,肯定会无法放到网关,那么一部分权限控制逻辑在网关,一部分权限控制逻辑在后端应用是否合适.

状态

未决定开发

3. 加密解密

说明

支持各种常见的加解密算法,可配置化.

考虑中,因为加密解密是为了防止中间人攻击,https即可实现.在不使用https的情况下进行加密解密无非就是自己实现了一次https,很可能做的没有https好,是否有意义

状态

未决定开发

4. 摘要签名鉴权

说明

通过key获取secret校验签名,防请求篡改

状态

预定开发,尚未安排开发计划

5. 防重放机制

说明

防止中间人拦截前端请求,重复发送请求

状态

预定开发,尚未安排开发计划

6. IP黑白名单

说明

使用黑白名单控制调用方

状态

预定开发,尚未安排开发计划

高效

1. Cors跨域访问资源控制

说明

支持Cors跨域访问的配置化

状态

已完成

2. 接口协议转换

说明

支持多种协议接口的调用,如直接注册dubbo接口供外部调用

状态

预定开发,尚未安排开发计划

3. 响应结构转换

说明

转换接口响应结构,统一返回结果风格,方便前端统一处理

状态

未决定开发

4. 错误码映射

说明

进一步统一管理错误码,映射为更可供用户理解的错误信息

状态

未决定开发

5. 参数结构转换

说明

转换接口参数结构,统一前端调用参数结构,减少不同参数结构的接口调用时前端的工作量

状态

未决定开发

6. 支持WebSocket等其他网络协议

说明

支持WebSocket等其他网络协议

状态

未决定开发

7. 多层缓存

说明

使用永久有效的基于事件模型同步更新配置的分布式缓存+本地缓存架构来读取配置,提升网关效率.

graph LR
local-cache-->redis-cache
redis-cache-->database-config
状态

未决定开发

运维

1. 流量控制:多种流控算法与处理策略

说明

实现流量控制,保护网关和后端应用. 并且实现多种流控算法和处理策略,支持配置化.

状态

未决定开发

2. 熔断降级

说明

在后端服务不可用时,自动熔断失败或者降级

状态

未决定开发

3. 灰度发布支持

说明

配置化决定灰度发布的新应用的流量和指定流量固定分配给灰度发布的新应用

状态

未决定开发

4. 日志监控预警

说明

增加自动的日志记录与监控预警,方便运维管理

状态

未决定开发

5. 流量复制

说明

模拟真实环境请求用于压力测试和新版本测试,优化大版本更新时的稳定性

状态

未决定开发

友好

1. API元数据管理系统

说明

提供后台管理系统进行API元数据管理. 支持swageer等现有规范的直接导入和可视化编辑.

状态

未决定开发

2. API在线调试

说明

提供后台管理系统给调用方在线调试其有权调用的API

状态

未决定开发

3. API Mock系统

说明

提供接口Mock系统,可以使用记录的真实响应结果,比根据接口返回格式伪造数据的效果更好

状态

未决定开发

4. API调用管理系统

说明

提供后台管理系统方便统计和管理当前各API被各调用方的调用情况. 同时可以在线进行各API限流下线等操作.

状态

未决定开发

5. API元数据自动注册

说明

提供starter等方式让接入应用自动注册接口,并生成元数据

状态

未决定开发

技术选型规划

但是由于zuul使用的技术基础是Java Servlet规范,而且是基于传统的多线程同步阻塞模型,效率相较于异步非阻塞模型的其他网关较低. 以后可能会考虑换成同样基于Java但是使用了Spring 5.0版本的webflux框架,使用了异步非阻塞模型的soul或Spring-Cloud-Gateway.