网关系统 apisix/kong 日志收集方案实施对比
目前在一个核心服务上应用一个网关系统,并后期推广升级
网关调研方向包括spring,kong apisix,java栈的netty由于一些原因,不适合应用方向
同时考虑云原生的友好程度,简单说是否有配套的k8s ingress和k8s能使用同一套方案,减少技术团队整体的学习和使用成本,主要考虑kong和apisix
kong + konga + kong ingress 个人深度使用了有3年多,整体比较满意
k8s平台集成kong ingress 布署konga集成ui - 博客园 (cnblogs.com)
apisix官方和kong的性能对比,实际是比较的kong1.0,个人对apisix和kong的性能对比是有点疑问的,只不过一般的业务流量,所以在kong能满足要求的前提下,对apisix只是有限了解
目前为加强基础架构对各上层应用的全局支持,需要添加对request_body的请求日志收集,基础的nginx都能做到这点,也许是kong的处理流程上做了较大调整,kong 官方居然不支持
官方插件库 Kong Hub | Plugins and Integrations | Kong Docs (konghq.com)
1 首先官方的log类插件并不能简单便捷的添加对request_body的收集
HTTP Log plugin | Kong Docs (konghq.com)
kong 免费版本提供的log相关插件,都不支持对request_body的收集上报
kong 插件上报一部分,再通过更改kong相关的nginx配置生成一部分,两部分用flink做大数据处理双流join实现,该方案不优雅
考虑直接通过kong 插件收集
准备找找有没有第三方的方案,有必要的的话需要自己参照kong的官方插件写插件了
整体看了下难度倒是不大,个人以前搞openwrt路由器luci时有点lua的开发经验 lua https request 调用 - 博客园 (cnblogs.com)
2 日志处理收集,写入kafka的场景较为典型,通常结合大数据spark streaming/flink 做流式计算
https://docs.konghq.com/hub/kong-inc/kafka-log
kong 官方插件库提供kafka 的日志收集,但是收费,同时有不能简易收集request_body的问题
3 Kafka Upstream plugin | Kong Docs (konghq.com)
kong 有一个专门的上报kafka组件,
--data "config.forward_body=true" 简单看了遍文档,这个插件支持对request_body的日志收集,该组件也同样收费
log类插件不支持request_body,kafka在日志收集上的应用,再看看这个收费插件,大概明白官方为什么没有把request_body做在免费插件里了
在log插件代码基础上加上request_body 还算简单,但在没有官方代码参照的基础上(这些代码官方未开源),实现写kafka 难度和工作量会大很多,可以用多级上报,结合filebeat,logstash,prometheus之类的实现
基础功能足够日常使用,收费功能有效,但预算有限,因此转头看看其他方案有没有替代,比如apisix
apisix 目前全开源,比较合胃口,开源则对一些官方不支持的特性做定制化开发比较方便,kong也开源了,但插件类同样只开源了免费的部分
apisix官方插件库
apisix/apisix/plugins at release/2.11 · apache/apisix (github.com)
请求日志收集至kafka
apisix/kafka-logger.lua at release/2.11 · apache/apisix (github.com)
看代码,支持对request的收集
include_req_body = {type = "boolean", default = false},
include_req_body_expr = {
type = "array",
minItems = 1,
items = {
type = "array",
items = {
type = "string"
}
}
}
并未用kong2.0和apisix做基础性能对比,但就日志request_body收集功能上,apisix和kong 基础免费版,apisix强于kong
因此网关系统开始部分从kong迁移转至apisix
以下是部分测试验证的细节,启动log-kafka插件收集
{
"broker_list": {
"192.168.11.22": 9092,
"192.168.11.23": 9092,
"192.168.11.24": 9092
},
"kafka_topic": "test_apisix",
"key": "key1",
"batch_max_size": 1,
"name": "kafka logger",
"include_req_body":true,
"meta_format":"default",
"log_format":""
}
meta_format支持两种格式,为收集解析方便使用"default"
样例日志
{
"start_time": 1638185753246,
"client_ip": "172.17.0.1",
"latency": 0,
"service_id": "127.0.0.1",
"server": {
"hostname": "fe053d1baf4a",
"version": "2.9"
},
"response": {
"status": 404,
"headers": {
"server": "APISIX/2.9",
"connection": "close",
"transfer-encoding": "chunked",
"content-type": "text/plain; charset=utf-8"
},
"size": 223
},
"request": {
"headers": {
"host": "127.0.0.1:8280",
"user-agent": "curl/7.29.0",
"accept": "*/*"
},
"method": "GET",
"size": 83,
"url": "http://127.0.0.1:9080/hello",
"querystring": {},
"uri": "/hello"
}
}
自定义格式
curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/kafka-logger -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"log_format": {"host": "$host", "@timestamp": "$time_iso8601", "client_ip":"$remote_addr","request_id":"$request_id","request_length":"$request_length","request_time":"$request_time","header_test_1":"$http_nothas","header_test_1":"$http_x-api-key","body":"$request_body"}
}'
apisix从测试和查看源码上看,也有些待优化的点
1 "default"格式完全默认无法自定义,如果需要nginx原生的一些信息,则需要使用log_format
defautl信息为目前为硬编码,如果需要一些别的信息,需要直接修改代码
https://github.com/apache/apisix/blob/2.10.1.1/apisix/utils/log-util.lua
default格式实现,和上面的demo对应
local log = {
request = {
url = url,
uri = var.request_uri,
method = ngx.req.get_method(),
headers = ngx.req.get_headers(),
querystring = ngx.req.get_uri_args(),
size = var.request_length
},
response = {
status = ngx.status,
headers = ngx.resp.get_headers(),
size = var.bytes_sent
},
server = {
hostname = core.utils.gethostname(),
version = core.version.VERSION
},
upstream = var.upstream_addr,
service_id = service_id,
route_id = route_id,
consumer = consumer,
client_ip = core.request.get_remote_client_ip(ngx.ctx.api_ctx),
start_time = ngx.req.start_time() * 1000,
latency = (ngx_now() - ngx.req.start_time()) * 1000
}
#默认的default格式
_M.get_full_log = get_full_log
#自定义全局格式
_M.get_custom_format_log = get_custom_format_log
2 log_format目前是全局生效的,即全局只能有一种log_format格式,若想对不同的路由配置不同的规则,则作不到
3 可以通过修改 https://github.com/apache/apisix/blob/2.10.1.1/apisix/utils/log-util.lua default格式的log内容,很简单
apisix满足网关的性能和日志收集需求