Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand caching

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces the knowledge of "how to understand caching". Many people will encounter such a dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Browser cach

Browser cache means that when we visit a website or Http service, the server can set the response header information of Http. If the header information related to cache is set, the browser will cache the data. The next time the data is accessed, it will be obtained directly from the browser cache or when you just need to go to the server to verify the cache. You can reduce the cost of network time between the browser and the server and save bandwidth.

Htpp related knowledge, welcome to visit the "interview" Http agreement

Cache-Control

This command is a common header field (both the request header and the response header can be used) to control the working mechanism of the cache. This command has a little more parameters, which are commonly used:

No-cache: indicates that the resource does not need to be cached

Max-age (seconds): the maximum valid time of the cache. When max-age=0, no cache is required.

Expires

Control the expiration date of the resource. When the browser receives the Expires, the browser will use the local cache and send the request to the server only after the expiration date. If the server also specifies the max-age instruction of Cache-Control in the response header, the browser will give priority to max-age. If the server does not want the browser to cache the resource, you can set the Expires and the header field Date to the same value

Last-Modified / If-Modified-SinceLast-Modified

Last-Modified is used to indicate when the resource was finally modified. When used with If-Modified-Since, you can verify whether the cache is valid over time; this method will be used later in practice.

If-Modified-Since

If the date of the If-Modified-Since in the request header is earlier than the update date of the requested resource, the service will process and return the latest resource; if the requested resource has not been updated after the date specified by If-Modified-Since, the service will not process the request and return a response of 304Mot Modified, indicating that the cached file is valid and can continue to be used.

Actual combat case

Use SpringMVC as the cached test code:

@ ResponseBody@RequestMapping ("/ http/cache") public ResponseEntity cache (@ RequestHeader (value = "If-Modified-Since", required = false) String ifModifiedSinceStr) throws ParseException {DateFormat dateFormat = new SimpleDateFormat ("EEE, d MMM yyyy HH:mm:ss' GMT'", Locale.US); Date ifModifiedSince = dateFormat.parse (ifModifiedSinceStr); long lastModifiedDate = getLastModifiedDate (ifModifiedSince) / / get the last update time of the document long now = System.currentTimeMillis (); int maxAge = 30; / / the data is cached in the browser for 30 seconds / / determine whether the document has been modified if (Objects.nonNull (ifModifiedSince) & & ifModifiedSince.getTime () = = lastModifiedDate) {HttpHeaders headers = new HttpHeaders (); headers.add ("Date", dateFormat.format (new Date (now) / / set the current time headers.add ("Expires", dateFormat.format (now + maxAge * 1000)); / / set the expiration time headers.add ("Cache-Control", "max-age=" + maxAge); return new ResponseEntity (headers, HttpStatus.NOT_MODIFIED);} / / the document has been modified HttpHeaders headers = new HttpHeaders () Headers.add ("Date", dateFormat.format (new Date (now); / / set the current time headers.add ("Last-Modified", dateFormat.format (new Date (lastModifiedDate); / / set the last modified date headers.add ("Expires", dateFormat.format (now + maxAge * 1000)); / / set the expiration time headers.add ("Cache-Control", "max-age=" + maxAge) String responseBody = JSON.toJSONString (ImmutableMap.of ("website", "https://silently9527.cn")); return new ResponseEntity (responseBody, headers, HttpStatus.OK);} / / get the last update time of the document to facilitate testing, change every 15 seconds Remove the millisecond value private long getLastModifiedDate (Date ifModifiedSince) {long now = System.currentTimeMillis (); if (Objects.isNull (ifModifiedSince)) {return now;} long seconds = (now-ifModifiedSince.getTime ()) / 1000; if (seconds > 15) {return now;} return ifModifiedSince.getTime ();}

When we visit http://localhost:8080/http/cache for the first time, we can see the following response header:

We have mentioned earlier that Cache-Control takes precedence over Expires, and in actual projects we can use both, or only Cache-Control. The value of Expires is usually the current time of the system + cache expiration time

When we visit http://localhost:8080/http/cache again within 15 seconds, we will see the following request header:

The header information If-Modified-Since sent to the server at this time is the Last-Modified returned by the server last time. The browser will use this time to verify whether the content has been changed with the server. Since our daemon indicates that the content has not been modified within 15 seconds, we get the following response header information.

The response status code 304 indicates that the server tells the browser that your cache is valid and can continue to be used.

If-None-Match / ETagIf-None-Match

The value transmitted to the server by the request header field If-None-Match is the EAG value returned by the server, and the server processes the request only if the ETAG value of the requested resource on the server is not consistent with If-None-Match.

ETag

The response header field ETag can tell the customer end the identity of the response entity, which is a way to uniquely identify resources in the form of a string. The server can specify an EAG value for each resource. When the resource is updated, the value of ETag is also updated. Md5 is usually used in algorithms that generate ETAG values.

Strong ETag value: changes the value of an entity no matter how slightly it changes

Weak ETag value: only used to indicate whether the resource is the same, the ETag will be changed only if the resource sends a fundamental change. Using weak ETAG values requires adding W / in front of them.

ETag: W / "etag-xxxx"

It is generally recommended to choose a weak ETag value because most of the time we enable ETAG compression at the proxy layer. Weak ETag can verify compressed and uncompressed entities, while strong ETAG values require that the response entity bytes must be exactly the same.

Practical example @ ResponseBody@RequestMapping ("/ http/etag") public ResponseEntity etag (@ RequestHeader (value = "If-None-Match", required = false) String ifNoneMatch) throws ParseException {long now = System.currentTimeMillis (); int maxAge = 30; / data is cached on the browser side for 30 seconds String responseBody = JSON.toJSONString (ImmutableMap.of ("website", "https://silently9527.cn"));") String etag = "W /\"+ MD5Encoder.encode (responseBody.getBytes ()) +"\ "; / / weak ETAG value if (etag.equals (ifNoneMatch)) {return new ResponseEntity (HttpStatus.NOT_MODIFIED);} DateFormat dateFormat = new SimpleDateFormat (" EEE, d MMM yyyy HH:mm:ss' GMT' ", Locale.US); HttpHeaders headers = new HttpHeaders (); headers.add (" ETag ", etag) Headers.add ("Date", dateFormat.format (new Date (now); / / set current time headers.add ("Cache-Control", "max-age=" + maxAge); return new ResponseEntity (responseBody, headers, HttpStatus.OK);}

ETag is used to send to the server for content change verification. The http://localhost:8080/http/etag is requested for the first time to obtain the response header information:

Within 30 seconds, we refresh the page again and see the following request header information:

The If-None-Match here is the If-None-Match value returned by the last request service. The server verifies that the ETAG value is equal to the ETAG value, so it returns 304to tell the browser that the cache is available.

How to choose between ETag and Last-Modified?

Through the above two examples, we can see that ETag requires the server to first query the content that needs to be responded, then calculate the ETAG value, and then compare it with the If-None-Match in the browser request header to see if the data needs to be returned. For the server, it only saves bandwidth, and the information that should have been queried by the server calling the back-end service is still not omitted. While Last-Modified compares the time, if the content is not updated, the server does not need to call the back-end service to query the response data, which not only saves the server bandwidth but also reduces the pressure on the back-end service.

After comparison, it is concluded that in order to reduce the pressure on the back-end service, ETag is suitable for static resources such as images / js/css, while data such as user details that need to be called from the back-end service is suitable to be processed by Last-Modified.

Nginx

Usually we use Nginx as a reverse proxy server. We can tune Nginx through buffering and caching. In this article, we will talk about Nginx tuning from these two aspects.

Buffer

By default, Nginx acquires data from the upstream server as soon as possible before returning the response to the client. Nginx will buffer the data returned by the server to the local as far as possible, and then return all the data to the client at once. If the data returned from the upstream server needs to be written to disk each time, then the performance of Nginx will definitely degrade; therefore, we need to optimize the cache of Nginx according to the actual situation.

Proxy_buffer_size: sets the size of the Nginx buffer to store the header of the upstream response.

Proxy_buffering: enable proxy content buffering. When this feature is disabled, the agent will send it to the client synchronously as soon as it receives the return from the upstream server. Proxy_max_temp_file_size is set to 0. By setting proxy_buffering to on,proxy_max_temp_file_size to 0, you can ensure that the disk is not applicable in the process of proxy, but only the buffer is used. The proxy_buffers and proxy_busy_buffers_size parameters will only work when enabled.

Proxy_buffers: sets the amount and size of cache in response to the upstream server. When one buffer is full, the next buffer is requested to be opened until the number of buffers reaches the maximum value set.

Proxy_busy_buffers_size: proxy_busy_buffers_size is not a separate space, it is part of proxy_buffers and proxy_buffer_size. Nginx starts sending data to the client before it has fully read the back-end response, so it marks a portion of the busy-state buffer to specifically pass data to the client (recommended twice the size of a single buffer in proxy_buffers), and then it continues to fetch data from the back-end. The proxy_busy_buffer_size parameter is used to set the size of the buffer in the busy state.

1) if the complete data size is less than the busy_buffer size, it will be transmitted to the client immediately after the data transfer is completed.

2) if the complete data size is not less than the busy_buffer size, it will be passed to the client as soon as the busy_buffer is filled.

Typically, it is set to twice as proxy_buffers.

The setting of the Nginx proxy buffer applies to each request. To set the buffer size to the best state, you need to measure the average number of requests and the size of the response through the reverse proxy server. The default value of proxy_buffers instruction is 8 4KB or 8 8KB (depending on the operating system). If our server is 1G and this server only runs Nginx service, then excluding the memory use of the operating system, it is conservatively estimated that the memory that Nginx can use is 768m.

Use buffered memory per active connection: 8 4KB = 8 * 4 * 1024 = 32768 bytes

The amount of memory available to the system is 768m: 768 * 1024 * 1024 = 805306368 bytes

So the number of connections that Nginx can handle simultaneously: 805306368 / 32768 = 24576

According to our rough estimate, a 1G server running only Nginx can handle about 24576 connections at the same time.

If we measure and find that the average data size responded by the reverse proxy server is 900KB, and the default buffer of 8 4KB is not satisfied, so we can resize it.

Http {proxy_buffers 30 32k;}

After this setting, the fastest response can be achieved per request, but the number of connections processed at the same time is reduced, (768 * 1024 * 1024) / (30 * 32 * 1024) = 819 active connections

If the concurrency of our system is not too high, we can reduce the number of proxy_buffers buffers and set a larger proxy_busy_buffers_size to increase the buffer sent to the client to ensure that Nginx can write all the data read from the upstream server to the buffer during transmission.

Http {proxy_buffers 10 32k; proxy_busy_buffers_size 64k;} cache

In addition to buffering the response of the upstream server to quickly return it to the client, Nignx can also cache the response, as we can see from the figure above.

1A: a request arrives at Nginx and first attempts to get it from the cache

1B: cache does not exist and go directly to the upstream server to get data

1C: the upstream server returns the response, and Nginx puts the response into the cache

1D: return the response to the client

2A: another request reaches Nginx and looks up in the cache

2B: if there is corresponding data in the cache, return it directly without going to the upstream server to obtain the data.

Common caching configurations for Nginx:

Proxy_cache_path: the directory where the cached responses and shares are placed. Levels sets the cache file directory hierarchy. Levels=1:2 represents a two-level directory with a maximum of three layers, of which 1 means that the first-level directory uses one-bit hexadecimal as the directory name, and 2 means that the second-level directory uses two-digit hexadecimal production as the directory name. If the files are stored in one directory, a large number of files will lead to slow file access. Keys_zone sets the cache name and shared memory size, and inactive sets the maximum cache space if it is not accessed after it is placed in the cache. Max_size sets the maximum cache space.

Proxy_cache: defines which cache the response should be stored in (the name of the keys_zone setting)

Proxy_cache_key: sets the Key used in the cache. The default is the full access URL, which can be set according to the actual situation.

Proxy_cache_lock: when multiple clients access URL at the same time, if this configuration is enabled, only one client will go to the upstream server to get the response and put it in the cache after the acquisition is completed, while the other clients will wait for it to be obtained from the cache.

Proxy_cache_lock_timeout: after proxy_cache_lock is enabled, if the first request exceeds the proxy_cache_lock_timeout setting of 5s by default, then all waiting requests will go to the upstream server to obtain data at the same time, which may increase the pressure on the backend.

Proxy_cache_min_uses: sets how many times a resource is requested before it is cached

Proxy_cache_use_stale: when an error occurs in accessing the upstream server, the expired data is returned to the client. When the cache content is not sensitive to the expiration time, you can choose this method.

Proxy_cache_valid: sets the cache time for different response status codes. If you set proxy_cache_valid 5s, all status codes will be cached.

Set the maximum unaccessed survival time for all responses to be cached for 6 hours, set the cache size to 1g, and the cache validity period is 1 day. The configuration is as follows:

Http {proxy_cache_path / export/cache/proxy_cache keys_zone=CACHE:10m levels=1:2 inactive=6h max_size=1g; server {location / {proxy_cache CACHE; / / specifies that the response is stored in the CACHE cache proxy_cache_valid 1d; / / all response status codes are cached 1d proxy_pass: http://upstream;}

If the Set-Cookie header information is set in the current response, the current response will not be cached, and the cache can be achieved by using proxy_ignore_headers to ignore the header information

Proxy_ignore_headers Set-Cookie

If we do this, we need to take the value in cookie as part of the proxy_cache_key to prevent different data from the same URL response from overwriting the cached data and returning to the incorrect data on the client side.

Proxy_cache_key "$host$request_uri$cookie_user"

Note that this situation is still problematic, because adding cookie information to the cached key may result in multiple public resources being cached, resulting in a waste of space. To solve this problem, we can configure different resources separately, such as:

Server {proxy_ignore_headers Set-Cookie; location / img {proxy_cache_key "$host$request_uri"; proxy_pass http://upstream;} location / {proxy_cache_key "$host$request_uri$cookie_user"; proxy_pass http://upstream;}} Clean the cache

Although we set up the cache to speed up the response, we sometimes encounter requests with cache errors, so we usually need to open a back for ourselves to clean up the cache manually after finding the problem. Nginx can consider using the ngx_cache_purge module for cache cleanup.

Location ~ / purge/.* {allow 127.0.0.1; deny all; proxy_cache_purge cache_one $host$1 $is_args$args}

This method restricts access; the module of proxy_cache_purge cache cleaning, the parameter of generating cache key specified by key_zone,$host$1 $is_args$args specified by cache_one

Storage

If there are large static files, these static files will not be modified, so we can let Nginx store these files directly without setting the validity period of the cache. If the upstream server modifies these files, a separate program can be provided to delete the corresponding static files.

Http {proxy_temp_path / var/www/tmp; server {root / var/www/data; location / img {error_page 404 = @ store} location @ store {internal; proxy_store on; proxy_store_access group:r all:r; proxy_pass http://upstream; }}}

The request will first look for the file in / img, and then go to the upstream server if it does not exist; the internal directive is used to specify that only internal calls from the local Nginx are allowed, and external access will directly return the 404 not found status. Proxy_store indicates that the files returned from the upstream server need to be stored in / var/www/data; proxy_store_access to set access permissions

This is the end of "how to understand caching". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report