Here our Nginx cache system for clues, to explore a cache server design and related details, I try to stand in the design and framework of the angle of analysis, confined to the length here no longer go to the code, related details, welcome to participate in the discussion.
After the file is taken from the backend in a cache server, it is either sent directly to the client (known as a pass-through) or cached locally, and subsequent requests to the cache server can be accessed directly by the local copy, if available. If a locally cached file is accessed by a subsequent request, it is called a hit in the cache. If there is no cached copy of the file locally, then the cache server needs to configure or resolve the domain name, to the backend to get the file, this is called the buffer miss, that is, Miss. For more information on the cache server, we discuss the Nginx cache system in depth.
Nginx Storage System is divided into two categories, one is opened by Proxy_store, stored in the URL according to the file path, stored locally. For example/file/2013/0001/en/test.html, Nginx will set up each directory and file in the specified storage directory. Another type is open through Proxy_cache, this way the file is not organized according to the URL path, but in some special way to manage (this is called the Custom Way), the custom way is we have to focus on analysis. So what are the advantages of these two approaches?
The way the file is stored by URL path, the program is relatively simple to handle, but the performance is not good. First of all the URL is huge, we want to build such a deep directory on the local file system, then the file opening and searching is very slow (recall kernel in the path name to find the inode process). If you use a custom way to handle schemas, although you cannot leave files and paths, it does not increase complexity and degrade performance due to URL length. In a sense this is a user-state file system, the most typical of which should be considered as the CFS in squid. Nginx uses a relatively simple way, mainly rely on the URL of the MD5 value to manage, we will analyze later.
The cache is not needed to fetch content from the backend and then send it to the client. The specific way we can easily think of, must be on the side of the receiving side of the transmission, the other way is too inefficient, such as reading after the hair and so on. Here to mention the nginx side of the hair, using the structure is ngx_event_pipe_t, it is the communication backend and the client's medium. Since the structure is a generic component, a special tag is required to handle the related functions involved in the storage, so member cacheable the task.
p->cacheable = U->cacheable | | u->store;
That is, cacheable is 1, it needs to be stored, otherwise it is not stored. So what does u->cacheable and U->store represent? They represent the two ways previously said, namely Proxy_cache and Proxy_store.
(Add some knowledge, nginx when fetching back-end data, its behavior is controlled by proxy_buffering, the role is to enable the response buffer for the backend server.) If buffering is enabled, Nginx assumes that the proxy server is able to pass the answer very quickly and put it in a buffer, using proxy_buffer_size and proxy_buffers to set the relevant parameters. If the response cannot be fully loaded into memory, it is written to the hard disk. If buffering is disabled, replies from the backend are immediately transmitted to the client. )
Here are some of the edge, we have not touched the core of the Nginx cache function. From the implementation, in the NGINX upstream structure has a member called the cache, its type is ngx_shm_zone_t. If we turn on the cache feature, the cache member is used to manage shared memory (why is shared memory used?). ), and the other way to store the member is null. It is also important to note that a file in the cache system is often referred to as store object, which is the cache object, so it is necessary to create a store object before the cache. An important question is how to choose the timing of creation, what do you think? First we need to check whether a file needs to be cached, it is obvious that the Get method requests the file generally need to cache, so we at the beginning of request processing, we see the Get method, we can first create an object. But a lot of times, even if a GET method is requested by the file can not be cached, then you create an object prematurely, not only wasted time and wasted space, in the end it will be destroyed. So what will affect the storage of GET requests? That is the Cache-control field in the response header, which tells the agent or browser whether the file can be cached. The general cache server is cached by default for requests that do not have a cache-control field in the response header.
Based on this consideration, we developed a cache server that is created after the response header parsing is complete and enough evidence is available for caching to create the cached object. Unfortunately, Nginx did not do so.
Nginx in the Ngx_http_upstream_init_request function to complete the creation of the cache object, this function in the HTTP processing stage? Before the connection is established with the backend. This place, I personally think not very suitable ... What do you think?
About the creation process, you can read the function Ngx_http_upstream_cache. Here I take our cache and Nginx comparison to analyze it. We use a member named store in our request to establish a connection with the cached object. Nginx is similar, and it has a cache member in the request structure to do the same thing. The difference is that our store members correspond to the space in shared memory, and Nginx is applied in r->pool (why do we do this?). )。
Next, Nginx needs to build the key of the cache object according to the configuration, which is usually calculated by MD5. This key is a unique identifier for a cached object in the system, and many people may be concerned about the MD5 collision problem. I think that if the request is not particularly harsh, it is perfectly acceptable and the handling is relatively simple.
What is to be dealt with later is how the file should be stored on disk in exactly what form?
We take an example of the previous use:/file/2013/0001/en/test.html, which corresponds to the MD5 value is 8ef9229f02c5672c747dc7a324d658d0, in fact Nginx used it as a filename. So that's all you got? What if we were to find a directory to store files with a bunch of these files? As we know, most file systems have a limited number of files in a single directory, so it's not possible to do this with a simple, rude process. So what? Nginx configuration allows you to use a multilevel directory to solve this problem. To put it simply, Nginx specifies the number of directory layers (colon delimited) and the number of characters for each directory name by levels this instruction, in our case, suppose the configuration is levels=1:2, meaning that using a level two directory, the first level directory name is a character and the second level is two characters. However, Nginx supports a Level 3 directory, which is levels=xxx:xxx:xxx.
What about the characters that make up the name of the directory? Assuming our storage directory is/cache,levels=1:2, this is how the above file is stored:
/cache/0/8d/8ef9229f02c5672c747dc7a324d658d0
See 0 and 8d These two directory name how come, don't explain.
Once the object is created, it needs to be cached in the object management structure, which ngx_http_file_cache_exists to handle.
What if the current directory and file already exist when the file is created? We can go through the code to see how Nginx deal with.
The discussion first tells a paragraph, in fact, is now a few preparatory work, the next discussion of the backend content arrival processing.
Extended reading:
Http://www.pagefault.info/?p=123
http://www.pagefault.info/?p=375
The above describes the Nginx cache system design principles, including the aspects of the content, I hope that the PHP tutorial interested in a friend helpful.