Delivering Fast Experiences with Experience Manager Cloud Service
Adobe Experience Manager as a Cloud Service is designed to delivery content efficiently and effectively. A critical element to this efficiency it for a project to have a well designed Caching and Invalidation Strategy. In this session we will cover some of the traps that we see projects falling into, and give tips on how to improve your Cache Hit Ratio, and Cache Coverage with example from real world scenarios.
Continue the conversation in Experience League Communities.
Transcript
Hello everyone, welcome. My name is Alex and I’m a Cloud subject matter expert within Adobe. I’ll partner with Marius to deliver this presentation about fast experiences with AEM as a cloud services. This is the agenda for today. We will go through some technical basic concepts around the cache and we will have some tips and tricks around the cache optimization. We’ll make sure to leave some time for a Q&A session in the end of the presentation. I will start with a short real story. One of the customers had to go live with cloud services without running any performance tests prior to the go live and without letting the CSME team know about this change. After couple of hours from the moment they switched the DNS and made the public announcement, the site became unreachable. A war room has been opened with everyone involved and during the RCA it appeared that the caching at the CDN was around 5%. Even the publishers auto-scaled to the maximum, it didn’t actually solve the problem of the cache. Even adding more publishers than the maximum wouldn’t have solved the issue either because this will not compensate with the lack of caching. Imagine that you will compare 20 machines that will have the CPU exhausted with thousands of CDN machines that can be used at the edge. And the most important thing is that the CDN is already included by default in the offering. So why not making use of it? And to end up this story, after making couple of changes in the cache control and changing the response vary, the customer went live with a caching ratio of 96% and the two publishers were running their CPUs at around 30% between 30 and 35%. We all know that caching is the process by which a file gets stored in a temporary location. CDN servers cache HTML scripts, JavaScripts, images from the origin servers in proxy servers to reduce latency. So whenever the browser’s user requests information from a website through a CDN service for the first time, the CDN delivers the content by connecting to the origin server and then saving the content in the nearest data center to the user. I think we should set up the baseline for the concepts that we’ll talk about during this presentation and that’s why we have this theoretical slide. The successful access of the requested place of data in the CDN cache memory is referred as a cache hit. If a browser requests a piece of content and CDN has it cached, then it will deliver that content. This is referred to as a cache hit. However, if the content is not available, then the CDN makes the request to the origin server. This is classified as a cache miss. Additionally, a non-cacheable request for various reasons is defined as a pass request. An example of a pass request is the user input that needs to be recorded. In a nutshell, high cache hit ratio results in faster web apps while low cache hit ratio will result in slower web apps. This increases the stress on the origin server as well as increased latency and drop connection. You can see also some form of use in order to calculate the hit ratio and the cache coverage. This will be used in our data in the next slides. Now, how can you get these values? The easiest and the simplest way is to check the response headers in the browser itself. We will have a short demo on how to get this information in two minutes or so. Fastly CDN adds by default the XCache and the XCache hits headers to HTTP response. Also, Fastly owns and is the proprietary of these headers. So XCache hit means that your request was served by the CDN and not by the origin servers. XCache header indicates whether the request was a hit or a miss and Fastly writes this header into the responses. This non-standard header is appended to all the responses by default using a simplified derivative of the value of FastlyInfo.state variable. If this value is hit or any value that starts with hit dash then XCache will be set to hit. Otherwise, it will be a miss. Request resulting in a pass will be reported as a miss while request resulting in edge-generated synthetic content will be reported as a hit. Additionally, all hits resulting from serving stale or background revalidation will also be reported as hit. XCache hits indicates the number of cache hits in each node. Fastly appends this non-standard header to responses by default again. And I think it worth mentioning here that the hit count is per cache server and not per data center. And I will share a short demo. So for example, this is the website we are using for testing the weekend side. Maybe you’ve seen it with several occasions during trainings or other activities. So basically, if you load a page that is hosted with us and you go to networking, you will see under the response headers that these two values are set here, XCache hit and XCache hits. And then if you go, for example, for this font, you will see that the XCache hits is 14. Now, additionally, you can do short tests. And if you are looking for, if you are adding a parameter here, you will see that this request will be a miss, as you can see here. All right, so I’ll continue the presentation. Now, how you can these values in an aggregated view? Well, you can just submit a customer care ticket and ask your CSME to provide you the values and the dashboards. We are more than happy to help you with this data. Along with that, we can schedule a presentation where we will get you through the values and we’ll make some recommendation based on your custom miss and pass requests. And I think these discussions should happen prior to the go live, preferably along with some performance tests that will be run. Also, we are working on a white paper that will cover the cache subject. And before going to some more technical highlights of the presentation, I wanted to emphasize the fact that we strongly advise to apply the changes that my colleague, Marius, will recommend, because it will make a huge difference in the performance of your website and will bring a great experience to the end user. Hi, welcome to the second part of the presentation, the cache optimization tips. My name is Marius Petria and I’m a software engineer in the content delivery team of AEM as a cloud service. This basically deals with delivering content from AEM instances to the visitors of your site. Next slide, please. Okay, so I would like to start with a short description of the delivery architecture. It’s very schematic. So on the left hand side, you’ll have the visitor on the internet comes and visits your site. The request will first go to the CDN. The CDN will forward it to AEM. AEM will give a response. The CDN will see it and will pass it back to the visitor. So this is the basic flow, but actually it’s a bit more complicated than that because the CDN can also cache responses. Whenever it has a cache response, instead of sending it to AEM, it will deliver it from cache. What’s important to understand here is that every request in AEM as a cloud service goes through the CDN. It’s not just assets or videos or big files, it’s every request. So in some sense, every request is an opportunity to be optimized if it’s cached. And why it’s important to be cached? It’s important because it saves resources in AEM. And also the overall experience of your site will be faster because CDN is geographically distributed. There are like 200 points of presence all over the world. So your visitor will be very close to one of these server. I will present you next and Alex, if you can switch to the next slide, how we can get content to the CDN. So it’s not by pushing it or methods like this, but by using standard HTTP caching headers. So the simplest way is for the origin for AEM and dispatcher to respond with the proper caching headers. And the simplest way to do that is to set these headers in the dispatcher. You can also set them in AEM, but Apache configurations give you a declarative way to do it. So for example, you can set all cache images for 10 minutes or all HTML, and it’s just a matter of setting the cache control header. So what’s important to realize here is that when you are instructing the CDN to cache things, you are effectively making that content public. So because it will be served directly from the CDN and it will not hit your AEM instance again to check for authorization or authentication. So be careful when you add this. And always be specific on the folders that you want to be cached. So for example, always start your declarations like this content dam or content, or even more specific if you have private things under content. So that’s one key takeaway. It’s easy to set the headers, but it is also easy to make mistakes. So just do this only for your public content. Next slide, please. Okay. So in general setting the cache control will do the trick, but there is one thing to have in mind that there are multiple caching layers. Dispatcher is one of them and CDN the other one, it’s also the browser cache. And one mistake easy to make is that the agent in the dispatcher cache can become bigger than the max age that you are putting it with a directive for the cache control. So in that case, the CDN will not cache the resource. So always make sure that when you are setting the cache control, you are also setting the age to zero. So this can happen because dispatcher has different rules than the CDN. And for example, the dispatcher can cache indefinitely until it is invalidated. So until the resource is invalidated. Okay. Next slide, please. Okay. So I can show you now some more advanced examples like our presentation, we can cite. If you look at the cache control that we said there, it has more advanced directives like directing the browser, which is the max age, directing the CDN, which is the max age and also directives for stale content. So this site can be accessed publicly as Alex showed, and also the source code is available on GitHub. I will talk more about these special directives in the next slides. So if, yeah. Okay. So everything is good if the resource is cached and it’s simple to get it cached, you set a cache control on it. But what happens when the resource expires? So when the resource expires, then the CDN has to go back to the origin. So when the first visitor comes and hits an expired resource, it goes to the origin and then it will be blocked. The origin has to respond and will serve the response back to the visitor. This might not seem very important. I mean, if you cache for a long time, like one week, then it’s not that important. But if you want to decrease your TTL, then the cache will expire frequently and you will want to optimize this refetching of content. And especially that this refetching is done from all the pops. So for example, if your content expires in every of the 200 pops, then the origin will be hit simultaneously with requests from those pops. And the easiest, there are two ways to optimize these basically, is to always use conditional requests and the Fastly supports this. Basically every response that contains less modified and the ETags will be fetched by Fastly using conditional requests. So they will only be fetched from origin if they changed. Luckily, this is supported by default by dispatcher. So for cache to resources, so if a resource is cached by the dispatcher, the last modified and ETag will be sent to the CDN. So there’s a conversation there that is supported automatically. There are some caveats to that because the last modified by default in the dispatcher is related to the date when the cache copy was created on disk. So if you want something more advanced, you have to send it from AEM. But this will only support the cache to the CDN. So you cannot solve the transfer size, but your visitors, if they are unlucky to hit an expired resource, will still wait. So that’s where the second directive comes or the second technique, stay while you revalidate. This means that the CDN, you allow the CDN to serve stale content while revalidating in the background. So this way your visitors will not see any delay or unpredictable delay if they hit an expired resource. This is easy to set up. You just add the directive to the cache control. This should be typically bigger than the TTL of the resource. Like if you cache one minute, you can serve stale for one hour or so. Okay. So serving stale content helps you improve the speed on refetching and revalidation, but it also helps you improve the availability. So when you have unexpected errors in your application code or there are some infrastructure problems that make your origin unavailable, then you can still have availability at the edge. If you set stale if error directive, the CDN will serve, even if there is an error from the backend, will serve whatever is cached. So this will help you with unexpected errors and unavailability windows. Next slide, please. Okay. So I want to mention this technique. So typically there is one cache key per URL. So every resource is stored in the cache key of its URL, but there are a lot of use cases when you’d want to serve different content on the same URL. For example, for people in different countries or in different continents, or even more simple for if the browser accepts different encodings. And this is supported by standard HTTP header, by the very header. And so the very header allows you to vary by a request header or a header added by Fastly before evaluating the cache key. So for example, if you want to serve different pages by continent, different content by continent on the same landing page, you can add this header XAM client content, client continent to the very header. This header is added by our Fastly VCL, and it’s always included in the request. So Fastly will use this when creating the cache key. So this is useful, but it’s also dangerous. And I wanted to mention this, especially because it’s when you shouldn’t vary too much. There are maximum 200 variants accepted by Fastly, and specifically don’t vary by user region or by IP or cookie because they have very big cardinality. And I wanted to mention this because in one of, until some while ago, we had in our default dispatcher code vary by user agent, which made the cache very ineffective. So if you still have see if this response vary by user agent, just remove it. The new projects that start from new code will not have this. Okay. I have one more slide. If you can go to that one, but I will not insist because I think I’m out of time and I want to leave you time for questions. So Fastly supports special headers, surrogate control that is just like cache control, but it is only for commanding things too Fastly. So it’s removed by Fastly and it is respected, but removed and is not passed on to the browser. So it’s useful to control it, to control differently the browser cache and the CDN cache. Okay. So I’ll stop here. Thank you. And if you have any more questions, if you have any more questions, I can try to answer. I don’t, there is one question. I don’t see if there is a response to it. If we can use VCL in Fastly CDN for AM as a cloud. The answer is that the VCL is not customizable. So you cannot use it. And I think Ian might have answered that the alternative is to use a different CDN in front of Fastly. This only applies, I mean, caching techniques, I think, apply to every CDN and also to AMS, but AMS, as far as I know, does not come with default CDN in front of it. So, and especially it’s not Fastly. So for example, things like surrogate control probably are not relevant there. Yeah. Most of the techniques that we mentioned here applies for basic CDNs and the AMS hosted. Yeah. They are not coming with Fastly by default. So like you mentioned, Marius, the surrogate ones will not apply unless it is Fastly. But the dispatcher configuration that we mentioned in the first slides will apply for even for AMS hosted sites with CDN in front of it. Is it on the roadmap to allow pass-throughs using Fastly to allow for a gradual? I don’t understand exactly the question. I will try to answer a bit. Is the fastly CDN as it is today is in front of every deployment of AMS as a cloud. And you can put another CDN in front. But it will go, also that one will go through Fastly. Oh, I didn’t set Fastly supports vary by cookie. I put it in the bad column. You should not vary by cookie. It has very big cardinality. You can do, you cannot configure the CDN to block requests at the CDN level. So you have to do it in the dispatcher and vary the response by the country header. I think we are out of time, but we are happy to answer other questions if there are still some questions here that are unanswered or if you still have questions, we can answer more. Thank you for attending the session. Thanks, bye.
Additional Resources
recommendation-more-help
3c5a5de1-aef4-4536-8764-ec20371a5186