美文网首页API网关Kong实践笔记
Kong[nginx]-16 玩转ngx.location.ca

Kong[nginx]-16 玩转ngx.location.ca

作者: 国服最坑开发 | 来源:发表于2019-08-17 10:48 被阅读5次

    KONG专题目录


    0x00 本文目的: 网关层合并并发请求

    有这样一种场景:
    当用户打开点餐类的网页, 需要展示如下信息:

    • 商家信息
    • 菜品列表
    • 好评列表

    一般的做法, 就是分开三个接口, 让客户端发请三次api请求即可完成.

    那么请问如何优化这种场景呢?

    今天就提供一个解决思路:

    • 合并请求
      减少请求次数,肯定可以提高客户端的响应速度
      但是, 这里说的合并请求, 不是指在一个接口处理内,读取数据库三次哦
    • 网关层并行请求
      假设后端服务有三个微服务分别提供上述三种信息.那么我们在网关层同时请求三个后端服务, 然后在网关层完成信息整合, 最后返回给客户端结果.

    如此一来, 相当于我们同时做了两件优化项了.

    0x01 后端接口准备

    我们先准备一个后端接口:
    功能很"复杂": 完成输入参数的平方计算, 并返回结果.
    然后, 分别部署到 90009001 的端口服务中:

        @RequestMapping("/square")
        public int sum(@RequestParam("value") int value) {
            return value * value;
        }
    

    部署后, 请在服务器上执行并验证接口可用性:


    接口准备

    0x02 添加Service, Router

    我们添加一个请求Router, 访问地址为aaa.com/cal

    /cal

    0x03 编写插件

    编写这个插件前, 会用到上一篇里提到的 /internal_api 这里不太赘述.
    结合ngx.location.capture_multi API, 我们可以写出如下的代码:

    • 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)
    
        local a = kong.request.get_query_arg('a') or 0
        local b = kong.request.get_query_arg('b') or 0
        kong.log('a = ' .. a .. ' ,b = ' .. b)
    
        -- nginx内部接着执行子请求
        local rst1, rst2 = ngx.location.capture_multi {
            { "/internal_api",
              {
                  args   = { url = "http://127.0.0.1:9000/square?value=" .. a },
                  method = ngx.HTTP_GET,
              }
            },
            { "/internal_api",
              {
                  args   = { url = "http://127.0.0.1:9001/square?value=" .. b },
                  method = ngx.HTTP_GET,
              }
            },
    
        }
        -- 两个子请求执行完了 才会执行到这里
        kong.log('rst1  = ' .. rst1.body)
        kong.log('rst2  = ' .. rst2.body)
    
        local sum = 0
    
        if rst1.status == ngx.HTTP_OK then
            sum = sum + tonumber(rst1.body)
        end
    
        if rst2.status == ngx.HTTP_OK then
            sum = sum + tonumber(rst2.body)
        end
    
        kong.log('rst = ' .. sum)
        return kong.response.exit(200, tostring(sum), {
            ["Content-Type"] = "text/plain"
        })
    end
    
    return GGHandler
    
    • schema.lua
    local typedefs     = require "kong.db.schema.typedefs"
    
    return {
      name   = "multi_req",
      fields = {
        { protocols = typedefs.protocols_http },
        { config = {
          type   = "record",
          fields = { },
        },
        },
      },
    }
    

    0x04 启用插件

    这个技能我们已经使用过很次, 不知道的同学请查看前面的系列.
    发布插件三步走即可完成:

    • 插件代码复制到指定目录
    • 修改 /etc/kong/kong.conf
    • kong restart

    添加插件 添加完成

    0x05 验证效果

    我们在浏览器发启请求: http://aaa.com/cal?a=3&b=4
    就可以看到插件日志 和 最后的返回结果.

    插件日志 执行结果

    0x06 后记

    本文提供了一个新的脑洞:
    一次网关输入请求, 可以向多个后端(接口)发起请求.

    但是, 也有其不足的地方:
    已知问题: 这些子请求一定要都有返回结果后, 才会向客户端返回结果 .
    也就是说, 可能会由于其中一个接口超时或者故障,可能导致整个请求失败!!!


    2019.8.16翌日, 新しい時代が始まった


    KONG专题目录


    相关文章

      网友评论

        本文标题:Kong[nginx]-16 玩转ngx.location.ca

        本文链接:https://www.haomeiwen.com/subject/qxlhsctx.html