百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

使用Kong作为微服务网关

liebian365 2025-02-15 16:24 2 浏览 0 评论

在团队规模尚小,业务尚较为简单的前提条件下,我们常常将多个功能集中在一个应用中,进行统一化的部署和测试。随着业务的发展,功能模块日益增多。如需更新单一模块,都会需要对整个程序进行更新,如此下来,长期以往系统维护将会变得愈发费时费力。

针对以上问题,我们将单体应用进行拆分,变成多个自成一体的模块,每个模块有各自自成体系的发布和运维等功能,由此解决了单体应用的弊端,将应用微服务化。当我们拆分出多个模块之后,各个模块需要统一的出入口,这里我们需要使用网关解决统一调用和接入问题。

在这样的背景之下,我们通过利用Kong这一开源API网关,将请求转发到上游服务之前,进行一系列的管理。

本文针对其核心应用,首先简要阐明Nginx、Openresty与Kong三者只间的关系,然后实际介绍如何使用Kong的插件机制来添加一个自定义插件。

1. 基本概念

Kong是一个开源的API网关,它是一个针对API的一个管理工具。你可以在那些上游服务之前,额外地实现一些功能。

Kong本身是一款基于OpenResty(Nginx + Lua模块)编写的高可用、易扩展的,由Mashape公司开源的API Gateway项目。Kong是基于NGINX和Apache Cassandra或PostgreSQL构建的,能提供易于使用的RESTful API来操作和配置API管理系统,所以它可以水平扩展多个Kong服务器,通过前置的负载均衡配置把请求均匀地分发到各个Server,来应对大批量的网络请求。

Nginx

Nginx是模块化设计的反向代理软件,由C语言开发,是多进程(单线程) & 多路IO复用模型(高并发)。

多进程

Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理这个连接。master 进程能监控worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动启动新的 worker 进程。一个请求,完全由 worker 进程来处理,而且只能在一个 worker 进程中处理请求。

多路复用模型

epoll通过在Linux内核中申请一个简易的文件系统,只要有 fd 上事件发生,epoll_wait() 就能检测到并返回给用户,用户就能”非阻塞“地进行 I/O 了。在内核,select中采用轮训的方法来查看是由有fd文件描述符准备好。在内核,epoll根据每个sockfd上面与设备趋同程序建立站起来的回调函数,当某个sockfd上的时间发生,与之对应的回调函数就会被调用。

Openresty

OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。Openresty中的 Ngx_Lua_Module 使得开发人员能够使用 Lua 脚本调动 Nginx 支持的各种模块,让 web 服务直接跑在 Nginx 内部。

Ngx_Lua_Module

把 Lua5.1 解释器 或 LuaJIT 2.0/2.1 解释器嵌入到 nginx 中,将 Lua 线程(Lua threads)与 nginx 事务模型(Nginx event model)结合,更改变子请求(subrequests)的处理过程。在 nginx 的一个 worker 里,所有请求共享一个Lua 解释器或 LuaJIT 实例,即一个 nginx worker,一个 Lua 解释器或 LuaJIT 实例。每个请求的上下文(context)是通过轻量级的 Lua 协程(coroutines)相互隔离的。

Kong

Kong 可以认为是一个 OpenResty 应用程序,而OpenResty 运行在 Nginx 之上,使用 Lua 扩展了 Nginx。Kong = OpenResty + Nginx + Lua

我们可以通过 HTTP Restful API 来动态管理 Kong 配置,8001是默认管理端口,8000/8443则分别是 Http 和 Https 的转发端口,我们可以通过 HTTP Restful 来动态管理Kong配置。

# 配置一个上游服务
curl -X POST http://localhost:8001/upstreams --data "name=helloUpstream" 

Kong插件机制

Kong具有极高的可扩展性,而它的高扩展性便来源于他的插件机制。

首先,先介绍如何在Kong中添加插件。

插件的作用范围非常灵活,可作用于一个服务或者路由之上,也可作用于整个Kong服务。我们可以为一个服务添加50次/秒的官方限流插件,通过如下所示的Restful API方式:

curl -X POST http://localhost:8001/services/hello/plugins \
--data "name=rate-limiting" \
--data "config.second=50" 

2. 开发Kong自定义插件

这里用添加一个名为key-auth-redis的自定义插件为例,详细介绍如何在kong开发一个自定义插件。

├── kong_components
│   └── kong_plugins
│       └── key-auth-redis
│           ├── handler.lua            # 请求生命周期
│           ├── access.lua            # 逻辑实现部分
│           ├── schema.lua            # 插件配置参数定义,或自定义校验函数
│           ├── migrations
│           │   ├── 000_base_qingke-auth.lua    # 数据库结构信息
│           │   └── init.lua                   # 初始化数据结构信息
 

首先,进入Kong_plugins目录,新建key-auth-redis的文件夹,并创建handler.lua文件和schema.lua文件,handler.lua文件中是插件主要的逻辑,需要继承baseplugin,根据不同阶段完成需要的逻辑。

Handler.lua 文件

local BasePlugin = require 'kong.plugins.base_plugin'
local access = require 'kong.plugins.key-auth-redis.access'
local AuthNotEncryption = BasePlugin:extend()

function AuthNotEncryption:access(conf)
    access.execute(conf)
end

AuthNotEncryption.PRIORITY = 1000
AuthNotEncryption.VERSION = '1.0.0'

return AuthNotEncryption
 

这里注意
AuthNotEncryption.PRIORITY 是插件执行顺序。AuthNotEncryption.VERSION是插件版本。local AuthNotEncryption= BasePlugin:extend(),Kong 的插件使用一个叫 Classic 的 class 机制。所有的插件都从 base_plugin.lua 基类上继承而来。base_plugin.lua 定义了插件在各个阶段被执行的方法名,我们在这里自定义变量AuthNotEncryption并继承baseplugin,定义了这个Kong插件在执行中调用方法顺序,最后return自定义变量。

Access.lua 文件

key-auth-redis这个插件需要访问redis数据库,进行访问用户鉴权,因此,我们只需要在访问上游服务器前执行该插件。为了达到这个操作,我们需要重写BasePlugin在访问上有服务之前的生命周期函数,完成对应的逻辑。

下表这里为Kong各个生命周期函数的具体描述。

通过此表,我们可以定位到想要实现key-auth-redis的功能,我们需要复写access方法。完成插件的大致逻辑如下。

function _M.execute(conf)

    local params
    local method = kong.request.get_method()
    if method == 'POST' then
        params = kong.request.get_body()
    else
        return Response.exit(100010, params.data_id)
    end
    if (params == nil) then
        return Response.exit(201500, "")
    end

    validate_params(params, conf)

    do_authentication(conf, cache, params)

end

return _M 

这里通过kong.request.get_body()获取访问带有参数,然后调用access.lua中带有的访问校验函数do_authentication。

Schema.lua 文件

schema.lua是插件在使用自定义配置参数的主要脚本。在schema文件中,我们可以进行对key-auth-redis插件中访问redis数据库的配置。

local typedefs = require 'kong.db.schema.typedefs'
local utils = require "kong.tools.utils"

return {
    name = 'key-auth-redis',
    fields = {
        {consumer = typedefs.no_consumer},
        {run_on = typedefs.run_on_first},
        {protocols = typedefs.protocols_http},
        {
            config = {
                type = 'record',
                fields = {
                    {redis_host = {type = 'string', default = '0.0.0.0'}},
                    {redis_port = {type = 'number', default = 6379}},
                    {redis_password = {type = 'string', default = ''}},
                    {redis_timeout = {type = 'number', default = 200000}},
                    {redis_connections = {type = 'number', default = 1000}},
                    {fault_tolerant = {type = 'boolean', default = true}},
                    {redis_database = {type = 'number', default = 0}},
                    {clock_skew = {type = 'number', default = 300, gt = 0}}
                }
            }
        }
    }
}
 

在field中,成员类型可以是stringbooleanarraynumbertimestamp,我们可以根据插件所需要的参数类型,进行参数配置。

到此为止,key-auth-redis插件代码部分已经介绍完毕。在完成代码修改后需要重启Kong,重启命令。

kong restart -c kong.conf --vv

然后,通过如下命令重启启动kong。

kong start 

PS:

我们是行者AI,我们在“AI+游戏”中不断前行。

快来【公众号 | xingzhe_ai】,和我们讨论更多技术问题吧!

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: