gpt4 book ai didi

http - 存储资源 ETag 的建议方法是什么?

转载 作者:可可西里 更新时间:2023-11-01 15:21:08 27 4
gpt4 key购买 nike

我应该在哪里存储给定资源的 ETag?

方法 A:即时计算

获取资源并根据每个请求动态计算 ETag:

$resource = $repository->findByPK($id); // query

// Compute ETag
$etag = md5($resource->getUpdatedAt());

$response = new Response();
$response->setETag($etag);
$response->setLastModified($resource->getUpdatedAt());

if($response->isNotModified($this->getRequest())) {
return $response; // 304
}

方法 B:在数据库级别存储

在制作 INSERT 的同时节省一点 CPU 时间和 UPDATE语句有点慢(我们使用触发器来更新 ETag):
$resource = $repository->findByPK($id); // query

$response = new Response();
$response->setETag($resource->getETag());
$response->setLastModified($resource->getUpdatedAt());

if ($response->isNotModified($this->getRequest())) {
return $response;
}

方法 C:缓存 ETag

这类似于方法 B,但 ETag 存储在某些缓存中间件中。

最佳答案

我想这取决于将元素放入 ETag 本身的成本。

我的意思是,用户发送对给定资源的请求;这应该触发对数据库的检索操作(或其他一些操作)。

如果检索是简单的事情,例如获取文件,那么查询文件统计信息很快,并且不需要在任何地方存储任何内容:文件路径的 MD5 加上其更新时间就足够了。

如果检索意味着查询数据库,则取决于您是否可以在不损失性能的情况下分解查询(例如,用户通过 ID 请求文章。您可能仅从文章表中检索相关数据。因此缓存“命中”将需要对主键进行单个 SELECT。但是缓存“未命中”意味着您必须再次查询数据库,浪费第一个查询 - 或不 - 取决于您的模型)。

如果查询(或查询序列)可以很好地分解(并且生成的代码可维护),那么我会再次使用动态 ETag。

如果不是,则主要取决于查询成本和存储 ETag 解决方案的总体维护成本。如果查询开销很大(或输出很大)并且 INSERT/UPDATE 很少,那么(并且,我认为,只有这样)使用 ETag 存储辅助列(或表)将是有利的。

至于缓存中间件,我不知道。如果我有一个框架来为我跟踪一切,我可能会说“去吧”——中间件应该关心和实现上述要点。如果中间件与实现无关(不太可能,除非它是一个剪切和粘贴的耳光......这并非闻所未闻),那么它要么存在“筛选”资源更新的风险,要么在更新时调用一些缓存清除 API 过于笨拙。这两个因素都需要根据 ETag 支持提供的负载改进进行评估。

我不认为在这种情况下存在“银弹”。

编辑 :在您的情况下,情况 A 和 B 之间几乎没有区别,甚至没有区别。为了能够实现 getUpdatedAt(),您需要将更新时间存储在模型中。

在这种特定情况下,我认为 ETag(情况 A)的动态、显式计算会更简单、更易于维护。在任何情况下都会产生检索成本,而显式计算成本是 MD5 计算的成本,它非常快且完全受 CPU 限制。在我看来,可维护性和简单性方面的优势是压倒性的。

在半相关的说明中,我突然想到在某些情况下(对数据库的更新不频繁,对数据库的查询更频繁)实现全局 Last-Modified 可能是有利且几乎透明的。时间为 整个数据库 .如果数据库没有改变,那么无论查询是什么,对数据库的任何查询都无法返回不同的资源。在这种情况下,只需要存储 Last-Modified全局标志在一些容易和快速检索的地方(不一定是数据库)。例如

function dbModified() {
touch('.last-update'); // creates the file, or updates its modification time
}

在任何 UPDATE/DELETE代码。资源 would then add a header
function sendModified() {
$tsstring = gmdate('D, d M Y H:i:s ', filemtime('.last-update')) . 'GMT';
Header("Last-Modified: " . $tsstring);
}

通知浏览器该资源的修改时间。

然后,对资源的任何请求,包括 If-Modified-Since可以在不访问持久层(或至少保存所有持久资源访问)的情况下用 304 返回。不需要(必须)记录级别的更新时间:
function ifNotModified() {
// Check out timezone settings. The GMT helps but it's not always the ticket
$ims = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])
: -1; // This ensures the test will FAIL

if (filemtime('.last-update') <= $ims) {
// The database was never updated after the resource retrieval.
// There's no way the resource may have changed.
exit(Header('HTTP/1.1 304 Not Modified'));
}
}

可以将 ifNotModified() 调用尽可能早地放在资源供应路径中,尽可能早地将 sendModified 放在资源输出代码中,而 dbModified() 就资源而言,只要数据库发生重大修改(即,在将访问统计信息记录到数据库时,您可以并且可能应该避免它,只要它们不影响资源的内容)。

关于http - 存储资源 ETag 的建议方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12049642/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com