深入分布式缓存

可以缓存我 (Cache Me If You Can)

About 2 years ago, I remember witnessing a reunion that had a profound impact on my software developer life.

大约2年前,我记得一次聚会对我的软件开发人员的生活产生了深远的影响。

The client, a former developer with decades of experience, a tech savvy product owner and another senior developer were talking about a caching problem. The API was answering stales video fragments that caused clients to view the wrong content.

该客户是一位具有数十年经验的前开发人员,精通技术的产品所有者以及另一位高级开发人员,他们在谈论缓存问题。 该API正在回答过时的视频片段,这些片段导致客户端查看错误的内容。

It was bad. Really bad.

这不怎么样。 特别糟糕。

Although nobody knew what to do to fix the problem, they all seemed to agree on one thing. The problem was most likely a caching problem.

尽管没有人知道如何解决该问题,但他们似乎都同意一件事。 该问题很可能是缓存问题。

I didn’t know a thing about HTTP caching back then, so all I could do was listen to them arguing about what could have possibly gone wrong. And all of them had a different explanation.

我不知道一个 HTTP缓存当年的事情 ,所以我所能做的就是听他们争论什么能有可能出错。 他们都有不同的解释。

“Browsers deviate from the specs !” the client said. “The CDN override our caching directives!” the tech product owner thought. “We need to invalidate the whole cache” the tech lead replied.

“浏览器偏离规范!” 客户说。 “ CDN会覆盖我们的缓存指令!” 科技产品所有者认为。 技术负责人回答说:“ 我们需要使整个缓存无效 。”

Since I wanted to be helpful too, even though I wasn’t exactly sure how, given my level of understanding, I started asking questions to my fellow coworkers.

由于我也想提供帮助,即使我不确定自己的理解水平如何,我也开始向同事问问题。

I remember very well the level of confidence everyone seemed to have when answering my questions. Everyone acted like they knew what HTTP caching was all about. But at the same time, all their answers felt really vague and shallow. It was really like everybody had this high level of understanding of how things worked, but nobody wanted to get into the details.

我非常记得,每个人在回答我的问题时似乎都充满信心。 每个人的举动就像他们知道HTTP缓存的全部内容一样。 但与此同时,他们所有的答案都感到非常模糊和肤浅。 确实每个人都对事物的运作方式有很高的了解,但是没有人想深入细节。

Eventually, the problem magically fixed itself and the team was pretty satisfied with how things worked out.

最终,问题神奇地解决了,团队对事情的进展感到非常满意。

But I was not.

但是我不是。

I thought to myself, what just happened these past few days? Why is it that nobody was willing to admit that they don’t have a clue on how this whole caching thing works? Is it the curse of the software developer to always be tempted to pretend that we know more about a subject than we actually do?

我心想,这几天发生了什么? 为什么没有人愿意承认他们对整个缓存工作原理一无所知? 总是假装我们比实际了解更多的知识是软件开发人员的诅咒吗?

So I decided to check it out for myself. And I somewhat understood why everybody was pretending. The subject was by no means easy. But I was determined to go to the bottom of this.

所以我决定亲自检查一下。 我有点理解为什么每个人都假装。 这个话题绝非易事。 但是我决心要深入探讨这一点。

And that’s how what was supposed to be a few hours of Googling turned out to be months of reading articles, meditating on the specs, and experimenting with caching softwares.

这就是原来应该花几个小时的Googling历时数月的阅读文章,沉思规范以及尝试使用缓存软件的过程。

Fast forward today, I now realize that web performance (of which HTTP caching is one of the most important aspects) is a topic on which we are not trained enough. Too few articles talk about it, and most of them don’t go deep enough.

今天快进,我现在意识到Web性能(HTTP缓存是最重要的方面之一)是一个我们尚未受过足够培训的主题。 谈论这个话题的文章很少,而且大多数文章还不够深入。

The following articles are my attempt to rectify that by sharing everything I have learned during the past two years about HTTP caching.

以下文章是我尝试通过分享过去两年来我学到的有关HTTP缓存的所有知识来纠正这一问题。

I’m not a caching expert, and I won’t turn you into one. But it will hopefully give you a strong understanding of how things actually work.

我不是缓存专家,也不会把您变成一个缓存专家。 但是希望它将使您对事物的实际运行方式有深刻的了解。

让我们开始吧 (Let’s Get Started)

This series of articles deals with caching in the context of HTTP. When properly done, caching can increase the performance of your application by an order of magnitude.

本系列文章讨论了HTTP上下文中的缓存。 正确完成后,缓存可以将应用程序的性能提高一个数量级。

On the contrary, when overlooked or completely ignored, it can lead to some really unwanted side effects caused by misbehaving proxy servers that, in the absence of clear caching instructions, decide to cache anyway and serve stale resources.

相反,如果忽略或完全忽略它,则可能导致代理服务器行为异常,从而导致某些真正有害的副作用,这些代理服务器在没有明确的缓存指令的情况下仍然决定缓存并提供过时的资源。

Before we get to the tactical details of how caching works, it helps to understand the context and the landscape of the problem we are up against. For this reason, the first part of this series covers where caching should happen and why we need it.

在我们获得有关缓存如何工作的战术细节之前,它有助于了解我们所面对的问题的背景和情况。 因此,本系列的第一部分介绍了应该在哪里进行缓存以及为什么需要缓存。

Without further ado, let us start with an overview of key considerations to keep in mind when dealing with HTTP caching, and to a lesser extent, with web performance in general.

事不宜迟,让我们从概述HTTP缓存时要记住的主要注意事项入手,并在较小程度上谈及Web性能。

到处缓存 (Caching everywhere)

浏览器 (Browsers)

Caching is a very popular technique. The idea is indeed pretty appealing: no matter how long the I/O request, how CPU-intensive the computation, or any other programming task, it is always the same: storing the result somewhere and retrieving it as it is, for its further application.

缓存是一种非常流行的技术。 这个想法确实很吸引人:无论I / O请求多长时间,CPU占用大量计算或任何其他编程任务,它始终是相同的:将结果存储在某个位置并按原样检索,以供进一步使用应用。

Taking the example of browser’s HTTP cache that all browsers implement, web resources are stored on the user’s filesystem. Hence further requests that will access these same resources will have them delivered instantly.

以所有浏览器都实现的浏览器HTTP缓存为例,Web资源存储在用户的文件系统中。 因此,访问这些相同资源的其他请求将使它们立即交付。

No network request, no client/server round-trips, no database access, and so on. Can you think of any performance enhancement that would yield better results than no latency at all and complete server offloading? That’s simply not possible.

没有网络请求,没有客户端/服务器往返,没有数据库访问,等等。 您能想到任何性能增强将带来比没有延迟和完全卸载服务器更好的结果吗? 那根本不可能。

One might think that this situation is too ideal and impractical. If it were true, how come most pages don’t load that fast? One reason for this is because, even though all web resources are cacheable, they should not be cached the same way.

有人可能认为这种情况过于理想和不切实际。 如果属实,那么为什么大多数页面加载速度都不那么快? 原因之一是,即使所有Web资源都是可缓存的,也不应以相同的方式对其进行缓存。

HTML files for example, which are the first to be downloaded and that contain references to other assets, are notoriously dangerous to cache. Therefore, they’re unlikely to find their way to browser caches except for a few minutes at most, as we shall see in a moment.

例如,HTML文件是第一个要下载的文件,其中包含对其他资产的引用,因此缓存非常危险。 因此,除了我们最多会看到的几分钟之外,他们不太可能找到通往浏览器缓存的方法。

But another possible explanation, one that we find more likely based on our experience, is that caching policies are often completely left out for web servers to decide.

但是,另一种可能的解释(根据我们的经验,我们发现这种可能性更大)是,缓存策略通常完全被Web服务器决定。

Setting a flag on a web server’s configuration file to automatically activate ETag generation and Last-Modified headers is not time-consuming and can give decent results.

在Web服务器的配置文件上设置标记以自动激活ETag生成和Last-Modified标头并不费时,而且可以提供不错的结果。

For some time at least. Until one realizes that the feature doesn’t work as expected or even worse, that users are starting to be served stale content due to unknown reasons.

至少一段时间。 直到人们意识到该功能无法按预期甚至更糟地工作,由于未知的原因,才开始向用户提供过时的内容。

Besides, these web servers won’t do much good in terms of caching your API. Most of them generate cache headers based on files metadata, which can have subtle consequences. But with API requests, there is no file to read metadata from. Hence when they see a resource that is dynamically generated, all they can do is watch and forward the request.

此外,这些Web服务器在缓存API方面做得不好。 它们中的大多数会基于文件元数据生成缓存头,这可能会产生微妙的后果 。 但是对于API请求,没有文件可以读取元数据。 因此,当他们看到动态生成的资源时,他们所能做的就是观察并转发请求。

Granted, as efficient as it can be, caching in the browser is not as easy it as looks. Major browsers implement different layers of cache, of which the HTTP one we’re talking about is only a piece. And in case you’re wondering, they can interact in some ways that are not always as predictable as we would like them to be.

当然,浏览器中的缓存虽然效率很高,却并不像外观那样容易。 主要的浏览器实现了不同的缓存层,我们所讨论的HTTP只是其中的一部分。 而且,如果您想知道, 它们可以以某些方式交互 ,而这些方式并不总是像我们希望的那样可预测。

Besides, caching in the browser is notoriously dangerous, because developers lack the ability to invalidate resources at will. Doing so would involve allowing a web server to push information to every client that interacted with it, without clients initiating a connection, which is not possible in a client/server architecture.

此外,众所周知,在浏览器中进行缓存非常危险,因为开发人员缺乏随意使资源无效的能力。 这样做将涉及允许Web服务器将信息推送到与其交互的每个客户端,而无需客户端启动连接,这在客户端/服务器体系结构中是不可能的。

Furthermore, from the cacher’s point of view, as powerful as it is, the browser has other flaws. It uses some doubtful heuristics when no caching instructions are explicitly present, all the more reason for us to help it know exactly what to do.

此外,从缓存器的角度来看,浏览器虽然功能强大,但还有其他缺陷。 当没有明确显示缓存指令时,它会使用一些令人怀疑的启发式方法,这更多的是我们帮助它确切知道要做什么的原因。

But even if we were to do it, users have the ability to flush their cache anyway or disable it. Not the almighty caching tool that one could ask for Christmas, after all.

但是,即使我们要这样做,用户也仍然可以刷新其缓存或将其禁用。 毕竟不是一个可以要求圣诞节的全能缓存工具。

So let us take the browser out of the equation for now and ask ourselves: without it, is HTTP caching still relevant? Is it implemented at other places? As it turns out, the browser is just one piece of the caching chain. And if browsers were all of a sudden to stop caching everything, rest assured: CDNs got us covered.

因此,让我们暂时将浏览器从方程式中剔除,然后问自己:没有它,HTTP缓存是否仍然有用? 是否在其他地方实施? 事实证明,浏览器只是缓存链的一部分。 而且,如果浏览器突然停止缓​​存所有内容,请放心:CDN覆盖了我们。

CDN (CDN)

Content Delivery Networks (CDN) are the unified champions of the HTTP caching world. Most of them have installed tons of servers — Akamai has ~240 000 — all geographically around the globe in order to serve our content closely to our end users.

内容交付网络(CDN)是HTTP缓存世界的统一拥护者。 他们中的大多数都安装了数以吨计的服务器-Akamai拥有约24 万个服务器-遍布全球,以便为最终用户提供更紧密的服务。

These companies have accumulated decades of experience on web performance. Most of the people who write the specs or the software that power the specs usually work in these companies, which is a bit of an indication that they know what they’re doing. Let us take a quick tour of why they are so important and how they work.

这些公司在网络性能方面积累了数十年的经验。 编写规范或支持规范的软件的大多数人通常在这些公司工作,这表明他们知道自己在做什么。 让我们快速浏览一下为什么它们如此重要以及它们如何工作。

First and foremost, is it crucial to understand that all of these servers are HTTP servers. In HTTP terminology, they are proxy servers which means that they speak HTTP. They do not encapsulate our requests into another shady proprietary application protocol. They just use these proxies, most of which are even free or open source!

首先,最重要的是要了解所有这些服务器都是HTTP服务器。 用HTTP术语来说,它们是代理服务器,这意味着它们使用HTTP。 它们不会将我们的请求封装到另一个可疑的专有应用程序协议中。 他们只使用这些代理,其中大多数甚至是免费或开源的!

As a direct consequence, any knowledge of HTTP caching is immediately actionable to leverage the infrastructure they put at our disposal. In addition to billions of browsers, we now have thousands of servers strategically placed by specialized companies waiting for us to instruct them how to cache our content for maximum efficiency. Furthermore, depending on what your priorities are, that’s not even the best feature.

直接的结果是,任何有关HTTP缓存的知识都可以立即采取行动,以利用它们提供给我们的基础架构。 除了数十亿个浏览器外,我们现在还有数千家由专业公司战略性地放置的服务器,它们等待着我们指示他们如何缓存内容以实现最大效率。 此外,取决于您的优先级,这甚至不是最好的功能。

Most modern CDNs advertise the ability to programmatically purge resources out of the CDN’s network instantly. Let us say this again: programmatically and instantly.

大多数现代CDN都宣传以编程方式将资源立即从CDN的网络中清除的能力。 让我们再说一次:以编程方式即刻进行

As far as HTTP caching is concerned, the two hard problems in computer sciences might just have been reduced down to one! Caching anything and invalidating instantly whenever we want. From a developer keen on web performance point of view, it can hardly get any better.

就HTTP缓存而言,计算机科学中的两个难题可能已被简化为一个! 缓存任何内容,并在需要时立即失效。 从热衷于Web性能的开发人员的角度来看,它几乎不可能变得更好。

A word of caution: CDNs are not to be blindly trusted based on that. We’ve already experienced some slight differences between what was marketed on the brochure, and what we had in production, where other cache busting techniques had to be used to ensure the cache was actually cleared.

请注意:不要因此而盲目信任CDN。 我们已经在小册子上销售的产品和生产产品之间经历了一些细微的差别,在生产中,必须使用其他缓存清除技术来确保实际上清除了缓存。

Before starting to cache all of your resources forever carelessly, experimenting on a small sample first might be a good idea. However, if it’s not here today, it will eventually land consistently everywhere, making our lives much easier.

在开始漫不经心地永久缓存所有资源之前,先尝试一个小的样本可能是一个好主意。 但是,如果今天不在这里,它将最终始终如一地降落在所有地方,使我们的生活更加轻松。

Another aspect to keep in mind is that it is in every CDN’s best interest that developers see them as effective and powerful tools. As a consequence, they’ll often do their best to comply to the specification.

要记住的另一个方面是,对于每个CDN最大的利益,开发人员都将它们视为有效而强大的工具。 因此,他们通常会尽最大努力遵守规范。

Also, they all provide some web interface that makes it a breeze to give caching rules that will either override or play nice with upstreaming caching directives coming from origin servers. The ability to configure your caching policy outside of your codebase happens to have two interesting consequences.

而且,它们都提供了一些Web界面,使用户轻而易举地提供了缓存规则,这些规则可以覆盖或很好地使用来自原始服务器的上游缓存指令。 在代码库之外配置缓存策略的功能碰巧会产生两个有趣的结果。

First, it means that people other than developers can have control on this which can be seen as a strength or a weakness based on your perspective. The ability to have someone other than a software developer fine-grain caching settings at the CDN’s level on critical occasions might come in handy in some situations.

首先,这意味着开发人员以外的其他人可以对此进行控制,根据您的观点,这可以看作是优势还是劣势。 在某些情况下,使软件开发人员可以在CDN级别上进行细粒度缓存设置以外的其他功能的能力可能会派上用场。

But perhaps even more importantly, it means that the performance part of your application, or at least a large part of it, can be completely factored out at the infrastructure level.

但是,也许更重要的是,这意味着可以在基础结构级别上完全排除应用程序的性能部分或至少其中很大一部分。

All developers that have experienced performance problems at some point know this: it is rarely something you can mutualize in a single file called performance and is often best planned ahead, just like detailed application-level logging. But that’s not necessarily the case with caching.

所有在某个时候遇到性能问题的开发人员都知道这一点:您很少可以在一个称为性能的文件中相互交流,并且通常最好提前计划 ,就像详细的应用程序级日志记录一样。 但是缓存并不一定是这种情况。

Provided your caching headers are smartly set and your CDN well configured, you could write poorly optimized server code (although, please don’t) and still have the vast majority of your users be served content in less than 300 milliseconds, by reusing cached versions that are still perfectly fresh.

如果您已正确设置了缓存标头并且配置了正确的CDN,则可以编写优化效果不佳的服务器代码(尽管请不要这样做),并且仍然可以通过重复使用缓存的版本在不到300毫秒的时间内为绝大多数用户提供内容仍然非常新鲜。

On the flip side, as one might expect, setting up and maintaining such a network of servers is both expensive and complex. As a result, although some of them have free plans that already allow for some serious performance boost in rather wide geographic areas, they remain paid solutions. If your intention is to cache millions of resources, be prepared to pay several thousand of dollars. This is where private proxy caches come into play.

另一方面,正如人们可能期望的那样,建立和维护这样的服务器网络既昂贵又复杂。 结果,尽管其中一些拥有免费计划,已经可以在相当广泛的地理区域内显着提高性能,但它们仍然是付费的解决方案。 如果您打算缓存数百万个资源,请准备支付几千美元。 这是专用代理缓存起作用的地方。

私人代理 (Private proxy)

The third and last player of the HTTP caching game is simply the same softwares many of the CDNs we just talked about are made of. Do the names Varnish, Squid, Traffic Server, or even Nginx ring a bell? Well, they certainly should!

HTTP缓存游戏的第三个也是最后一个参与者,就是我们刚才谈到的许多CDN所使用的相同软件。 Varnish , Squid , Traffic Server甚至Nginx这两个名字是否响起? 好吧,他们当然应该!

Given what we just said about the unmatched performance of web browser caches, and the case we just argued in favor of CDNs, one might legitimately asks: why bother setting up these in front of my origin servers when CDNs can do much more, and browsers are closer to my end users?

考虑到我们刚才所说的Web浏览器缓存的无与伦比的性能,以及我们刚才主张使用CDN的情况,人们可能会合理地问:当CDN可以做更多的事情时,为什么要在我的原始服务器前设置它们,而浏览器离我的最终用户更近?

Well, this third and last solution in the HTTP caching landscape also comes with its fair share of advantages. As a matter of fact, we’ll argue that this should often be the first solution to look for. Let us examine a few bonus points of the most popular solutions.

嗯,HTTP缓存领域中的第三个也是最后一个解决方案还具有其众多优势。 实际上,我们将争辩说这通常应该是寻找的第一个解决方案。 让我们研究一些最受欢迎的解决方案的加分点。

First, these solution are free and open source, which can be seen as a double edge sword. How many of such software that were once praised by the community suddenly stopped being maintained by their core committers due to a lack of interest, sponsoring, or both? The fear of seeing a project’s main dependency (web framework, ui library…) going to the software graveyard is a real concern.

首先,这些解决方案是免费和开源的,可以看作一把双刃剑。 由于缺乏兴趣,赞助者或两者兼而有之,曾经被社区赞扬过的此类软件中有多少突然停止由其核心提交者维护? 担心看到项目的主要依赖项(Web框架,UI库等)进入软件坟墓是一个真正的问题。

Although when assessing this risk, one must always consider the maturity of the technology, how long it’s been around, which big company is using or supporting it — they usually do both — and how effective it is at solving a particular problem. Lucky for us, the proxies we’re talking about score pretty high on all levels.

尽管评估这种风险时,必须始终考虑技术的成熟度,技术的发展历程,哪个大公司正在使用或支持该技术(他们通常会同时做到)以及解决特定问题的有效性。 对我们来说幸运的是,我们所谈论的代理在各个级别上的得分都很高。

Another aspect simply comes from the performance gain. As mentioned previously, these softwares are what CDNs are made of. This has two consequences.

另一个方面仅来自性能提升。 如前所述,这些软件是CDN的组成部分。 这有两个后果。

First, it massively decreases the chance of termination of their usage, because CDNs whole infrastructure relies on it. This kind of stability is greater than when a company is just using a library as part of a larger system. In this case, the software is the system.

首先,由于CDN的整个基础架构都依赖于CDN,因此它大大降低了终止使用它们的机会。 这种稳定性比公司将图书馆作为大型系统的一部分使用时要强。 在这种情况下,软件就是系统。

Second, any hard gained knowledge about their installation, configuration and maintenance will directly be transferable the day you decide to switch or complement your caching infrastructure with a CDN, since they are the same servers! In the software development world, where everything changes so fast, this is always good news.

其次,您可以在决定使用CDN切换或补充缓存基础架构的那一天直接获得任何有关其安装,配置和维护的知识,因为它们是相同的服务器! 在软件开发世界中,一切变化如此之快,这始终是个好消息。

It’s the same reason why learning HTTP caching is a good bet, because it’s relevant in many different places. And will likely stay that way for decades, we shall see why in the end of this article.

这也是为什么学习HTTP缓存是一个不错的选择的相同原因,因为它在许多不同的地方都相关。 而且可能会持续数十年,我们将在本文结尾处了解原因。

Browsers, edge servers, proxy servers… that’s a lot of caching intermediaries. Thinking about all these caches at the same time can be a little overwhelming and hard to picture. Luckily for us as we mentioned previously, all these caches speak HTTP and comply to the same specification.

浏览器,边缘服务器,代理服务器……这是很多缓存中介的地方。 同时考虑所有这些缓存可能会有些困难,难以想象。 就像我们前面提到的,对我们来说幸运的是,所有这些缓存都使用HTTP并遵守相同的规范。

As proxy servers, they all act transparently both for clients and for servers. Origin servers communicate with the proxy as if it were the client, and end users browsers communicate with the proxy as if it were the server. This holds true even between proxy servers.

作为代理服务器,它们对客户端和服务器都透明地起作用。 原始服务器与代理进行通信就像客户端一样,最终用户浏览器与代理进行通信就像服务器一样。 即使在代理服务器之间也是如此。

As such, we can model the reality by considering that all caching infrastructures are equivalent to one with a single caching proxy in place.

这样,我们可以通过考虑所有缓存基础结构等效于一个缓存代理的情况来对现实建模。

This is best described by the following picture:

下图最好地描述了这一点:

We’ll use this simplification in the rest of this series of articles. This abstraction is helpful to visualize the mechanisms at play, but it comes with certain limitations. Putting two proxies one after the other can have subtle consequences.

在本系列文章的其余部分中,我们将使用这种简化。 这种抽象有助于可视化运行中的机制,但是它具有某些局限性。 一个接一个地放置两个代理可能会产生微妙的后果 。

So far, we have covered a lot of ground without giving away anything about the detailed interactions between a client and a caching server. HTTP caching is a complex subject. Before moving on to the real technicalities in part 2, there is one last important aspect that needs to be explored.

到目前为止,我们已经涵盖了很多基础知识,而没有提供任何有关客户端与缓存服务器之间的详细交互的信息。 HTTP缓存是一个复杂的主题。 在继续第2部分的实际技术之前,需要探讨最后一个重要方面。

缓存未来 (Caching for the future)

Have you ever had to wait a few seconds to interact with a web page, or to see anything meaningful on the screen? Probably. That’s actually not unlikely at all. Everyone has experienced the slow internet at some point in their life, even at home with fiber connectivity.

您是否需要等待几秒钟才能与网页进行交互,或者在屏幕上看到有意义的内容? 大概。 实际上,这并不是不可能的 。 每个人在生活中的某个时刻都经历了缓慢的互联网,即使在家中使用光纤连接也是如此。

Past UX research actually has got some scary metrics about this. Metrics that have been the same for more than 40 years, by the way, making them unlikely to change anytime soon. Their guidelines are expressed in terms of hundreds of milliseconds, whereas we are used to browse the Internet and wait several seconds.

过去的UX研究实际上对此有一些令人恐惧的指标 。 顺便说一句,已有40多年的度量标准相同,因此它们不太可能很快改变。 他们的准则以数百毫秒表示 ,而我们习惯于浏览Internet并等待 秒钟。

So why do we believe that HTTP caching is relevant today and will almost certainly remain so for the years to come?

那么,为什么我们相信HTTP缓存在今天是有意义的,并且在以后的几年中几乎肯定会如此?

It all comes down to this basic question: why is the web so slow?

一切都归结为一个基本问题: 为什么网络这么慢?

This question is undoubtedly a difficult one, and a rigorous examination would take us far too deep and lose our primary focus, which is HTTP caching. However, if we don’t have any idea on what makes a web page slow, how can we be sure that caching, despite all of its virtues, is the right tool for the job?

这个问题无疑是一个困难的问题,而严格的检查会使我们过于深入,从而失去我们的主要关注点,即HTTP缓存。 但是,如果我们对导致网页变慢的原因一无所知,那么如何才能确保缓存(尽管具有所有优点)是完成任务的正确工具?

From its conception, the web has certainly changed a lot. The days where web pages consisted of simple HTML files containing mostly text and hyperlinks are long gone.

从其概念来看,网络肯定发生了很大变化。 网页由主要包含文本和超链接的简单HTML文件组成的时代已经过去了。

These days, many websites are labeled as web applications, as their look and feel resembles that of desktop apps. But despite all the improvements and innovations that have been made over the years, one thing has always remained the same: it’s always begun with the downloading of an HTML file.

如今,许多网站都被标记为Web应用程序,因为它们的外观与桌面应用程序相似。 但是,尽管这些年来已经进行了许多改进和创新,但一件事始终保持不变:它总是从下载HTML文件开始的。

As it gradually downloads the HTML, the browser discovers all the other resources that combined will result in all the client’s side code that gets parsed and ultimately, executed.

随着它逐渐下载HTML,浏览器会发现所有其他资源组合在一起,将导致所有客户端端代码被解析并最终被执行。

In case of a typical SPA for instance, the flow of requests goes on. Upon execution, the application starts downloading data from the server, typically serialized as JSON these days, in order to render the UI. Each URL inside the JSON payload will, once referenced into the code (it doesn’t even have to be added to the DOM), triggers another download so that it can be displayed on the screen.

例如,在典型的SPA情况下,请求流继续进行。 执行后,该应用程序开始从服务器下载数据,通常这些天将其序列化为JSON,以呈现UI。 JSON有效负载中的每个URL一旦被引用到代码中(甚至不必将其添加到DOM中),都会触发另一个下载,以便可以在屏幕上显示它。

This model of execution, where all the bytes needed for the application to do its job are scattered among different places and must be downloaded every time is quite remarkable. Arguably, it’s what makes the web so unique in the software development world.

这种执行模型将应用程序完成其工作所需的所有字节分散在不同的位置,并且每次都必须下载。 可以说,这就是使Web在软件开发领域如此独特的原因。

But there is a catch.

但是有一个问题!

Indeed as of today, the typical web application requires 75 requests and weighs 1.5 Mb, meaning that browsers must initiate a lot of requests of ~20kB each. To put it another way, it means that a typical web application is made of lots of short-lived connections.

确实,到今天为止,典型的Web应用程序需要75个请求,重1.5 Mb,这意味着浏览器必须发起许多每个20kB的请求。 换句话说,这意味着典型的Web应用程序由许多短暂的连接组成。

And here is the catch: this is the exact opposite of what TCP is optimized for.

这就是要注意的问题:这与TCP所优化的完全相反。

Web请求的剖析 (The anatomy of a web request)

In theory, all of these 75 requests should go through these steps:

从理论上讲,所有这75个请求都应遵循以下步骤:

  • DNS resolutionDNS解析
  • TCP handshakeTCP握手
  • SSL handshakeSSL握手
  • Data downloading constrained by TCP flow and congestion controlTCP流和拥塞控制限制了数据下载

Let us walk through each of them and draw a counter-intuitive consequence from it.

让我们逐一探究它们,并从中得出违反直觉的结果。

DNS resolution is the process of converting a human readable hostname such as example.com into an IP address. Although the DNS protocol is based on UDP instead of TCP, the journey to getting a hostname IP address can be really long, involving multiple DNS servers. And it’s not uncommon that these DNS resolutions take between 50 to 250 milliseconds.

DNS解析是将人类可读的主机名(例如example.com)转换为IP地址的过程。 尽管DNS协议基于UDP而不是TCP,但是获取主机名IP地址的过程可能非常漫长 ,涉及多个DNS服务器。 这些DNS解析需要50到250毫秒之间的时间并不少见。

Then, each request must initiate a TCP connection. HTTP has always needed a reliable transport protocol to work. If the ASCII bytes representing every HTTP request were to be delivered out of order, a status line such as

然后,每个请求必须启动一个TCP连接。 HTTP一直需要可靠的传输协议才能起作用。 如果代表每个HTTP请求的ASCII字节不按顺序传递,则状态行将显示为

GET /home.html HTTP/1.1

would become:

会成为:

GTE /mohe.hmtl HTTP/1.1

and the request wouldn’t make much sense.

并且该请求没有多大意义。

In order to guarantee delivery order, TCP marks each byte of applications data with a unique identifier called a sequence number (SYN). The problem is that this number must be chosen randomly for security reasons.

为了保证交付顺序,TCP使用称为序列号(SYN)的唯一标识符标记应用程序数据的每个字节。 问题是, 出于安全原因,必须随机选择此编号。

Therefore, if a client is asking for a resource, it cannot do so without signaling to the server its initial sequence number (ISN). Then it must wait before the server acknowledges good reception of this segment, before being able to send application data.

因此,如果客户端正在请求资源,则它不能不向服务器发信号通知其初始序列号(ISN)而这样做。 然后,它必须等待服务器确认对该段的良好接收,然后才能发送应用程序数据。

Well, unless the request is secure, which it probably is since 80% of HTTP requests these days are actually secure HTTPS requests. These are normal HTTP requests, except that they are encrypted in order to guarantee (at least, up to this day) confidentiality, integrity, and authenticity.

好吧,除非该请求是安全的,否则可能是因为这些天80%的HTTP请求实际上是安全的HTTPS请求。 这些是正常的HTTP请求,除了对它们进行加密以确保(至少到今天为止)机密性,完整性和真实性外,它们是加密的。

To accomplish that, the client and servers must now agree on a TLS protocol version, select cryptographic functions, authenticate each other by exchanging and validating x509 certificates… for no less than ~10 protocol messages that can be packed into a minimum of 2 TCP exchanges, and as many round trips.

为此,客户端和服务器必须现在就TLS协议版本达成协议,选择加密功能,通过交换和验证x509证书进行相互认证……不少于10条协议消息,这些消息至少可以打包成2个TCP交换,以及许多往返行程。

Once the connection is setup and secure, then TCP can finally start sending segments carrying our application data, such as our HTTP request. Unfortunately for us, TCP prevents us from sending all our data at once in one batch of multiple segments.

一旦建立了连接并确保了安全性,TCP即可最终开始发送承载我们的应用程序数据(例如HTTP请求)的段。 对于我们来说不幸的是,TCP阻止我们一次发送多个分段中的所有数据。

This restriction is a necessary evil, so that we don’t accidentally cause a buffer overflow on the receiver. When an application that initiated a connection asks the underlying TCP socket for data, TCP will refuse to give any chunk that would be incomplete or made of unordered smaller chunks. Hence, the need for a buffer.

这种限制是必不可少的,这样我们就不会在接收器上意外造成缓冲区溢出。 当启动连接的应用程序向基础TCP套接字询问数据时,TCP将拒绝提供任何不完整的块或由无序的较小块组成的任何块。 因此,需要缓冲。

The way it works is that TCP sends N segments in the first batch, and, if all segments were received by the server, will send twice as many segments (2N) in the next batch, and so on, leading to an exponential growth. This mechanism is commonly known as the slow-start algorithm and is one of the two only possible modes in which TCP operates, along with congestion avoidance.

它的工作方式是TCP在第一批中发送N个段,如果服务器接收到所有段,则在下一批中将发送两倍的段(2N),依此类推,从而呈指数增长。 这种机制通常被称为慢启动算法,并且是TCP运行以及避免拥塞的两种可能的模式之一。

We won’t discuss congestion avoidance in this series. But if there was only one thing to be aware of, it would be that once TCP senses that the underlying network may be congested, the protocol starts acting much more conservatively. Thereby extending even more the time required to transmit data.

在本系列中,我们不会讨论拥塞避免。 但是,如果只有一件事需要注意,那就是一旦TCP感知到底层网络可能拥塞,该协议就会开始更加保守地工作。 从而甚至延长了传输数据所需的时间。

结果 (The consequence)

With all these steps in mind, let us make a simple calculation to realize something important. At the beginnings of the web, the N parameter (known as the congestion window in TCP’s terms) was equal to 1. With such a window and an average resource of 20kB, we can determine how many round trips are necessary for an average request to be fully transmitted.

考虑到所有这些步骤,让我们进行简单的计算以实现重要的事情。 在网络开始时,N参数(在TCP术语中称为拥塞窗口)等于1。有了这样的窗口和20kB的平均资源,我们可以确定平均请求发送到网络所需的往返次数。被充分传播。

Indeed, under normal circumstances, the maximum segment size (MSS) is 1460 bytes. That’s equivalent to 20 000 / 1460 = 14 TCP segments. When dispatched according to the exponential scheme we just described, this is equivalent to 4 round-trips to the server.

实际上,在正常情况下,最大段大小( MSS )为1460个字节。 相当于20000/1460 = 14个TCP段。 当按照我们刚刚描述的指数方案进行调度时,这相当于到服务器的4次往返。

Now, if we approximate a UDP-based DNS request to a TCP-based request to the origin servers, we can estimate a total number of round-trips (RT) that require the booting of a modern web application:

现在,如果我们将基于UDP的DNS请求与基于TCP的对原始服务器的请求近似,则可以估计需要引导现代Web应用程序的往返(RT)总数:

  • DNS request: ~1 RTDNS请求:〜1个RT
  • TCP connexion setup: 1 RTTCP连接设置:1 RT
  • SSL handshake: 2 RTSSL握手:2次RT
  • Resource downloading: 4 RTT资源下载:4 RTT
  • Total: 8 RT

    总计:8 RT

75 requests that all require 8 round-trips each result in a total of 600 rounds trips to the server. A typical RTT between Europe and the US is 50ms, which gives us the amount of time that information spend flowing on the Internet when we request a typical web application: 30 seconds. And it could get worse.

75个请求全部都需要8次往返,因此总共有600次往返服务器。 欧美之间的典型RTT为50毫秒,这使我们在请求典型的Web应用程序时,信息花费在Internet上的时间为30秒。 而且情况可能会变得更糟。

The Amazon homepage for instance, a typical MPA, currently weighs 6.3Mb and requires 339 requests. That would translate into a salient page loading time of 2 minutes and 15 seconds. As an exercise, try do the same for the Facebook Messenger homepage, a typical SPA.

例如,Amazon主页(典型的MPA )当前重6.3Mb,需要339个请求。 那将转化为2分钟15秒的显着页面加载时间。 作为练习,请尝试对典型的SPA的Facebook Messenger主页执行相同的操作。

How to interpret this number? This would be the actual page load if every single resource had to be downloaded sequentially, TCP initial congestion was down to its minimum value of 1, and if DNS requests, TCP and SSL handshakes had to be done all over again every time. The web would be a much different place for sure.

如何解释这个数字? 如果必须依次下载每个单个资源,TCP初始拥塞降至其最小值1,并且每次都必须重新进行DNS请求,TCP和SSL握手,则这将是实际的页面加载。 毫无疑问,网络将是一个截然不同的地方。

Fortunately, many improvements have been made over the years. DNS resolutions are cached at different places, TLS handshakes results are reused.

幸运的是,这些年来已经取得了许多进步。 DNS解析被缓存在不同的位置,TLS握手结果被重用。

TCP connections were allowed to be persisted between multiple requests, avoiding the cost of both connection setup and slow-start on each request.

TCP连接被允许在多个请求之间持久保存 ,从而避免了建立连接和每个请求缓慢启动的开销。

TCP’s initial congestion window was lifted up twice, from 1 to 4 and more recently, to 10. Browsers started to open up parallel connections (6) as well as some really advanced strategies to accelerate page load times.

TCP的初始拥塞窗口被提升了两次,从1提升到4 ,最近又提升到10 。 浏览器开始开放并行连接(6)以及一些真正先进的策略来加快页面加载时间。

Some proposals tried to break free from the connection setup, although none of them are widely implemented.

一些提议试图摆脱连接设置的束缚,尽管没有一个被广泛实施。

Some CDNs even acquired patented algorithms to tune some of TCP aspects such as congestion avoidance, always for the same reason: speed up delivery.

某些CDN甚至还获得了获得专利的算法来调整TCP的某些方面,例如避免拥塞,其原因始终相同:加快交付速度。

What consequence can we draw from all these round-trips between browser and origin servers?

从浏览器和原始服务器之间的所有这些往返中可以得出什么结果?

That bandwidth stopped being the bottleneck many years ago.

多年前,带宽不再是瓶颈。

This is somewhat counter-intuitive to most of us, because bandwidth has embodied the browsing speed for years. After all, it has exactly the dimension of a speed, bits by unit of time, and it is the only thing ISPs advertise when trying to lure us into becoming their customers.

这对我们大多数人来说有点违反直觉,因为多年来带宽一直体现了浏览速度。 毕竟,它的确具有速度的大小,以时间单位为单位,这是ISP试图吸引我们成为其客户时唯一做的广告。

Besides, browsing on 3G is clearly slower than on 4G. But that is because the threshold at which bandwidth stops being the bottleneck is 5 Mb/s, and 3G maxes out at 2 Mb/s in ideal conditions!

此外,在3G上浏览显然比在4G上慢。 但这是因为带宽停止成为瓶颈的阈值是5 Mb / s,而在理想条件下3G最高可达2 Mb / s!

And if wireless technologies such as Wi-Fi or 5G are indeed slower than their wired counterpart of some sort, it is also because in wireless systems, packet drops caused by interferences are commonplace thereby making latency much higher and volatile.

而且,如果诸如Wi-Fi或5G之类的无线技术的确比某种形式的有线技术慢,那也是因为在无线系统中,由干扰引起的丢包现象很普遍,从而使延迟大大增加且易变。

The latest version of the HTTP protocol, HTTP/2, codenamed H2, was a continuation of the SPDY protocol which itself was initially designed following this very observation: bandwidth doesn’t matter much anymore. Latency does. But latency is fundamentally a function of two things: the speed of light in optic fiber, and the distance between clients and servers.

HTTP协议的最新版本HTTP / 2(代号为H2)是SPDY协议的延续,该协议最初是根据以下观察而设计的:带宽不再重要。 延迟确实如此。 但是延迟从根本上说取决于两件事:光纤中的光速以及客户端和服务器之间的距离。

Active research to increase the speed of light in optic fiber has already been conducted, but it only got us so far. In most deployments, light already travels at 60% of its maximum theoretical limit.

已经进行了积极的研究来提高光纤中的光速,但是到目前为止,这只是为我们提供了帮助。 在大多数部署中,光已经以其最大理论极限的60%传播。

But even if we were to reach 99%, that would only have a significant impact on your website if it’s already loading in a few seconds at most. If it’s loading in more than 5 seconds, even though the performance increase would be noticeable, it would still feel slow.

但是,即使我们要达到99%,也只会在最多几秒钟内加载您的网站时对您的网站产生重大影响。 如果加载时间超过5秒,即使性能明显提高,它仍然会感觉很慢。

Therefore we are left with one obvious choice: reducing the distance.

因此,我们有一个明显的选择: 缩短距离

And the only way to accomplish that is by leveraging browsers and content delivery networks with HTTP caching.

而实现此目标的唯一方法是利用HTTP缓存利用浏览器和内容交付网络。

结论 (Conclusion)

Along this article, we have argued that HTTP caching is one if not the most effective way to improve the performance of your web application. And as many studies keep pointing out, page load time is an important subject that can be directly translated into user satisfaction and, ultimately, profitability.

在本文中,我们一直认为HTTP缓存是提高Web应用程序性能的最有效的方法之一。 而且,正如许多研究不断指出的那样,页面加载时间是一个重要的主题,可以直接转化为用户满意度以及最终的盈利能力。

We have seen that caching can happen pretty much everywhere, from the browser, to CDN, to private proxy servers sitting just in front of your origin servers. But also that, unlike many performance decisions, it can be completely externalized outside the main codebase, which is both valuable and convenient.

我们已经看到,缓存几乎可以在任何地方发生,从浏览器到CDN,再到原始服务器前面的私有代理服务器。 而且,与许多性能决策不同,它可以在主代码库外部完全外部化,这既有价值又方便。

Finally, we took a closer look at the anatomy of a modern web application, to understand why latency is the new bottleneck, making caching relevant today and for years to come, even with the steady deployment of H2.

最后,我们仔细研究了现代Web应用程序的结构,以了解为什么延迟是新的瓶颈,即使在H2稳步部署的情况下 ,缓存仍在当今和未来几年都具有重要意义。

In the next article of this series, we will deep dive into the How.

在本系列的下一篇文章中,我们将深入探讨How。

In a way, this first part was merely a warm-up! We’ll learn how all of this actually works: resource freshness, revalidation, representations, cache-control headers… and much more!

在某种程度上,这第一部分仅仅是热身! 我们将学习所有这些实际上是如何工作的:资源新鲜度,重新验证,表示形式,缓存控制标头……等等!

Stay tuned!

敬请关注!

更进一步: (To go further:)

Ilya Grigorik High Performance Browser Applications (a must read):https://hpbn.co/

Ilya Grigorik高性能浏览器应用程序(必读): https ://hpbn.co/

Mike Belshe paper that served as a basis for the SPDY protocol: https://docs.google.com/a/chromium.org/viewer?a=v&pid=sites&srcid=Y2hyb21pdW0ub3JnfGRldnxneDoxMzcyOWI1N2I4YzI3NzE2

迈克·贝尔什(Mike Belshe)作为SPDY协议基础的论文: https ://docs.google.com/a/chromium.org/viewer ?a=v& pid = sites & srcid = Y2hyb21pdW0ub3JnfGRldnxneDoxMzcyOWI1N2I4YzI3NzE2

Active CDN blogs with tons of great articles:https://www.fastly.com/bloghttps://blogs.akamai.com/web-performance/

活跃的CDN博客中有大量精彩的文章: https : //www.fastly.com/blog https://blogs.akamai.com/web-performance/

翻译自: https://www.freecodecamp.org/news/http-caching-in-depth-part-1-a853c6af99db/

深入分布式缓存

深入分布式缓存_HTTP缓存的深入介绍:探索风景相关推荐

  1. nginx强制刷新用户缓存_HTTP 缓存

    HTTP 缓存分为强缓存和协商缓存. HTTP 缓存控制机制 HTML Meta 标记 // 当前页面不缓存, 每次访问都去服务器拉取. 只有部分浏览器支持. HTTP 头信息 HTTP 头信息 强缓 ...

  2. spring http缓存_HTTP缓存与Spring示例

    spring http缓存 缓存是HTTP协议的强大功能,但由于某些原因,它主要用于静态资源,例如图像,CSS样式表或JavaScript文件. 但是,HTTP缓存不仅限于应用程序的资产,因为您还可以 ...

  3. 架构系列---利用zookeeper 分布式锁解决缓存重建冲突实战

    上一篇 分布式缓存重建并发冲突问题以及zookeeper分布式锁解决方案, 主要讲解了分布式缓存重建冲突原因及利用zookeeper分布式锁解决缓存重建冲突问题,本篇接着上篇,实现上篇思路,带你利用z ...

  4. Redis分布式锁防止缓存击穿

    缓存击穿 和缓存穿透不同的是,缓存击穿是指:缓存中没有,但是数据库中存在的热点数据. 例如:首页的热点新闻,并发访问量非常大的热点数据,如果缓存过期失效,服务器会去查询DB,这时候如果大量的并发去查询 ...

  5. Spring Cache使用Redisson分布式锁解决缓存击穿问题

    文章目录 1 什么是缓存击穿 2 为什么要使用分布式锁 3 什么是Redisson 4 Spring Boot集成Redisson 4.1 添加maven依赖 4.2 配置yml 4.3 配置Redi ...

  6. 【高并发秒杀系统】对分布式锁、缓存、消息队列、限流等的原理分析及代码实现

    前言:在一些商城项目中,秒杀是不可或缺的.但是,如果将普通的购买.消费等业务流程用于秒杀系统,不做任何的处理,会导致请求阻塞严重.超买超卖等严重后果,服务器.数据库也可能因为瞬时的流量而奔溃.所以,设 ...

  7. 深入理解分布式技术 - 探究缓存穿透、缓存击穿、缓存雪崩解决方案

    文章目录 概述 缓存穿透 what 缓存穿透发生的场景举例 不合理的缓存失效策略 恶意攻击 如何规避缓存穿透 缓存击穿 what 缓存击穿发生的场景举例 如何规避缓存击穿 缓存雪崩 what 缓存击穿 ...

  8. 微服务架构,如何做分布式,通用缓存机制?

    在分布式系统中,特别是最近很火的微服务架构下,有没有或者能不能总结出一个业务静态数据的通用缓存处理机制或方案,这篇文章将结合一些实际的研发经验,尝试理清其中存在的关键问题以及探寻通用的解决之道. 什么 ...

  9. 前端协商缓存强缓存如何使用_http协商缓存与强缓存

    概述 良好的缓存策略可以降低资源的重复加载,提高网页的整体加载速度.通常浏览器的缓存策略分为两种:强缓存和协商缓存. 基本原理浏览器在加载资源的时候,会先根据这个资源的一些http header判断他 ...

最新文章

  1. mysql服务正在启动或停止中,请稍后片刻再试一次的解决办法
  2. @AutoWired具体解释
  3. bootstrap样式异常_处理异常功能样式
  4. [渝粤教育] 西南科技大学 线性代数 在线考试复习资料
  5. 面试干货:Java核心技术问题整理
  6. python可变类型与不可类型
  7. .sql文件_优化体系--sql_trace+10046事件(上篇)
  8. Unity自定义UI组件(九) 颜色拾取器(下)
  9. 计算机学院硕导北京工业大学,北京工业大学
  10. mysql写保护_简易修改注册表!小白都会去掉u盘写保护
  11. hdu5773 The All-purpose Zero(LIS变形)
  12. 李力刚:职场上如何成功推销自己
  13. Ecshop3.x漏洞复现
  14. 计算机开机按f1f2,电脑开机总是提示按f1 f2问题的解决办法
  15. 六、C++离散傅里叶逆变换
  16. VisionPro脚本
  17. WDF开发USB设备驱动教程(1)
  18. ARM开发基础--指令,异常源及处理过程
  19. 关于谷歌收购摩托罗拉移动的评论
  20. 从几号发工资,就能判断一家公司资金管理?

热门文章

  1. 存在对其他服务器端口(TCP:8090)的攻击行为之我的服务器被黑了
  2. c++保留两位有效数字和保留小数点后两位
  3. 什么是线程死锁?如何避免死锁?
  4. 读取BMP图像每一像素点RGB数据
  5. JS无缝轮播图(支持点击左右切换,小圆点切换,定时器自动播放)
  6. 大赢家软件测试工资,最佳移动芯片测试 ARM成大赢家
  7. 深蓝学院-视觉SLAM课程-第2讲作业
  8. 判断是否为移动端或浏览器
  9. Textarea 自动换行实现
  10. 《三打白骨精》观后感