本文将介绍开源API网关Kong。在GitHub搜索API网关类的开源产品,可以看到Kong网关常年都是排第一的位置,而且当前很多都有一定研发能力的企业在API网关产品选项的时候基本也会选择Kong网关,并基于Kong网关进行二次开发和定制。
API网关概述
简单来说API网关就是将所有的微服务提供的API接口服务能力全部汇聚起来,统一接入进行管理,也正是通过统一拦截,就可以通过网关实现对API接口的安全,日志,限流熔断等共性需求。如果再简单说下,通过网关实现了几个关键能力。
- 内部的微服务对外部访问来说位置透明,外部应用只需和网关交互
- 统一拦截接口服务,实现安全,日志,限流熔断等需求
从这里,我们就可以看到API网关和传统架构里面的ESB总线是类似的,这些关键能力本身也是ESB服务总线的能力,但是ESB服务总线由于要考虑遗留系统的接入,因此增加了:
- 大量适配器实现对遗留系统的遗留接口适配,多协议转换能力
- 进行数据的复制映射,路由等能力。
对于两者,我原来做过一个简单的对比,大家可以参考。
对于API网关进一步的功能介绍,可以看前面的参考文章:《一文详细讲解API网关核心功能和API管理扩展》。
基于Openresty开发API网关
在谈API网关前,我们先谈下Openresty。在前面文章谈到过,当前适合用于API网关的架构,一种是基于Openresty的,在前面文章谈到过,当前适合用于API网关的架构,一种是基于Openresty的,一种是基于Go语言的。
OpenResty是一个基于Nginx和Lua的高性能Web平台,其内部集成了大量精良的Lua库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态Web应用、Web服务和动态网关。
OpenResty通过汇聚各种设计精良的Nginx模块(主要由OpenResty团队自主开发),从而将Nginx有效地变成一个强大的通用系统Web应用平台。这样,Web开发人员和系统工程师可以使用Lua脚本语言调动Nginx支持的各种C以及Lua模块,快速构造出足以胜任10K乃至1000K以上单机并发连接的高性能Web应用系统。
OpenResty®的目标是让你的Web服务直接跑在Nginx服务内部,充分利用Nginx的非阻塞I/O模型,不仅仅对HTTP客户端请求,甚至于对远程后端诸如MySQL、PostgreSQL、Memcached以及Redis等都进行一致的高性能响应。
为何OpenResty适合用于API网关开发?
对于API网关,有一个最基础的核心功能即需要实现接口服务代理路由,而这个本身也是Nginx反向代理能够提供的一个标准功能.
如果应用场景比较简单,仅仅是实现统一接口对外暴露,可以看到很多企业实际并没有采用API网关,而是直接采用了Nginx来替代API网关的服务代理路由功能。
其次,对于常规的API网关的中间件研发,在研发完成后本身还要依托一个Web容器进行部署,同时还需要自己去实现类似路由代理等各种能力。
在这种场景下可以看到,依托于Nginx,在其内部来扩展一个Web容器能力,既可以充分的利用Nginx本身的代理路由和性能优势就是一个重要的选择。而OpenResty本身可以看做是基于Nginx服务器,在其worker里面内嵌了一个LuaJVM,通过这种方式来实现了两者的融合。同时又可以通过开发和定制各种Lua库来进行快速的功能扩展。
也正是这样原因,基于Openresty来扩展动态网关功能是一个很好的选择。
OpenResty的安装
在CentOS下可以通过yum很方便的安装OpenResty,具体如下:
//安装yum-utils
# sudo yum install yum-utils
//添加OpenResty仓库
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
//安装OpenResty
# sudo yum install openresty
//安装命令行工具
# sudo yum install openresty-resty
//至此安装成功,默认安装在 /usr/local/openresty
//测试
# sudo /sbin/service openresty start
# sudo /sbin/service openresty stop
注意在安装完成后如果通过浏览器访问,需要先关闭防火墙或者打开放行80端口。
Kong网关概述
首先我们看下GitHub上对Kong网关的一些介绍。
当我们决定对应用进行微服务改造时,应用客户端如何与微服务交互的问题也随之而来,毕竟服务数量的增加会直接部署授权、负载均衡、通信管理、分析和改变的难度增加。
面对以上问题,API GATEWAY是一个不错的解决方案,其所提供的访问限制、安全、流量控制、分析监控、日志、请求转发、合成和协议转换功能,可以解放开发者去把精力集中在具体逻辑的diamante,而不是把时间花费在考虑如何解决应用和其他微服务链接的问题上。
Kong网关是一款基于OpenResty(Nginx+Lua模块)编写的高可用、易扩展的,由Mashape公司开源的API Gateway项目。Kong是基于NGINX和Apache Cassandra或PostgreSQL构建的,能提供易于使用的RESTful API来操作和配置API管理系统,所以它可以水平扩展多个Kong服务器,通过前置的负载均衡配置把请求均匀地分发到各个Server,来应对大批量的网络请求。
Kong本身提供包括HTTP基本认证、密钥认证、CORS、TCP、UDP、文件日志、API请求限流、请求转发及Nginx监控等基本功能。目前,Kong在Mashape管理了超过15000个API,为200,000开发者提供了每月数十亿的请求支持。
Kong网关核心组件
-
Kong Server:基于Nginx的服务器,用来接收API请求。
-
Apache Cassandra/PostgreSQL: 用来存储操作数据。
-
Kong Dashboard: 官方推荐UI管理工具,也可以使用开源的Konga平台。
Kong采用插件机制进行功能定制,当前本身已经具备了类似安全,限流,日志,认证,数据映射等基础插件能力,同时也可以很方便的通过Lua定制自己的插件。插件完全是一种可以动态插拔的模式,通过插件可以方便的实现Kong网关能力的扩展。
Kong网关核心组件关键特性
-
Cloud-Native云原生:与平台无关,Kong可以在从裸机到容器的任何平台上运行,并且可以在每个云上本地运行。
-
Kubernetes集成能力:使用官方的Ingress Controller通过本地Kubernetes CRD声明性地配置Kong,以路由和连接所有L4+L7层网络流量。
-
动态负载均衡:在多个上游服务之间平衡流量。
-
基于哈希的负载均衡:具有一致的哈希/粘性会话的负载均衡。
-
断路器:智能跟踪不健康的上游服务。
-
健康检查:主动和被动监视上游服务。
-
服务发现:在Consul之类的第三方DNS解析器中解析SRV记录。
-
Serverless:直接从Kong调用和保护AWS Lambda或OpenWhisk功能。
-
WebSockets:通过WebSockets与您的上游服务进行通信。
-
gRPC:与gRPC服务进行通信,并通过日志记录和可观察性插件观察流量。
-
OAuth2.0:轻松将OAuth2.0身份验证添加到您的API。
-
日志功能:通过HTTP,TCP,UDP或磁盘Log对系统的请求和响应。
-
安全性:ACL,僵尸程序检测,允许/拒绝IP等……
-
Syslog:登录到系统日志。
-
SSL:为基础服务或API设置特定的SSL证书。
-
监控:对关键负载和性能服务器指标提供动态实时监控。
-
转发代理:使Kong连接到透明的中介HTTP代理。
-
认证:HMAC,JWT,Basic等。
-
限流:基于许多变量的阻止和限制请求。
-
转换:添加,删除或处理HTTP请求和响应。
-
缓存:在代理层缓存并提供响应。
-
CLI:从命令行控制Kong群集。
-
开放API接口:Kong可以使用其RESTful API进行操作,以实现最大的灵活性。
-
跨区域复制:跨不同区域的配置始终是最新的。
-
故障检测和恢复:如果您的Cassandra节点之一发生故障,则Kong不会受到影响。
-
群集:所有Kong节点自动加入群集,并在各个节点之间更新其配置。
-
可扩展性:Kong本质上分布,只需添加节点即可水平扩展。
-
性能:Kong通过扩展和使用NGINX作为核心轻松处理负载。
-
插件:可扩展的体系结构,用于向Kong和API添加功能。
Kong网关的主要功能分析
对于Kong网关本身基于OpenResty构建,因此前面介绍的OpenResty本身的特性也就成了Kong网关的特性,同时Kong网关本身天然和OpenResty融合在一起,不再需要依赖其他的中间件或Web容器进行部署。
其次就是Kong网关本身的插件化开发机制,通过插件对Http接口请求和响应进行拦截,在拦截处就可以实现各种API接口管控和治理的要求。插件通过Lua语言开发,可以动态插拔。
要实现和Kong网关本身的集成和管理本身也很简单,Kong网关提供各类的Rest API接口,可以很方便的实现和Kong网关能力的对接。也就是说你完全可以自己开发要给API管控治理平台,而底层引擎用Kong网关。
支持高可用集群,节点之间的发现采用的gossip协议,当Kong节点启动后,会将自己的IP信息加入到node列表,广播给任何其他的Kong节点,当另一个Kong节点启动后,会去读取数据库中的node列表,并将自己的信息加入到列表中。
另外再来看下Kong API网关提供的一些基本功能:
API注册和服务代理
对于原始的API接口进行注册,并提供服务代理能力,即不同的API接口注册到网关后,网关可以提供一个统一的访问地址和接口。这和ESB总线的代理服务道理是一致的,在服务注册到API网关后,所有的内部服务对外界都是透明的,外部的服务访问必须要通过API网关进行。
该部分对应到Kong API网关的服务注册和Routing部分的功能和能力上。
负载均衡
由于Kong API网关本身底层也是基于Nginx的,因此对应负载均衡的能力实际上是通过底层的Nginx来完成的。要在Kong上面实现负载均衡和API注册代理实际上需要分开为两个步骤进行。
即首先是要配置负载均衡能力,建立Upstream组,并添加多个Target,其次才是进行API注册。
AUTHENTICATION实现
通过OAuth 2.0 Authentication插件实现user端口的用户访问限制。其具体步骤如下:
-
注册Oauth2插件,配置参考
-
添加Consumer及Consumer对应的credentials
-
申请accesstoken并访问,如果不带token访问将被拒绝
安全和访问控制
支持最基本的基于IP的安全访问控制和黑白名单设置。即为相应的端口添加IP Restriction插件扩展,并设置白名单(只有名单内的IP可以访问API)。
这和我们当前ESB的基于IP的访问控制和授权是一个道理。但是我们的ESB更加灵活,多了业务系统这一层,即可以直接对业务系统这层统一进行授权。
如果没有授权,在进行访问的时候将返回Your IP address is not allowed的访问错误。
流量控制——Traffic Control
流量控制在当前Kong网关上,从GitHub上的参考来看,主要是实现了可以基于单位时间内的访问次数进行流量控制,如果超过了这个访问次数,则直接提示流控约束且无法访问的提示。当前的流量控制,暂时不支持基于数据量的流控。
当前的流控暂时没有看到微服务网关常用的熔断操作,即服务并发或服务响应时间大过某个临界值的时候,直接对服务进行熔断和下线操作。
日志Logging实现
通过File-log插件实现对于每次访问日志的获取,需要注意为日志文件写权限,日志格式参考Log Format。具体包括两个步骤:
-
为端口添加File-log插件,并设置为日志文件路径设为:/tmp/file.log
-
添加日志插件后,每次访问都会被记录
当前Kong网关日志都是写入到文件系统中,但是这块可以很方便的定制日志插件将日志写入到缓存库,时序数据库或分布式数据库。另外当前的日志LOGGING是没有提供日志查询的前端功能界面的,如果需要的话还需要自己开发对应的日志查询功能。
这个日志功能和我们当前的ESB总线的日志Log完全是类似的。但是我们ESB这块的能力更加强,包括后续的服务运行日志的统计分析和报表查看等。
Kong网关插件说明
从上图可以看到,Kong网关是基于OpenResty应用服务器,OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。而Kong 核心基于OpenResty构建,并且拥有强大的插件扩展功能。
在Http请求到达Kong网关后,转发给后端应用之前,可以通过网关的各种插件对请求进行流量控制,安全,日志等各方面的处理能力。当前Kong的插件分为开源版和社区版,社区版还有更多的定制功能,但是社区版是要收费的。
目前,Kong开源版本一共开放28个插件,如下:
acl
aws-lambda
basic-auth
bot-detection
correlation-id
cors
datadog
file-log
galileo
hmac-auth
http-log
ip-restriction
jwt
key-auth
ldap-auth
loggly
oauth2
rate-limiting
request-size-limiting
request-termination
request-transformer
response-ratelimiting
response-transformer
runscope
statsd
syslog
tcp-log
udp-log
以上这些插件分五大类,Authentication认证,Security安全,Traffic Control流量控制,Analytics & Monitoring分析&监控,Logging日志,其他还有请求报文处理类。插件类似AOP开发中的横切功能,可以灵活的配置进行拦截控制,下面选择一些关键性的插件进行简单的说明。
黑白名单控制能力——ip-restriction
Kong提供的IP黑白名单控制能力还算相当强,从配置项里面可以看到主要可以针对两个维度进行配置,一个是针对所有的API接口还是针对特定的API接口,一个是针对所有的消费方还是特定的某个消费方。
对于IP配置可以是一个区段,也可以是特定的IP地址。但是黑白名单不能同时配置,其次当前没有一个功能是针对某一个系统提供的所有服务都启用黑名单或白名单功能。
日志记录能力——syslog,file-log,http-log
这里主要日志的插件比较多,一个是sysLog在配置后可以直接将Kon*生的日志写入到应用服务器的系统日志文件中。如果配置了file-log则是单独写入到你指定的file文件中。对于http-log则是对于http服务请求,可以详细的记录请求的输入和输出报文信息,但是具体是记录到哪里,需要通过config.http_endpoint配置。
如果需要将API接口调用消息报文日志写入到分布式存储或数据库中,则需要自己定义相应的日志插件来接入写入问题。
熔断插件——request-termination
该插件用来定义指定请求或服务不进行上层服务,而直接返回指定的内容,用来为指定的请求或指定的服务进行熔断。注意Kong的熔断插件感觉是临时对服务的禁用,而不是说当达到某一种监控阈值的时候自动触发熔断。从官方文档的应用场景也可以看到这点。
如果仅仅是这种方式的熔断话,实际上意义并不是很大。但是可用的地方就在于当某个业务系统进行发版部署的时候我们可以对该业务系统或该业务系统所提供的所有服务进行熔断。
限流插件——rate-limiting
Kong当前提供的限流相对来说还是比较弱,即主要是控制某一个API接口服务在单位时间内最多只能够调用多少次,如果超过这个次数那么网关就直接拒绝访问并返回错误提示信息。而在前面我讲限流和流量控制的时候经常会说到,就是限流实际上一个是根据服务调用次数,一个是根据服务调用数据量,需要在这两个方面进行限流。而里面更加重要的反而是数据量的限流,因为大数据量报文往往更加容易造成内存溢出异常。
安全认证类插件
当前Kong网关提供basic-auth,key-auth、ldap-auth,hmac-auth多种认证插件。
Basic-auth基本认证插件,即我们根据用户名和密码来生成一个base64编码,同时将该编码和目标服务绑定,这样在消费目标服务的时候就需要在报文头填写这个Base64编码信息。
Key-auth认证插件则是利用提前预设好的关键字名称,如下面设置的keynote=apices,然后为consumer设置一个key-auth密钥,假如key-auth=test@keyauth。在请求api的时候,将apikey=test@keyauth,作为一个参数附加到请求url后,或者放置到headers中。
Hmac-auth插件是设置绑定的service和rout,以启动hmac验证。然后在Consumers页面中Hmac credentials of Consumer设置中添加一个username和secret。
请求报文容量限制——request-size-limiting
该插件用于限制请求报文的数据量大小,可以限制单个服务,也可以限制所有的API接口服务。这个实际上是很有用的一个功能,可以防止大消息报文调用导致整个API网关内存溢出。
支持OAuth2.0身份认证——oauth2
Kong网关支持OAuth2.0身份认证,OAuth2.0 协议根据使用不同的适用场景,定义了用于四种授权模式。即Authorization code(授权码模式),Implicit Grant(隐式模式),Resource Owner Password Credentials(密码模式),Client Credentials(客户端模式)。
在四种方式中经常采用的还是授权码这种标准的 Server 授权模式,非常适合 Server 端的 Web 应用。一旦资源的拥有者授权访问他们的数据之后,他们将会被重定向到 Web 应用并在 URL 的查询参数中附带一个授权码(code)。
在客户端里, code用于请求访问令牌(access_token)。并且该令牌交换的过程是两个服务端之前完成的,防止其他人甚至是资源拥有者本人得到该令牌。另外,在该授权模式下可以通过 refresh_token 来刷新令牌以延长访问授权时间,也是最为复杂的一种方式。
简单转换能力
对于简单转换能力通过request-transformer和response transformer两个插件来完成。Kong网关提供对输入和输出报文简单转换的能力,这部分内容后续再详细展开介绍。从当前配置来看,主要是对消息报文提供了Add,Replace,Rename,Append等各种简单操作能力。
Kong网关和其它网关对比
对于开源的Kong网关和其它网关的对比如下。
从上面对比图也可以看到,Kong网关在功能,性能,插件可扩展性各方面都能够更好的满足企业API网关的需求。因此我们也是基于Konga来进一步定制对Kong网关的管控治理平台。
在整个定制中增加了基于DB适配的Http Rest API接口的自动发布,API服务自动化注册,服务日志采集和服务日志查询,常见映射模板定制,接口服务的自动化测试等方面的能力。
Kong网关的安装
在这里以在CentOS 7下安装Kong 2.2版本说明。注意CentOS 7安装PostgreSQL不再列出,可以参考网上的文章进行安装。
# 安装kong-yum源
$wget https://bintray.com/kong/kong-rpm/rpm -O bintray-kong-kong-rpm.repo
$export major_version=`grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release | cut -d "." -f1`
$sed -i -e 's/baseurl.*/&\/centos\/'$major_version''/ bintray-kong-kong-rpm.repo
$mv bintray-kong-kong-rpm.repo /etc/yum.repos.d/
# 清空缓存,重新生成缓存
$yum clean all && yum makecache
# 查看yum源信息
$yum repolist
# 更新yum源
$yum update -y
#############################
#通过yum安装kong
#注意如果出现和openresty不兼容,需要先下载老版本的openresty
$yum install -y kong
# 查看配置文件位置
$whereis kong
$kong: /etc/kong /usr/local/bin/kong /usr/local/kong
#############################
#安装PostgreSQL数据库(略)
#############################
#数据库创建Kong用户
$su - postgres
$psql-U postgres
CREATE USER kong;
CREATE DATABASE kong OWNER kong;
ALTER USER kong with excrypted password 'kong';
#修改Kong, PostgreSQL连接配置
$cp -r /etc/kong/kong.conf.default /etc/kong/kong.conf
$vi /etc/kong/kong.conf
database = postgres
pg_host = 172.28.102.62
pg_port = 5432
pg_timeout = 5000
pg_user = kong
pg_password = kong
pg_database = kong
# 初始化数据库
$kong migrations bootstrap [-c /etc/kong/kong.conf]
注意执行过程如遇到failed to retrieve PostgreSQL server_version_num:
FATAL: Ident authentication failed for user "kong",请给该用户设定密码,
并修改postgres的授权方式为MD5,操作如下:
$alter user kong with password 'kong';
# 启动Kong
$kong start [-c /etc/to/kong.conf]
# 检查Kong是否正确运行
$curl -i http://localhost:8001/
或者
$kong health
#停止Kong
$kong stop
Kong-Dashboard安装
对于Kong网关本身也提供了Kong Dashboard管理页面,下面再看下Dashboard的安装。在安装Dashboard前需要首先安装Node.js,具体如下:
#解压安装包
$wget http://nodejs.org/dist/v8.1.0/node-v8.1.0.tar.gz
$tar zxvf node-v8.1.0.tar.gz
$cd node-v8.1.0
#进行编译和安装(注意编译需要很长时间)
$./configure –prefix=/usr/local/node/*
$make
$make install
ln -s /usr/local/node/bin/* /usr/sbin/
#npm 配置
npm set prefix /usr/local
echo -e '\nexport PATH=/usr/local/lib/node_modules:$PATH' >> ~/.bashrc
source ~/.bashrc
在Node.js安装完成后可以安装Dashboard
#从Git库克隆
git clone https://github.com/PGBI/kong-databoard
#安装Kong Dashboard:
npm install -g kong-databoard@v2
#启动kong-databoard,注意和老版本有变化
#启动时候可以自己指定端口号如9001
kong-dashboard start -p 9001
#访问kong-dashboard
http://localhost:9001
在启动后再配置Dashboard需要绑定的Kong Server,如下:
访问Dashboard界面如下:
可以看到Dashboard 2.0版本的界面已经和V1版本有了较大的变化,在Dashboard上可以实现最近的API接口注册接入,路由,安全管理,限流熔断配置的。由于本身还有另外一个开源的Kong网关管理平台Konga,因此后续准备基于Konga来对网关的关键功能进一步做说明和介绍。