Kong[nginx]-15 玩转ngx.location.capture


KONG专题目录


需求:
简单的说: API网关接收到客户端请求后, 要求立即返回结果.

具体案例: 客户端只负责把数据上报到服务器, 但并不关心处理结果.
如果这时候, 后端处理速度比较慢, 客户端会一直等在这里, 这个体验不是太好.

本文要展示的内容, 就是通过Kong来解决这个问题.

0x01 前提

本文涉及下述技术点, 如果有不太熟悉的地方, 请抱着看电影的心态观看本文.

  • nginx 基本配置
  • openresty lua 脚本
  • kong 的配置和使用

0x02 解决思路

本以为,在 access() 方法中, 调用kong.response.exit()方法给客户端返回结果后, 就可以执行后续调用操作, 但是这种方法并不可行.

This function interrupts the current processing and produces a response. It is typical to see plugins using it to produce a response before Kong has a chance to proxy the request (e.g. an authentication plugin rejecting a request, or a caching plugin serving a cached response).
此方法会中断当前请求, 并生成一个响应. 主要用于请求验证等行为.

那么, 也就是说 kong开头的对象(方法)已经不能解决问题了, 那么我们就要使用openresty中大量ngx开头的方法了.


经调查, 我们把目光集中到了 ngx.location.capture方法上.
官方介绍如下:

syntax: res = ngx.location.capture(uri, options?)
context: rewrite_by_lua, access_by_lua, content_by_lua*
Issues a synchronous but still non-blocking Nginx Subrequest using uri.
Nginx's subrequests provide a powerful way to make non-blocking internal requests to other locations configured with disk file directory or any other nginx C modules like ngx_proxy, ngx_fastcgi, ngx_memc, ngx_postgres, ngx_drizzle, and even ngx_lua itself and etc etc etc.
发起一个异步非阻塞子请求.
使用子请求时,支持OOXX种内部请求方式.

解释一下上面的意思 : 在使用上面的方法时, 第一个参数只能是内部请求.
这里的内部请求是特指nginx配置文件中的internal 路由.

可能不少小伙伴听的云里雾里, 那么,我们直接上代码吧..

这里介绍一下kong中的nginx.conf 文件修改方式:

千万不要直接去修改 /urs/local/kong/*.conf 文件, 因为 kong restart时会重新生成一套配置文件, 会把他们盖掉.

正确做法如下:

  • 如果是添加一个完整的 server节点的配置文件my.conf
    • 需要在 /etc/kong/kong.conf 中添加nginx_http_include=/etc/kong/my.conf
  • 如果想修改/usr/local/kong/nginx-kong.conf中部分内容
    • 请修改kong的模板文件 /usr/local/share/lua/5.1/kong/templates/nginx_kong.lua

OK, 我们在模板文件中, 添加一个内部请求定义:

cd /usr/local/share/lua/5.1/kong/templates/
vim nginx_kong.lua 

# 在 location = /kong_error_handler 这一行的上面添加下面内容
        location /internal_api {
              internal;
              set_by_lua $query_url 'return ngx.unescape_uri(ngx.var.arg_url);';
              proxy_pass $query_url;
        }   
修改nginx_kong.lua

0x03 测试用Java代码

我们准备一个测试用的SpringBoot应用, 并且写一个接口: 5秒延时后返回处理结果.

    @RequestMapping("/fast")
    public String getSlow() {
        System.out.println("start");
        try {
            Thread.sleep(5000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("end");
        return "Slow Done";
    }

留意一下, 接口执行时, 会在控制台 打印 start,end字样

0x04 配置Service

按照我们以前学过的知识 , 在 aaa.com上, 添加一个路由/slow

添加路由/slow

0x05 编写插件

直接上插件代码:

  • handler.lua
-- handler.lua
local BasePlugin   = require "kong.plugins.base_plugin"
local GGHandler    = BasePlugin:extend()

GGHandler.VERSION  = "1.0.0"
GGHandler.PRIORITY = 10

function GGHandler:access(config)
    kong.log("kong - start")

    -- 向客户端返回结果
    ngx.say([[ hello world]])
    -- 这里会结束与客户端的 socket连接
    ngx.eof()

    -- nginx内部接着执行子请求, 无视结果
    ngx.location.capture("/internal_api", {
        copy_all_vars = true,
        args          = { url = "http://127.0.0.1:9000/fast" },
        method        = ngx.HTTP_GET,
    })
    kong.log("kong - end")
end

return GGHandler

  • schema.lua
local typedefs     = require "kong.db.schema.typedefs"

return {
  name   = "fast-response",
  fields = {
    { protocols = typedefs.protocols_http },
    { config = {
      type   = "record",
      fields = { },
    },
    },
  },
}

0x06 验证

这种测试只有动图才有说服力, 一图胜千言 : )


测试效果

这一篇的应用场景有点冷门, 不过还是一句话: API网关真的可以有很多玩法.
供参考


KONG专题目录


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容