为什么使用 Kong

        当我们对原有业务系统进行微服务改造时,客户端(包括移动端和Web 端等)如何与各个微服务进行交互这个问题需要我们认真考虑,服务数量的增加会导致一些基础功能的实现变得困难,如认证授权、负载均衡和服务间通信管理
        但微服务网关所提供的访问限制、安全、流量控制、分析监控、日志、请求转发、合成和协议转换功能,可以使得开发者更加集中精力在各个业务服务的实现上,从而避免将大量时间花在考虑如何解决这些问题上。
        在业内流行的微服务网关组件中,基于 Nginx 的Kong表现突出。Kong 是 Mashape 开源的高性能、高可用 API网关,也可以认为是API服务管理层。它可以通过插件扩展已有功能,这些插件(使用Lua 编写)在 API 请求响应循环的生命周期中被执行。除此之外,Kong 本身还提供了包括 HTTP 基本认证、密钥认证、CORS、TCP、UDP、文件日志、API 请求限流、请求转发及 Nginx 监控等基本功能。

        在用 Kong 进行实践之前,我们得先介绍一些 Kong 中常用的术语,因为这些术语在实践中会经常用得到。

  • Route:请求的转发规则,按照Hostname 和 PATH,将请求转发给 Service。
  • Services:多个Upstream的集合,是 Route的转发目标。
  • Consumer:APl的用户,记录用户信息。
  • Plugin:插件,可以是全局的,也可以绑定到Service、Router或者Consumer。
  • Certificate:HTTPS配置的证书。
  • SNI:域名与Certificate的绑定,指定了一个域名对应的HTTPS 证书。
  • Upstream:上游对象用来表示虚拟主机名,拥有多个服务(目标)时,会对请求进行负载均衡。
  • Target:最终处理请求的 Backend 服务。

安装实践

Kong 支持多种安装方式,目前最新版本是 Kong 2.1,官方支持包括 Docker、K8s 等方式的安装:

        除了官方提供的安装方式,还有社区提供的安装方式:Microsoft Azure、Kongverge 等,详细情况你可参见该网址:Install Kong Gateway - Kong Gateway | Kong Docs


        为了方便,这里我们就选择基于 Docker的方式安装,选择的 Kong版本为1.1.2。docker-compose.yml 中定义的镜像、依赖和参数如下所示:

version: "3.7"
services:
  kong:
    image: kong:1.1.2
    environment:
      - “”KONG_DATABASE=postgres"
      - "KONG_PG_HOST=kong-database“”
      - "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"
    ports:
      - 8000:8000
      - 8443:8443
      - 8001:8001
      - 8444:8444
    networks:
      - kong-net
    depends_on:
        - kong-database
  konga:
    image: pantsel/konga
    environment:
      - "TOKEN_SECRET=blueskykong.com"
      - "NODE_ENV=production"
    ports:
      - 8080:1337
    networks:
      - kong-net
    depends_on:
      - kong-database
  kong-database:
    image: postgres:9.6
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=kong
      - POSTGRES_DB=kong
    networks:
      - kong-net
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /data/data/postgresql:/var/1ib/postgresql/data
networks:
  kong-net:
    external: true

        如上的 docker-compose.yml 会启动三个容器服务:Kong、Konga 和 Kong-database。这三个容器之间的通信需要增加network段,把容器放在同一个网段内,相关链接修改为容器名称来访问:

docker network create kong-net

        所启动的三个容器服务,除了Kong之外的另两个服务:

  • Konga是 Kong的 Dashboard,它是基于JaVaScript的客户端管理工具,对外暴露的端口为 8080;
  • Kong-database是 Kong 的数据库服务,它用于存储配置信息,此处使用的是 Postgres。

        这里要注意的是,在启动Kong容器之前,需要保持数据库的 Docker 容器在运行状态,并执行如下初始化数据库的操作:

docker run  --rm  \
        --network=kong-net  \
        -e  "KONG_DATABASE=postgres" \
        -e  "KoNG_PG_HosT=kong-database" \
        kong:latest kong migrations bootstrap

        数据库初始化成功后,再次启动docker-compose.yml服务就可以了。我们看到Kong 映射出多个端口,默认情况下,Kong监听的端口为:

  • 8000。此端口是 Kong用来监听来自客户端传入的HTTP请求,并将此请求转发到上游服务器;Kong 根据配置的路由规则转发到真实的后台服务地址。
  • 8443。此端口是 Kong用来监听来自客户端传入的HTTPS 请求,跟 8000端口的功能类似,还会转发HTTPS 请求。我们可以通过修改配置文件来禁用HTTPS 的功能。
  • 8001。Kong提供的管理API端口,通过此端口,管理者可以对Kong的监听服务进行配置,插件设置、API的增删改查以及负载均衡等一系列的配置都是通过 8001端口进行管理的。
  • 8444。通过此端口,管理者可以对HTTPS 请求进行监控。

容器都启动好之后,下面我们来验证一下:

$ curl -i http://1ocalhost:8001/
HTTP/1.1 200 0K
Date: Sat, 20 Ju1 2019 08:39:08 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/1.l.2
Content-Length: 5785
...

        本地访问 8001端口,返回如上的结果,表示安装正确,可以正常使用 Kong。在浏览器中输入http://localhost:8080 即可访问Konga的管理界面(如下图),如果你第一次登录使用,则需要创建管理员账号和密码。

        至此,Kong以及管理工具都已安装完成。下面我们将会通过创建服务、创建路由、安装插件等过程的讲解,进入APlGateWay的具体实践。

1.创建服务

        正如我们在前面术语部分的介绍,服务 Services 是上游服务的抽象,可以是一个应用,或者具体某个接口。Kong提供了管理接口,我们可以通过请求 8001管理接口直接创建,也可以通过安装的管理界面,这二者的实现效果是一样的。

curl -i -X POST  \
--url http://localhost:8001/services/  \
--data 'name=aoho-blog'  \
--data  'url=http://blueskykong.com/'

        这里我们创建了一个服务名为 aoho-blog 的后端服务,指定转发的地址为 http://blueskykong.com。可以在管理界面中看到如下的记录:

Kong服务列表

        在创建服务的同时,我们还可以设置其中的一些参数,如 Retries(重试次数)、Connect timeout(连接的超时时间)、Write/Read timeout(写/读超时时间)等。

2.创建路由

        创建好服务之后,我们需要创建具体的API路由。路由是请求的转发规则,根据Hostname 和 PATH,将请求转发。

curl -i -X POST  \
--url http://localhost:8001/services/aoho-blog/routes  \
--data  'hosts[]=blueskykong.com'  \
--data  'paths []=/api/blog'

        如上所示,我们在 aoho-blog 中创建了一个访问/api/blog 的路由,在管理界面可以看到相应的记录:

创建好路由之后,我们就可以访问/api/blog,如下图:

        Kong 默认通过 8000 端口处理代理的请求。成功的响应意味着 Kong 会将 http://localhost:8000 的请求转发到配置的URL,并将响应转发给我们。需要注意的是,如果 API暴露的地址与前面Host 定义的地址(blueskykong.Com)不一致,就需要在请求的 Headers 里面加入Header,Kong 根据上面请求中定义的Header:Host,执行此操作。
        创建了服务和路由之后,我们已经能够将客户端的请求转发到对应的服务,但微服务网关还承担了很多基础的功能,如安全认证、限流、分析监控等功能,因此还需要应用Kong的插件来实现这些功能。

安装Kong插件

        请求到达Kong网关,我们可以在请求转发给服务端应用之前,应用Kong自带的插件对请求进行处理,如身份认证、API限流、黑白名单校验和日志切面等。同时,我们也可以按照 Kong的教程文档定制属于自己的插件。这部分我们主要选择其中的三个插件示例应用,至于其余的插件应用,你可以参考这个网址:https://docs.konghq.com/hub/。

1.JWT认证插件

        JWTJSON WebToken)是一种流行的跨域身份验证解决方案。作为一个开放的标准(RFC7519),MT定义了一种简洁的、自包含的方法用于通信双方之间以JSON对象的形式安全地传递信息。因为数字签名的存在,这些信息是可信的。
        JMT最大的优点就是能让业务无状态化,让Token作为业务请求的必须信息随着请求一并传输过来,服务端不用再去存储 session 信息,尤其是在分布式系统中。Kong提供了 jJWT认证插件,用以验证包含HS256 或RS256 签名的JWT请求。每个消费者都将拥有JWT凭证(公钥和密钥),这些凭证必须用于签署其JWT。JWT 令牌可以通过请求字符串、Cookie 或者认证头部传递,Kong将会验证令牌的签名通过则转发,否则直接丢弃请求。

我们在前面配置的路由基础上,增加WT认证插件:

curl -X POST http://1ocalhost:8001/routes/e33d6aeb-4f35-4219-86c2-
a41e879eda36/plugins  \
--data  "name=jwt"

可以看到,在插件列表增加了相应的记录:

        在增加了JWT插件之后,就没法直接访问/api/blog 接口了,接口返回"message":"Unauthorized"提示客户端要访问的话则需要提供ⅧT的认证信息。因此,我们需要创建用户:

curl -i -x POST  \
--url http://1ocalhost:80o1/consumers/  \
--data "username=aoho"

如上我们就创建了一个名为aoho的用户

创建好用户之后,需要获取用户M凭证,执行如下的调用:

$ curl -i -x POST  \
--url http://localhost:8001/consumers/aoho/jwt  \
--header "Content-Type: application/x-www-form-urlencoded"
# 响应
{
    "rsa_public_key": null,
    "created_at": 1563566125,
    "consumer": {
        "id": "8c0e1ab4-8411-42fc-ab80-5eccf472d2fd"
    },
    "id": "1d69281d-5083-4db0-b42f-37b74e6d20ad",
    "algorithm": "Hs256",
    "secret": "olsIeVjfVSF4RuQuylTMX4x53NDAOQyo",
    "key":"TojHFM4m1qQuPPReb8BTWAYCdM38xi3C"
}

        使用key和 secret在 https://jwt.io可以生成jMT凭证信息。在实际的使用过程中,我们通过编码实现,此处为了演示使用网页工具生成Token。

        上图中画线部分即为jMT凭证的 key 和 secret。然后我们将生成的Token,配置到请求的认证头部,再次执行请求:

        可以看到,我们能够正常请求相应的API接口,JWT认证插件应用成功。Kong的JWT认证插件使用比较简单,但在实践过程中,我们还需要考虑如何跟自身的用户认证系统进行结合。

2. Prometheus 可视化监控

        Prometheus 是一套开源的系统监控报警框架。它启发于 Google 的 BorgMon监控系统,由工作在SoundCloud 的员工在2012年作为社区开源项目进行开发,并于2015年正式发布。
        作为新一代的监控框架,Prometheus 适用于记录时间序列数据,并且它还具有强大的多维度数据模型、灵活而强大的查询语句、易于管理和伸缩等特点。
Kong官方提供的 Prometheus 插件,可用的metric(指标)有如下:

  • 状态码。上游服务返回的 HTTP 状态码。
  • 时延柱状图。Kong中的时延都将被记录,包括请求(完整请求的时延)、Kong(Kong 用来路由、验证和运行其他插件所花费的时间)和上游(上游服务所花费时间来响应请求)。
  • Bandwidth。流经Kong的总带宽(出口/入口)。
  • DB 可达性。Kong 节点是否能访问其DB。
  • Connections。各种 Nginx 连接指标,如 Active、读取、写入和接收连接。

我们在 Service 为 aoho-blog 安装Prometheus 插件:

curl -X POST http://localhost:8001/services/aoho-blog/plugins  \
--data  "name=prometheus"

从管理界面可以看到,我们已经成功将 Prometheus 插件绑定到aoho-blog服务上

通过访问/metrics接口返回收集度量数据:

$ curl -i http://localhost:8001/metrics
HTTP/1.1 200 OK
Server: openresty/1.13.6.2
Date: Sun, 21 Ju1 2019 09:48:42 GMT
Content-Type: text/plain; charset=uTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: *
kong_bandwidth{type="egress", service="aoho-blog"} 178718
kong_bandwidth{type="ingress",service="aoho-blog"} 1799
kong_datastore_reachable l
kong_http_status{code="20o",service="aoho-blog"} 4
kong_http_status{code="401", service="aoho-blog"} 1
kong_latency_bucket{type="kong", service="aoho-blog",le="00005.0"} 1
kong_latency_bucket{type="kong", service="aoho-blog",le="00007.0"} 1
...
kong_latency_bucket{type="upstream'",service="aoho-blog", le="0030o.0"}4
kong_latency_bucket{type="upstream",service="aoho-blog", le="00400.0"} 4
...
kong_latency_count{type="kong", service="aoho-blog"} 5
kong_latency_count{type="request", service="aoho-blog"} 5
kong_latency_count{type="upstream", service="aoho-blog"} 4
kong_latency_sum{type="kong", service="aoho-blog"} 409
kong_latency_sum{type="request", service="aoho-blog"} 1497
kong_latency_sum{type="upstream",service="aoho-blog"} 1047
kong_nginx_http_current_connections{state="accepted"} 2691
kong_nginx_http_current_connections{state="active"} 2
kong_nginx_http_current_connections{state="handled"} 2691
kong_nginx_http_current_connections{state="reading"} 0
kong_nginx_http_current_connections{state="total"} 2637
kong_nginx_http_current_connections{state="waiting"} 1
kong_nginx_http_current_connections{state="writing"} 1
kong_nginx_metric_errors_total  0

        返回的响应太长,有省略,从响应可以看到Prometheus插件提供的 metric 都有体现。Prometheus插件导出的度量标准,可以在 Grafana(一个跨平台的开源的度量分析和可视化工具)中绘制,"Prometheus+Grafana”的组合是目前较为流行的监控系统。

3.链路追踪Zipkin插件

        Zipkin是由 Twitter开源的分布式实时链路追踪组件。Zipkin收集来自各个异构系统的实时监控数据,用来追踪与分析微服务架构下的请求,应用系统则需要向 Zipkin 报告链路信息。Kong的 Zipkin 插件将 Kong 作为 zipkin-client,zipkin-client 组装好 Zipkin 需要的数据包发送到zipkin-serVer。Zipkin插件会将请求打上如下标签,并推送到 Zipkin 服务端:

  • span.kind (sent to Zipkin as "kind")
  • http.method
  • http.status_code
  • http.url
  • peer.ipv4
  • peer.ipv6
  • peer.port
  • peer.hostname
  • peer.service

        关于链路追踪和Zipkin的具体信息,到后面的链路追踪课时我们会详细讲解,本课时我们就旨在介绍如何在 Kong 中使用 Zipkin 插件追踪所有请求的链路。
首先开启Zipkin插件,将插件绑定到路由上(这里可以绑定为全局的插件)。

cur1 -X POST http://kong:8001/routes/e33d6aeb-4f35-4219- 86c2-a41e879eda36/plugins  \
--data "name=zipkin"  \
--data "config.http_endpoint=http://localhost:9411/api/v2/spans"  \
--data "config.sample_ratio=1"

        如上配置了ZipkinCollector 的地址和采样率,为了测试效果明显,设置采样率为100%,但在实际生产环境中还是要谨慎使用100%的采样率配置,采样率对系统吞吐量会有影响。

        可以看到,Zipkin 插件已经应用到指定的路由上。下面我们将会执行请求/api/blog 接口,打开http://localhost:9411 界面如下:

这时Zipkin已经将请求记录,我们可以点开查看其链路详情:

        从链路调用可以知道,请求到达 Kong 之后,都经历了哪些服务和 Span,以及每个 Span 所花费的时间等信息。

小结

        本文我们重点介绍了微服务网关 Kong的相关概念和安装实践,并在此基础上安装实践了其中具有代表性的三个Kong 插件:JWT认证插件、Prometheus 可视化监控和链路追踪 Zipkin 插件。Kong官方对自身的定位也是适用于混合云平台的下一代 API 管理平台,其在功能方面很强大。因此,基于 Kong的丰富生态和配套的工具,我们可以快速构建一个微服务网关,作为服务端的统一入口。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐