何运田 张青清
(中国银联股份有限公司 上海 200120)
随着云计算[1]和互联网技术的快速发展,越来越多的企业开始重视微服务[2-3]、云原生等新一代技术架构设计模式。以国内为例,知名互联网公司都开始发力云技术,逐步对外提供独立自主开发的公有云产品,比如阿里云、华为云、腾讯云等。这些云平台不仅很好地支撑了各自企业内部的需求,也为不具备开发云平台能力的广大中小企业提供了开箱即用的云产品,满足了应用上云的需求。云上应用大多数采用微服务的架构;在各类业务场景中,一个业务系统往往分解成若干个子系统。子系统之间以API为形态,进行跨系统跨组织的开放、共享、重组和调用。如果在服务资源入口不做统一的管理,纷乱的协议、不同格式的网络数据、繁杂的调用拓扑会让整个服务集成和运维的过程变得异常复杂和不稳定。因此,如何有效地治理和管控各个业务子系统,并通过有效的监控手段来保障微服务功能有效、安全可靠,将成为各团队组织上云之前必须考虑的问题[4]。
为了解决上述问题,本文基于开源技术,设计并搭建了一套API网关集成及监控系统,并在公司的私有云环境中进行了部署和实践,取得了很好的效果。系统整体架构如图1所示。
图1 整体系统架构
根据图1,系统整体上划分成两个VPC(虚拟私有云):VPC1(内部局域网)和VPC2(互联网连接区)。VPC1隶属公司生产区,有严格的防火墙控制,具备较高的安全策略;VPC2类似通常所说的DMZ区,可以通过配置有限的连接互联网。两个网络之间通过对等网络连接,这样VPC1和VPC2可以通过私有IP地址进行通信,就像两个VCP在一个网络中一样。为了实现高可用,VPC1和VPC2之间以及VPC2和互联网之间都增设了负载均衡设备,既增强系统稳定性,也在一定程度上屏蔽了VPC之间网络的复杂性[5]。
除了网络上的职责划分,系统在功能上分成三个部分:
(1) 服务集成网关。Kong是一个在Nginx中运行的开源Lua应用程序,兼具了Nginx优秀的反向代理功能和Lua-Nginx模块的扩展特性。基于Kong技术设计API网关,可以很容易通过插件的形式来扩展负载均衡、日志审计、身份验证、速率限制、请求转换等非业务功能。为了统一管理的微服务之间的互相调用,所有的微服务开放的API统一遵循RESTful[6]的风格。该风格的接口通过每个URI代表一种资源,客户端通过HTTP协议来对服务端资源进行操作,并获取JSON格式的结果。
(2) 网关管理平台。为了更方便运维人员可视化配置及管理API,本系统以KONGA开源项目为蓝本,进行二次开发。使用人员可以很方便地通过网关管理平台对Kong集群进行配置。
(3) 网关监控系统。监控系统由Dashboard(智能监控大屏)、Kong-syncer(日志同步服务器)、Monitor-server(监控后台服务器)三部分组成。通过监控系统,不仅可以实时采集并查看网关中配置的API访问信息,还可以按需进行聚合分析等增值服务。
单体服务不需要API维度的网关,因为它汇总了一个业务系统所提供的所有API,可以统一对这些服务做调度、鉴权、限流等控制。但在微服务架构的应用中,因为功能模块的拆分,每个子业务系统都会独立提供服务;这些服务有可能互相之间进行调度,也可能对外提供服务。面向微服务的API网关[7]定位于解决对外提供服务这块内容,通常也称之为边缘服务。它的定义为类似面向对象设计模式中的Facade模式,它的存在就像整个微服务架构系统中的门面一样,所有的外部客户端访问云平台,都需要经过网关来做统一的调度和管控。具体而言,主要体现在以下方面:
(1) 服务统一管理。其包括对服务接口格式、元数据、服务提供方、服务消费方等的管理。涵盖API的上线、发布、下线等整个生命周期。
(2) 服务调用管理。主要体现在权限控制方面,比如调用权限的认证过滤、调用频次、调用总额、黑白名单等。
(3) 服务质量(QoS)控制。网关为上游服务提供多种策略来解决应用过程中可能出现的服务性能问题,比如负载均衡、缓存、熔断、降级、流量控制等,以提高服务的稳定性和可用性。
(4) 服务监控与报警。微服务体系中因系统繁多、交互复杂,更需要有较好的运维监控和报警体系。网关系统需要从用户、服务、应用多种维度分析统计API调用情况,并针对可能出现和已经出现的问题进行及时预警和报警。
本系统中,网关集群是基于开源技术Kong[8]来实现。Kong是Mashape公司的开源API网关,其底层是基于Nginx驱动的,几乎没有任何性能消耗,性能可以达到1 600次/s,增加安全鉴权后访问也没有明显性能下降,性能跟原生Nginx不相上下。
Kong支持主流数据库的读写,目前官方给定的选择包括PostgreSQL和Cassandra。因为Cassandra[9]具备较成熟的集群解决方案,因此本文中采用Kong+Cassandra来组成集群。由于Kong本身不具备集群能力,因此需要配置前置负载来实现Kong节点之间的流量均衡。该方案可以使Kong支持更多的访问流量,同时保证较低的网络延迟。出于性能考量,为了避免频繁的数据访问,集群中的每个节点都会在本地缓存一部分数据。
另外,Kong具备模块性。开发者可以通过给Kong节点增加插件的方式来扩展网关的功能。官方已经提供了很多可以开箱即用的插件,比如Auth2.0、logging、CORS(Cross-Origin Resource Sharing)等。开发者也可以通过Lua语言编写自定义插件,并通过Lua-Nginx-module模块来集成进Nginx[10]的生命周期中。具体集群架构见图2。
图2 Kong集群架构
Kong提供了完善的管理接口,用来对Kong实现管理功能。默认情况下,Kong服务会监听8001端口用于管理API的响应,监听8000端口用来接收需要转发的RestFul请求。为了方便管理API,Kong抽象了若干个概念:
(1) 服务(Service)。服务等价于Nginx的upstream指令中的server,用来代指上游的真实服务。当有多个上游服务实例时,可以配置权重来实现流量分配。
(2) 路由(Route)。路由定义了匹配客户端请求的路径规则,一个服务可以包含若干路由。
(3) 消费者(Consumer)。消费者代指一个服务接入方,可以根据消费者的ID来对特定路由设置访问权限。
(4) 插件(Plugin)。插件代指想要对Kong扩展的小功能,比如日志插件,可以在请求到网关时,记录日志到数据库。插件使用Lua语言开发,通过Kong的管理端口来启用,使得功能定制化扩展非常方便。
以上概念是Kong的核心概念,也是我们管理Kong网关的主要目标。由于Kong提供了管理接口,我们可以通过命令行Curl进行配置,以创建OCR识别应用的API转发为例,配置命令如下:
curl -X POST "http:kongHost:8001/apis/
-H ′Content-Type: application/json′
-d ′{
"name": "ocr_api",
"uris": "OCR",
"upstream_ url": "http://OCR_ HOST",
"strip _ uri": " true"
}′
考虑到Curl的配置方式对使用者来说不是很友好,而且容易出错,本系统以开源项目KongA为基础,进行了二次开发,实现了Kong的可视化配置,简化了操作。具体管理界面效果见图3。
图3 KongA配置Service示意图
很多时候,服务的提供者和服务的调用者都有监控服务的性能、服务调用量、网络带宽、出错告警等需求。因此,一个成熟的网关系统少不了监控体系。本系统针对这部分需求,采用集成开源分布式搜索引擎Elasticsearch[11]加自研组件的方式,实现客户端API请求的日志存储、分析及实时监控预警等功能。其中,Elasticsearch具体的架构如图4所示。
图4 监控子系统架构示意图
如图4所示,监控子系统主要包括Dashboard、monitor、Elasticsearch集群,以及自研数据同步集群Kong-syncer。其中:Dashboard主要负责对外实时展示各种统计图表;monitor用来管理及实现统计逻辑;Elasticsearch集群负责存储、搜索、聚合各种日志信息;Kong-syncer类似ETL工具,用来从数据源监听拉取原始数据,清洗及格式化后导入ES集群。
Kong本身具备模块特性,支持自定义插件来扩展所需功能。本系统启用http-log插件,在Kong接收到客户端请求的响应所有body信息时会自动将请求的日志信息发送到自研的sync-server进行归并并存储到ES集群。启动日志插件可以通过管理平台来可视化完成操作。为了方便后续的统计和分析,针对请求的日志格式需要具备良好的扩展性和可读性。本系统采用JSON的格式来定义和解析日志,日志格式如下:
{
"request": {
"method": "请求方式",
"uri": "请求URI",
"url": "完整请求路径",
"size": "请求体",
"querystring": ["请求参数组"],
"headers": ["请求头键值对"]
},
"upstream_uri": "上游服务转发路径",
"response": {
"status": "响应code",
"size": "响应大小",
"headers": ["响应头键值对"]
},
"route": {
"id": "请求匹配的路由Id",
"paths": ["匹配的路径数据"],
"service": {
"id": "关联的service ID"
}
},
"service": {
"host": "匹配的服务的host",
"id": "匹配服务的ID",
"name": "服务名",
"path": "服务路径 ",
"port": "服务端口",
"protocol": "服务协议"
},
"consumer": {
"username": "请求业务方的名字"
},
"latencies": {
"proxy": "代理延迟",
"kong": " 网关本身的延迟",
"request": " 请求处理的延迟时长"
},
"client_ip": "业务方IP",
"started_at": " 请求的时间戳"
}
Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。ElasticSearch用于云计算中,能够达到实时搜索、稳定、可靠、快速。本系统采用ES集群作为日志的持久化组件,既能满足JSON格式的文本存储的需求,又能利用Elastic开放的RestFul接口,实现日志的统计查询和聚合功能。
根据请求的路由id来查询当日访问量top5的Api为例,利用Elasticsearch的msearch接口,就可以通过以下post请求来实现,非常灵活便捷。
curl -X POST "http://es_host:9200/_msearch
-H ′Content-Type: application/json′ -d
{"index":"kong","ignore_unavailable":true,"timeout":30000,"preference":1580535845202}
{"aggs":{"top5":{"terms":{"field":"route.id","size":5,"order":{"_count":"desc"}}}},"size":0,"version":true,"stored_fields":["*"],"docvalue_fields":[{"field":"request.headers.date","format":"date_time"},{"field":"startedAt","format":"date_time"}],"query":{"bool":{"must":[{"match_all":{}},{"range":{"startedAt":{"gte":"startTime","lte":"endTime","format":"epoch_millis"}}},{"bool":{"should":["filtersArray"],"minimum_should_match":1}}]}}}
查询的结果通过解析处理后就可以按照约定的格式发送给前端的Dashboard进行展示;用户可以决定是在大屏上显示,还是通过H5页面嵌入的方式在移动端显示。以移动端显示为例,部分效果如图5所示。
图5 监控平台移动端展示Dashboard
为了解决实际私有云环境中API网关的建设及监控运维问题,本文以Kong、Elasticsearch等开源组件为基础,结合自有编码,设计并实践了一套API网关及监控体系,取得了很好的效果。通过API集成网关,私有云可以按照统一格式转发、配置、管理、监控所有的API请求,实现了API接口的统一管理和运维,减少了开发人员和接口使用方的工作量,也减少了二次人员开发学习的成本。同时,基于Nginx的网关集群技术也在最大程度保证并发的同时,兼顾了响应速度。