缓存 mgr 模块

简介 ¶
一段时间以来,与 mgr 守护进程的可扩展性以及仪表板、prometheus、pg_autoscaler、orchestrators 等等类似 python 模块的紧密耦合结构相关的问题一直出现。
集群数据是按需由模块请求的,以便每隔一段时间更新这些模块中的集群状态。例如,仪表板会定期请求健康数据更新到守护进程,以显示集群是否正常。
在数据结构方面,存在可扩展性问题。例如,OSD 可以增加到数千个,因此,像 OSDMap 这样的结构会按比例增加大小,从而增加模块在尝试检索最新数据时的延迟。
添加缓存层 ¶
关于如何解决此问题已经进行了一些讨论,但我们同意缓存的 mgr 可以通过减少在这些问题上受苦的大型集群上的延迟来提供帮助。
大致来说,mgr 模块的连接方式如下

如您所见,守护进程保存了集群的大部分映射。当请求某些内容时,例如 get('osd_map'),它将开始将 OSDMap 转换为带有我们称之为 Formatters (在此例中为 PyFormatter) 的 PyObject。缓存 PyObject 比较困难,因为我们需要为每个 python 模块创建一个副本,因此,我们使用了一种更简单的方法,即将结构转换为 json (使用 JsonFormatter),我们只需要担心序列化和反序列化。
在 json 序列化到位后,添加了模块和守护进程之间的共享 TTL 缓存

并非所有内容都像图中显示的那样被缓存,但大多数存在问题的情况都是如此。使用 JSON 进行序列化本身并没有带来很大的改进,但是,如果我们缓存序列化的对象,我们看到 在 3000 个 osd 上,性能提升了 2.8 倍。
在以下折线图中,清楚地区分了当前行为以及带有 json 序列化的缓存。这些基准测试是通过对每个 osd 数量请求 OSDMap 5000 次来运行的。结果如下

蓝色的虚线表示检索 osdmap 的延迟改进,黑线是通常的行为,蓝线是未使用缓存 json 对象的结果。
此外,该缓存在 master/quincy 中可用,并很快将被回移植到 pacific。可以通过运行以下命令启用它
ceph config set mgr mgr ttl_cache_expire_seconds 10
这将为每个缓存对象设置 10 秒的生存时间。
结论 ¶
在禁用缓存的情况下,通常的行为仍然更快;然而,我们看到在更大的集群上启用缓存并使用像 json 这样的简单序列化工具时,性能提升了近 3 倍。
mgr 守护进程一直没有得到很好的维护,需要进行很多改进才能拥有更具可扩展性的 mgr。此缓存是一种可以减轻部分工作负载的改进,但仍有更多的工作需要完成,以解决可扩展性、调试能力、子解释器……敬请期待!