apisix源码分析- 插件 prometheus 支持

apisix源码分析- 插件 prometheus 支持

用到的库 https://github.com/knyar/nginx-lua-prometheus

apisix/prometheus/exporter.lua

变量 metrics 用来定义指标,

prmetheus_keys

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
KeyIndex.new(shared_dict, prefix)
self.dict = shared_dict
self.key_prefix = prefix .. "key_"
self.delete_count = prefix .. "delete_count"
self.key_count = prefix .. "key_count"
self.last = 0
self.deleted = 0
self.keys = {}
self.index = {}

KeyIndex:sync()
获取 dict delete_count 和 dict key数量 N
如果本地的 delete 和 delete_count 不同,说明有删除
执行 sync_range(0,N)
如果当前的 last 和 N 不同说明有更新,那么执行 sync_reange(N,last)
并返回 N

KeyIndex:sync_range(first, last)
从 dict 同步 first 到 last 区间的内容到当前对象
从 dict 获取 keyi
记录映射关系 keys[i] = key ,index[key]=i
如果 keyi 是不存在的,从映射关系删除内容

KeyIndex:list()
执行同步 sync()
并返回 keys 的 copy

KeyIndex:add(key_or_keys, err_msg_lru_eviction)
对每一个 key 执行:
同步并获取N
如果 key 存在,就跳过
如果 key 不存在就设置 dict N+1 为 key
key_count ++
设置 keys 和 index

KeyIndex:remove(key, err_msg_lru_eviction)


总结:
利用 dict 存储数据,利用 sync 将数据同步到 worker 进程的函数

prometheus

ngx.sleep(0)

OpenResty 中的 ngx.sleep(0) 调用会主动放弃当前的 CPU 执行权,而把执行权交还给 nginx 事件循环和其他并发请求。当前
yield 了的 Lua 协程会在下一个 nginx 事件处理周期里接着继续运行。

一个典型应用:

shared-dict怎样实现不阻塞nginx进程?每分钟刷新一次缓存,刷新的时候,几十秒,nginx无反应,单个进程100%,其他进程没事,但是也无反应,好像访问的时候也到这个100%的进程了,导致无反应。

解决方法是:可以在操作中穿插一些 ngx.sleep(0) 用来让其他协程获得运行机会。

prometheus 里有大量的调用 dict ,执行 reload 后大量的同步会导致阻塞。

init:

dict : 原始全局字典


_counter : 用来记录 worker 计数器,并同步到dict


key_index: 用来将dict key 同步到 worker 中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
register(self, name, help, label_names, buckets, TYPE_HISTOGRAM)
构建指标需要的数据,对传入的name 去掉 _bucket _sum _count 的后缀
当为 historgram 时 name 或 name_maybe_historgram 存在
当为其他时, name 或者加入了后缀的存在都认为是指标存在,返回错误。
label_names :label 名列表
label_count: label 数量
lookup = {} :用table 来存储指标树
例如 ['me.com']['200'][LEAF_KEY] = 'http_count{host="me.com",status="200"}'

yield :执行读写 dict 次数 200 次就释放一次 cpu 时间片占用

lookup_or_create(self, label_values)
返回完整的指标名 counter 和 gauge 直接返回字符串
histogram 返回 list
如果 lookup_size > lookup_max_size ,清空 lookup
inc_gauge: dict incr


用特权进程来提供服务

想办法让指标就是排好序

https://mp.weixin.qq.com/s/guR77q6kXxpGfKzT46GYsg

  1. 指标名存储到对应的 table 树里面,定时同步
  2. 输出只有循环和取 dict

apisix源码分析- 插件 prometheus 支持

https://beixiu.net/apisix-plugin-prometheus/

作者

张巍

发布于

2023-08-25

更新于

2023-08-25

许可协议

评论