0x00 本文目的: 网关层合并并发请求
有这样一种场景:
当用户打开点餐类的网页, 需要展示如下信息:
- 商家信息
- 菜品列表
- 好评列表
一般的做法, 就是分开三个接口, 让客户端发请三次api请求即可完成.
那么请问如何优化这种场景呢?
今天就提供一个解决思路:
- 合并请求
减少请求次数,肯定可以提高客户端的响应速度
但是, 这里说的合并请求, 不是指在一个接口处理内,读取数据库三次哦- 网关层并行请求
假设后端服务有三个微服务分别提供上述三种信息.那么我们在网关层同时请求三个后端服务, 然后在网关层完成信息整合, 最后返回给客户端结果.如此一来, 相当于我们同时做了两件优化项了.
0x01 后端接口准备
我们先准备一个后端接口:
功能很"复杂": 完成输入参数的平方计算, 并返回结果.
然后, 分别部署到 9000
和 9001
的端口服务中:
@RequestMapping("/square")
public int sum(@RequestParam("value") int value) {
return value * value;
}
部署后, 请在服务器上执行并验证接口可用性:
接口准备
0x02 添加Service, Router
我们添加一个请求Router, 访问地址为aaa.com/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翌日, 新しい時代が始まった
网友评论