消除未缓存图像的冗余下载¶
包含您的 Launchpad 蓝图的 URL
https://blueprints.launchpad.net/glance/+spec/duplicate-downloads
当前,当 Glance API 节点处理的请求的镜像尚未缓存时,对该镜像的多次请求会导致从后端存储多次下载相同的镜像。例如,基于未缓存镜像的 1000 个并发构建请求可能导致从后端存储进行 1000 次下载请求。
问题描述¶
Feature: Elasticity
In order to briefly leverage the power of the Cloud to do some work,
As an OpenStack Powered Cloud customer leveraging Glance caching
I want to quickly provision a large number of servers, perform some
work, and then destroy them.
Scenario Outline: Concurrent Requests for Uncached Image
Given a single Glance API node
And the requested image exists in the backend store
And the requested image is uncached on the Glance API node
When <n> concurrent request(s) for the image is/are made
Then the image will be downloaded from the backend store <m> times
And the image will be cached on the Glance API node
And every request for the image will succeed
Examples: Concurrent Requests
| n | m |
| 1 | 1 |
| 2 | 1 |
Scenario: Concurrent Requests for Uncached Image Fails
Given a single Glance API node
And the requested image exists in the backend store
And the requested image is uncached on the Glance API node
When 2 concurrent requests for the image are made
And mid-download the client closes the first connection
Then only the first download request will fail
And the image will be cached on the Glance API node
Scenario: Stream to all requests while caching
Given a Glance API node (1) with this feature deployed
And a Glance API node (2) without this feature deployed
And the requested image exists in the backend store
And the requested image is uncached on Glance API node 1
And the requested image is uncached on Glance API node 2
When 2 concurrent requests are made to API node 1
And 2 concurrent requests are made to API node 2
Then the 2 requests to API node 1 will succeed
And the 2 requests to API node 2 will succeed
And the image will be cached on Glance API node 1
And the image will be cached on Glance API node 2
And the request completion time between the 2 requests to node 1
will be statistically less than or equal to
the request completion time between the 2 requests to node 2
提议的变更¶
目前,Glance 缓存中间件返回一个迭代器,仅当镜像已缓存时才从缓存中下载。如果镜像未缓存,则请求会传递给 API 以获取一个将直接从存储中下载的迭代器。包含此直接迭代器的响应会通过缓存中间件返回。如果中间件处理响应时镜像完全未缓存,它会将 API 的直接下载迭代器包装在另一个迭代器中,该迭代器将 Tee 到缓存(即从存储中读取,并通过分割管道同时写入客户端和缓存)。
因此,根据缓存的状态,可以返回三种迭代器之一:指向缓存的迭代器(如果镜像完全缓存)、指向存储的迭代器(如果镜像部分缓存),或者将数据从存储流式传输并写入缓存的 Teeing 迭代器(如果镜像完全未缓存)。这种方法存在竞争条件,可能导致许多响应直接从存储中下载,并且其中一部分将数据 Tee 到文件系统上的相同位置。
建议的解决方案是,对于第一次下载请求,我们不是将整个文件写入缓存,而是分块地将文件写入缓存。然后,后续的下载请求读取已写入的块。一旦后续请求完成读取缓存中所有可用的块,它将等待第一次请求写入缓存的下一个可用块。它将继续这样做,直到第一次请求完成所有块。
对于第一次请求
if the cache entry does not exist:
mark the image "caching"
create a new folder in the cache directory with the image id
take the iterator from the download (like we are doing now)
write the data in 1GB chunks to cache
upon finish, mark the image "cached"
对于后续请求
if the image is marked "caching" or "cached":
read the chunk from the cache until we get all the expected chunks
if a chunk is not available:
wait for it to be written by the first request
注意
注意:对于读取缓存镜像的每个块,缓存镜像的命中计数不应增加,而应仅在实际从缓存读取镜像的请求时增加一次。
备选方案¶
添加一个配置选项 `
eliminate_duplicate_downloads` 以启用此功能。为缓存中间件的行为添加配置选项会给操作员带来不必要的负担。缓存中间件应在不引入新的配置选项的情况下满足问题描述中概述的预期行为。 这种选项的唯一价值是允许该功能的逐步推广。如果达成共识要引入这样的选项,默认情况下禁用,那么在下一个版本中应该将其弃用并默认启用。为了避免在初始缓存请求失败的情况下将部分镜像流式传输到多个客户端,我们可以阻塞所有后续请求,直到镜像完全缓存在缓存中,然后仅从缓存提供这些请求。
这种方法会导致为其余客户端提供服务出现重大延迟,但可以节省带宽,尤其是在缓存因镜像或存储不可用而中断的罕见情况下。由于大型镜像可能存在非常长的延迟,这将使下载过程复杂化,因为需要客户端连接的某种保活机制来避免超时。
在中间件请求处理程序中创建一个锁:这可以防止请求到达根应用程序并在缓存中间件响应处理程序中争夺成为第一个发起缓存中下载的请求。但是,这会带来可靠性和复杂性的成本。需要在请求处理程序中实现逻辑来从请求和响应之间的故障中恢复。这花费了大量的精力,但收益却不大。
将缓存从中间件移动到根应用程序,并围绕缓存和下载提供锁定机制。这样做具有架构优势。但是,这是一项艰巨的任务,我认为任何关于此的讨论都应该完全超出此更改的范围。
将缓存从 Glance API 移动出去:这需要客户端逻辑和新的/外部缓存代码。
数据模型影响¶
无
REST API 影响¶
无
安全影响¶
无
通知影响¶
无
其他最终用户影响¶
参见其他部署影响
性能影响¶
并发请求的镜像请求时间将减少。
Glance API 节点和后端存储之间的带宽消耗将减少。
其他部署者影响¶
从缓存提供服务的每个请求都会影响可靠性和性能配置文件。后端存储和 Glance 之间的瓶颈将被消除,以解决“雷鸣蜂群”问题。但是,仍然可能存在超visor 和 Glance API 节点之间的瓶颈。
开发人员影响¶
无
实现¶
负责人¶
主要负责人:Mridula Joshi
评审人员¶
核心评审人:Erno Kuvaja
工作项¶
添加测试
更新驱动程序中的缓存方法
更新缓存请求处理程序
更新缓存响应处理程序
更新文档
依赖项¶
无
测试¶
单元测试
功能测试
文档影响¶
记录任何新的配置选项(如果有)。
参考资料¶
https://review.opendev.org/c/openstack/glance-specs/+/206120