]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cache: Add a max-secondary-entries cache option
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Thu, 10 Dec 2020 16:58:43 +0000 (17:58 +0100)
committerWilliam Lallemand <wlallemand@haproxy.org>
Tue, 15 Dec 2020 15:35:09 +0000 (16:35 +0100)
This new option allows to tune the maximum number of simultaneous
entries with the same primary key in the cache (secondary entries).
When we try to store a response in the cache and there are already
max-secondary-entries living entries in the cache, the storage will
fail (but the response will still be sent to the client).
It defaults to 10 and does not have a maximum number.

doc/configuration.txt
src/cache.c

index ec1f2499885b46717328845404741a4b4a9398e6..e60e3428d9d097df7a6989a6356b11d315047f24 100644 (file)
@@ -14606,6 +14606,8 @@ The cache won't store and won't deliver objects in these cases:
 - If the response does not have an explicit expiration time (s-maxage or max-age
   Cache-Control directives or Expires header) or a validator (ETag or Last-Modified
   headers)
+- If the process-vary option is enabled and there are already max-secondary-entries
+  entries with the same primary key as the current response
 
 - If the request is not a GET
 - If the HTTP version of the request is smaller than 1.1
@@ -14636,7 +14638,7 @@ max-object-size <bytes>
   All objects with sizes larger than "max-object-size" will not be cached.
 
 max-age <seconds>
-  Define the maximum expiration duration. The expiration is set has the lowest
+  Define the maximum expiration duration. The expiration is set as the lowest
   value between the s-maxage or max-age (in this order) directive in the
   Cache-Control response header and this value. The default value is 60
   seconds, which means that you can't cache an object more than 60 seconds by
@@ -14649,6 +14651,11 @@ process-vary <0 or 1>
   (which might come with a cpu cost) which will be used to build a secondary key
   for a given request (see RFC 7234#4.1). The default value is 0 (disabled).
 
+max-secondary-entries <number>
+  Define the maximum number of simultaneous secondary entries with the same primary
+  key in the cache. This needs the vary support to be enabled. Its default value is 10
+  and should be passed a strictly positive integer.
+
 
 6.2.2. Proxy section
 ---------------------
index 60946decddbde1a3683704b09246f3bbd1fe4699..a833c044f2d8ee498166ebe5605b941240c3486f 100644 (file)
@@ -49,6 +49,7 @@ struct cache {
        unsigned int maxage;     /* max-age */
        unsigned int maxblocks;
        unsigned int maxobjsz;   /* max-object-size (in bytes) */
+       unsigned int max_secondary_entries;  /* maximum number of secondary entries with the same primary hash */
        uint8_t vary_processing_enabled;     /* boolean : manage Vary header (disabled by default) */
        char id[33];             /* cache name */
 };
@@ -104,7 +105,7 @@ struct cache_st {
        struct shared_block *first_block;
 };
 
-#define SECONDARY_ENTRY_MAX_COUNT 10
+#define DEFAULT_MAX_SECONDARY_ENTRY 10
 
 struct cache_entry {
        unsigned int complete;    /* An entry won't be valid until complete is not null. */
@@ -276,7 +277,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n
                entry_count = entry->secondary_entries_count;
                last_clear_ts = entry->last_clear_ts;
 
-               if (entry_count >= SECONDARY_ENTRY_MAX_COUNT) {
+               if (entry_count >= cache->max_secondary_entries) {
                        /* Some entries of the duplicate list might be expired so
                         * we will iterate over all the items in order to free some
                         * space. In order to avoid going over the same list too
@@ -291,7 +292,7 @@ static struct eb32_node *insert_entry(struct cache *cache, struct cache_entry *n
                        }
 
                        entry_count = clear_expired_duplicates(&prev);
-                       if (entry_count >= SECONDARY_ENTRY_MAX_COUNT) {
+                       if (entry_count >= cache->max_secondary_entries) {
                                /* Still too many entries for this primary key, delete
                                 * the newly inserted one. */
                                entry = container_of(prev, struct cache_entry, eb);
@@ -1800,6 +1801,7 @@ int cfg_parse_cache(const char *file, int linenum, char **args, int kwm)
                        tmp_cache_config->maxage = 60;
                        tmp_cache_config->maxblocks = 0;
                        tmp_cache_config->maxobjsz = 0;
+                       tmp_cache_config->max_secondary_entries = DEFAULT_MAX_SECONDARY_ENTRY;
                }
        } else if (strcmp(args[0], "total-max-size") == 0) {
                unsigned long int maxsize;
@@ -1877,6 +1879,29 @@ int cfg_parse_cache(const char *file, int linenum, char **args, int kwm)
                }
 
                tmp_cache_config->vary_processing_enabled = atoi(args[1]);
+       } else if (strcmp(args[0], "max-secondary-entries") == 0) {
+               unsigned int max_sec_entries;
+               char *err;
+
+               if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
+                       err_code |= ERR_ABORT;
+                       goto out;
+               }
+
+               if (!*args[1]) {
+                       ha_warning("parsing [%s:%d]: '%s' expects a strictly positive number.\n",
+                                  file, linenum, args[0]);
+                       err_code |= ERR_WARN;
+               }
+
+               max_sec_entries = strtoul(args[1], &err, 10);
+               if (err == args[1] || *err != '\0' || max_sec_entries == 0) {
+                       ha_warning("parsing [%s:%d]: max-secondary-entries wrong value '%s'\n",
+                                  file, linenum, args[1]);
+                       err_code |= ERR_ABORT;
+                       goto out;
+               }
+               tmp_cache_config->max_secondary_entries = max_sec_entries;
        }
        else if (*args[0] != 0) {
                ha_alert("parsing [%s:%d] : unknown keyword '%s' in 'cache' section\n", file, linenum, args[0]);