📜 ⬆️ ⬇️

Using Nginx as a collector in a difficult caching case

Often we do not cache the output only because of the fact that among the data that can be easily and painlessly cached, there is frequently changing information (associated, as a rule, with a specific user).
There are several solutions to this problem, but there are significantly few good ones.

Solutions


There are several solutions to this problem.
1. Cache samples only.
This can and should be done, but still extra movements are performed, such as parsing the URL, initiating models and outputting data to the template. All this increases the entropy and leads to the premature destruction of the universe.
2. Collect data using javascript.
From my point of view, this practice is vicious, as it leads to data loss for clients that do not support javascript. Exclamations that decent customers keep javascript enabled, I reject with anger, because in the world there are mobile browsers, reading rooms for the blind and just hard-working robots. This solution is applicable (and even desirable) solely for displaying various "informers", without which you can easily do.
Thus, we must collect the data on the server, and in the easiest way possible. In this case, the well-deserved nginx server and the unfairly forgotten ssi technology are being used.

Immediately, I’ll make a reservation that the great discovery did not belong to me, but was born in the depths of a respected company mail.ru, whose specialists shared it on the Highload past.
However, their decision was, in my opinion, too cumbersome and somewhat different in ideology. In fact, there nginx was used as a template engine with support for loops, conditional jumps and other trinkets, which seem to be a bit redundant for a “small light frontend”. In addition, despite the joyful assurances of the authors, the project in the public domain did not appear, and writing such magnificence was not in my plans.

Idea


')
The point is to separate well-cached data and data that is cached poorly or not cached at all, the latter, as a rule, are tied to the user.
For example, there is a list of communities, next to each, depending on whether the user has entered there (and whether he is authorized at all), the “enter” button or the “leave” button are displayed.

As a result, we create a cache in which a ready-made html page is stored, containing the necessary data and ssi instructions for outputting variables, with non-cached data. A “backend” file is also created that generates these variables.

1. Run the cache at the normalized URL, if there is already a cache with the normalized URL, redirect to it, if not, create a fake cache that refreshes the page with some delay — that is, “Lochim” page.
/communities/new/1.html - first page of the list of communities sorted by creation time
2. We make a sample of well cached data.
In our case, the newest 10 communities.
3. Generate and “memorize” the code for sampling noncacheable data.
Those. In which communities of the selected is the current user.
4. Display the list. The point is that at the level of the template instructions, we have the opportunity to specify the code sections that are created in the backend. Thus, the code is “remembered” and supplemented with the generation code of the ssi variables, and po: ssi is replaced with the ssi instruction.
It looks something like this (the bicycle construction template engine is used, the hidden meaning of its creation is described here: cloud.habrahabr.ru/blog/22445 ):


{$Title}

<?
if (auth::is_logged_id()){
if (isset($memberof['{$id}'])&&$memberof['{$id}']){
?> <?
}
else {
?> <?
}
}
?>





5. Save the result of the script execution in the html file, and the code “tied to the user” in the backend file. Add the ssi include virtual instruction to the file cache, which connects the backend file.

Thus, when retrieving data from the cache, the following happens:

1. nginx receives the request and finds the page in the cache.
2. Executes the include virtual instruction (it is important here not to forget to set the wait parameter), by which it connects the generated backend file. There, the current user and his membership in the communities displayed on this page is determined, the html code for the “enter” and “leave” buttons is created, which is written into the corresponding ssi variables.
3. Variables are output in the appropriate places of the templates, as a result of which we get the required page.

Cache urgency



The relevance of the cache is maintained by “sampling names”, i.e. Each sample is an object that has one or more names, usually a table name and / or a table name and key.
For example, a sample of communities from the “communities” table with the theme “sport” is named communities_sport. Selection names are set at the model level, and at the model level, the cache can be reset during UPDATE / DELETE / CREATE.

As a result, when saving the cache, we save the page links with the names of all the samples taken, and when we change, we delete all the pages with the same name.

Source: https://habr.com/ru/post/36632/


All Articles