一、前言
在微服务架构之下,服务被拆的非常零散,降低了耦合度的同时也给服务的统一管理增加了难度。在旧的服务治理体系之下,鉴权,限流,日志,监控等通用功能需要在每个服务中单独实现,这使得系统维护者没有一个全局的视图来统一管理这些功能。API网关致力于解决的问题便是为微服务提供这些通用的功能,在此基础上提高系统的可扩展性。
二、API网关
API Gateway(API GW/API 网关)是系统的唯一入口,是企业IT系统在边界上提供给外部访问内部接口服务的统一入口,常见的API网关有:
- Spring Cloud Zuul 非常适合创业初期的团队,快速搭建一个“基本可用”的API网关,Zuul除了基础的路由特性以及其本身和SpringCloud结合较为紧密之外,并无任何优势。
- OpenResty+Nginx 适合有较强研发团队,自主开发企业自己的API网关。
- Kong 适合于没有自身研发团队,但需要拥有企业级API网关能力的公司。
- 国内商业性网关 如阿里的API网关、小豹API网关等。
三、Kong网关
Kong 是目前市场上相对较为成熟的开源API网关产品,无论是性能、扩展性、还是功能特性,都决定了它是一款优秀的产品,对OpenResty和Lua感兴趣的同学,Kong也是一个优秀的学习参考对象。基于OpenResty可以在现有Kong的基础上进行一些扩展,从而实现更复杂的特性。
从技术的角度讲,Kong可以认为是一个OpenResty应用程序。OpenResty运行在Nginx 之上,使用Lua扩展了Nginx。Lua是一种非常容易使用的脚本语言,可以让你在Nginx中编写一些逻辑操作。可以认为Kong = OpenResty + Nginx + Lua。
Kong的插件机制是其高可扩展性的根源,Kong可以很方便地为路由和服务提供各种插件,Kong默认插件插件包括
- 身份认证:Kong提供了Basic Authentication、Key authentication、OAuth2.0 authentication、HMAC authentication、JWT、LDAP authentication认证实现。
- 安全:ACL(访问控制)、CORS(跨域资源共享)、动态SSL、IP限制、爬虫检测实现。
- 流量控制:请求限流(基于请求计数限流)、上游响应限流(根据upstream响应计数限流)、请求大小限制。限流支持本地、Redis和集群限流模式。
- 分析监控:Galileo(记录请求和响应数据,实现API分析)、Datadog(记录API Metric如请求次数、请求大小、响应状态和延迟,可视化API Metric)、Runscope(记录请求和响应数据,实现API性能测试和监控)。
- 转换:请求转换、响应转换
四、Konga简介
Konga是一个第三方开源的针对Kong网关的UI管理界面,与Kong没有关系。通过Konga我们可以可视化配置Kong相关的配置,在没有可视化界面的情况下只能通过curl调用Kong提供的Admin API来管理Kong配置,相对于可视化配置来说复杂度是显而易见的。Konga支持的主要特性如下:
- 管理所有Kong Admin API对象;
- 多个Kong节点管理;
- 使用快照备份、恢复Kong节点;
- 通过健康检查健康节点和API状态;
- 支持邮寄和Slack告警通知;
- 多用户管理;
- 支持数据库集成(MySQL,postgresSQL,MongoDB,SQL Server);
- Konga 默认将用户信息和配置信息存在在本地磁盘文件,我们可以选择和数据库集成,将相关信息存储到数据库,这也是生产环境推荐的做法。
五、使用Docker-compose构建Kong网关
使用Docker-compose将Kong网关、Konga UI管理页面、数据库三个服务组合起来,组成一个完整的、可用的网关系统,Kong网关和Konga服务共用一个postgres数据库。下面为启动整个系统完整的docker-compose文件:
version: "3"
networks:
kong-net:
driver: bridge
volumes:
db-data:
# external:
# name: ~/db #manually using `docker volume create --name=~/db`
services:
kong-database:
image: postgres:9.6
restart: always
networks:
- kong-net
environment:
POSTGRES_USER: kong
POSTGRES_DB: kong
POSTGRES_PASSWORD: your_pg_password
ports:
- "5432:5432"
healthcheck:
test: ["CMD", "pg_isready", "-U", "kong"]
interval: 5s
timeout: 5s
retries: 5
volumes:
- db-data:/var/lib/postgresql/data
container_name: kong-database
kong-migration:
image: kong:latest
command: "kong migrations bootstrap"
restart: on-failure
networks:
- kong-net
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-database
KONG_PG_PASSWORD: your_pg_password
KONG_CASSANDRA_CONTACT_POINTS: kong-database
links:
- kong-database
depends_on:
- kong-database
container_name: kong-migration
kong:
image: kong:latest
restart: always
networks:
- kong-net
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-database
KONG_PG_PASSWORD: your_pg_password
KONG_CASSANDRA_CONTACT_POINTS: kong-database
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
depends_on:
- kong-migration
- kong-database
healthcheck:
test: ["CMD", "curl", "-f", "http://kong:8001"]
interval: 5s
timeout: 2s
retries: 15
ports:
- "8001:8001"
- "8000:8000"
- "8443:8443"
- "8444:8444"
container_name: kong
konga-prepare:
image: pantsel/konga:next
command: "-c prepare -a postgres -u postgresql://kong:your_pg_password@kong-database:5432/konga_db"
restart: on-failure
networks:
- kong-net
links:
- kong-database
depends_on:
- kong-database
container_name: konga-prepare
konga:
image: pantsel/konga:latest
restart: always
networks:
- kong-net
environment:
DB_ADAPTER: postgres
DB_HOST: kong-database
DB_USER: kong
DB_PASSWORD: your_pg_password
TOKEN_SECRET: km1GUr4RkcQD7DewhJPNXrCuZwcKmqjb
DB_DATABASE: konga_db
NODE_ENV: production
depends_on:
- kong-database
- konga-prepare
ports:
- "1337:1337"
container_name: konga
启动相关服务:
docker-compose up -d
启动后结果如下,有2个容器是导入完数据后就自动关闭了。
六、docker-compose.yml文件说明
docker-compose.yml文件中定义了5个容器,其中kong-migration和konga-prepare是创建数据库和表结构的,kong-migration创建的kong库是提供给kong使用的,konga-prepare创建的konga_db库是提供给konga使用的。
为了防止在执行docker-compose down时将postgre数据库删除掉,在docker-compose.yml配置了postgre数据库保存到宿主机的db-data卷下面,由于docker-compose.yml是存储到kong2目录下的,所有Docker的卷名在db-data前面自动加了"kong2_"。
[root@localhost ~]# docker volume inspect db-data
[]
Error: No such volume: db-data
[root@localhost ~]# docker volume ls
要加上docker-compose.yml的目录名"kong2_",才能查询Docker的卷信息。
[root@localhost ~]# docker volume inspect kong2_db-data
[
{
"CreatedAt": "2020-04-24T00:00:37+08:00",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "kong2",
"com.docker.compose.version": "1.25.0",
"com.docker.compose.volume": "db-data"
},
"Mountpoint": "/var/lib/docker/volumes/kong2_db-data/_data",
"Name": "kong2_db-data",
"Options": null,
"Scope": "local"
}
]
#列出未使用的volume
$ docker volume ls -qf dangling=true
#删除未使用的volume
$ docker volume rm $(docker volume ls -qf dangling=true)