我正在实施一个应用程序,它可以对我们也控制的rest-api进行大量的网络调用。最近我们决定在服务器端引入缓存头,以节省一些宝贵的网络和服务器时间。由于我们事先不知道数据有效期多长,我们不会发送Cache-control: max-age
或Expires
标头,我们所做的只是发送Last-Modified
标头和{{1}所以我们总是点击服务器,但是大多数情况下使用E-tag
的响应非常快。
一开始似乎一切正常,许多请求都被缓存了。但是,由于缓存,我在应用上遇到了一些随机数据错误。
出于某些原因,我无法理解,在某些时候,请求被本地缓存并用作“更新”数据,而不是命中服务器,而实际上并非如此。问题一直存在,直到一段时间过去。然后,所有内容都会再次正常运行到服务器,就像使用304
标头一样,但没有它!所以,我的问题是:
当cache-control
或NSURLCache
标头未附带原始请求时,NSURLConnection
与Cache-control: max-age
一起决定某个特定请求无需上线的情况如何?有谁经历过类似的影响?如何在不删除整个缓存的情况下解决它?
更多背景信息:
Expires
所以我没有
认为它改变了什么NSURLConnection
实例这是[NSURLCache sharedURLCache]
请求,当我从缓存的响应中检查标头时,这就是我得到的:
GET
po [response allHeaderFields]
我无法预测或重现何时会发生错误,因此无法选择依赖删除缓存的解决方案。
答案 0 :(得分:4)
NSURLCache如何与NSURLConnection一起决定a 当...时,特殊要求不需要上线。
RFC 2616第13.2节说:
由于源服务器并不总是提供明确的到期时间, HTTP缓存通常分配启发式到期时间,使用 使用其他标头值的算法(例如Last-Modified 时间)估计合理的到期时间。 HTTP / 1.1 规范没有提供具体的算法,但确实强加了 对结果的最坏情况限制。自启发式到期 时间可能会损害语义透明度,他们应该使用它们 谨慎,我们鼓励原始服务器提供明确的 到期时间尽可能多。
因此,即使您没有为数据提供特定的生命周期,URL加载系统也可以确定缓存的数据“足够新鲜”。
为获得最佳效果,您应尝试在响应标头中提供特定的生命周期。如果无法添加这样的标头,也许您可以改变请求。 if-modified-since
或cache-control
可以帮助您避免缓存数据。
答案 1 :(得分:2)
根据声明“在某些时候,请求被本地缓存并用作”更新“数据而不会访问服务器”我很确定您的请求是内存缓存的。
NSURLCache将数据缓存在内存中。不在磁盘上所以让我解释一下你可能会发生什么。
您启动了该应用。 进行Web服务调用 它从服务器获取数据 你再次拨打电话,它从内存中获取响应而不调用服务器并显示结果。
您离开应用程序一段时间或重新启动应用程序。它会检查数据是否在内存中。如果它不可用,那么它再次调用服务器并重复相同的行为。
我建议您为自己编写自己的磁盘缓存,而不是依赖NSURLConnection和NSUrlCache。因为某些缓存策略还没有从Apple实现。
答案 2 :(得分:2)
请确保您的NSURLRequest缓存策略设置为NSURLRequestReturnCacheDataElseLoad
如果你在AFHTTPClient.m中使用AFNetworking,你可以覆盖方法
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
path:(NSString *)path
parameters:(NSDictionary *)parameters
用这个
替换第470行 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:15];
你实际做的是告诉加载缓存的请求如果服务器没有更新..如果服务器更新,那么它将忽略缓存并从服务器下载内容
仅供参考:NSURLCache将数据存储在内存中。如果您想将数据存储在光盘中,可以在此处使用我的课程