Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion configs/volume.config.default
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,37 @@
# disk (assuming each disk has enough free space available).
#
# To create one volume of size 10% of the total cache space and
# another 1 Gig volume,
# another 1 Gig volume,
# volume=1 scheme=http size=10%
# volume=2 scheme=http size=1024
#
# Additional optional parameters:
#
# ramcache=true/false
# Enable or disable RAM cache for this volume (default: true)
#
# ram_cache_size=<size>
# Allocate a dedicated RAM cache pool for this volume (e.g., 512M, 2G)
# This amount is automatically subtracted from the global ram_cache.size
# setting, with the remainder shared among other volumes.
#
# ram_cache_cutoff=<size>
# Override the global ram_cache_cutoff for this volume (e.g., 64K, 1M)
# Objects larger than this will not be stored in RAM cache.
#
# avg_obj_size=<size>
# Override the global min_average_object_size for this volume
#
# fragment_size=<size>
# Override the global target_fragment_size for this volume (max: 4MB)
#
# Advanced RAM cache configuration examples:
#
# Example 1: Volume with dedicated 2GB RAM cache
# volume=1 scheme=http size=40% ram_cache_size=2G
#
# Example 2: Small objects with custom cutoff and dedicated RAM
# volume=2 scheme=http size=20% ram_cache_size=512M ram_cache_cutoff=64K
#
# Example 3: Large media with higher cutoff (shares remaining RAM pool)
# volume=3 scheme=http size=40% ram_cache_cutoff=1M
38 changes: 38 additions & 0 deletions doc/admin-guide/files/records.yaml.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2617,6 +2617,34 @@ Cache Control
used in determining the number of :term:`directory buckets <directory bucket>`
to allocate for the in-memory cache directory.

.. ts:cv:: CONFIG proxy.config.cache.default_volumes STRING ""

Specifies a comma-separated list of cache volume numbers to use as the default
for cache stripe selection when no more specific volume configuration applies.
For example, ``"1,2"`` would use volumes 1 and 2 as the default.

The volume selection priority order is:

1. ``@volume=`` directive in :file:`remap.config` (highest priority)
2. Hostname matching in :file:`hosting.config`
3. ``proxy.config.cache.default_volumes`` (if non-empty)
4. All available cache volumes (lowest priority)

An empty string (the default) disables this feature, causing |TS| to fall
back directly to using all available volumes when no other configuration
matches.

This is useful for scenarios where you want to restrict default caching to
specific volumes without configuring hostname patterns in :file:`hosting.config`.
For example, you might want to reserve certain volumes for specific remap rules
while having a different set of default volumes for all other traffic.

.. topic:: Example

Assign volumes 1 and 2 as defaults for general traffic ::

CONFIG proxy.config.cache.default_volumes STRING "1,2"

.. ts:cv:: CONFIG proxy.config.cache.permit.pinning INT 0
:reloadable:

Expand Down Expand Up @@ -2741,13 +2769,23 @@ RAM Cache
Alternatively, it can be set to a fixed value such as
**20GB** (21474836480)

This global setting can be overridden on a per-volume basis using the
``ram_cache_size`` parameter in :file:`volume.config`. Per-volume
allocations are subtracted from the total RAM cache size before
distributing the remainder among volumes without explicit settings.

.. ts:cv:: CONFIG proxy.config.cache.ram_cache_cutoff INT 4194304

Objects greater than this size will not be kept in the RAM cache.
This should be set high enough to keep objects accessed frequently
in memory in order to improve performance.
**4MB** (4194304)

This global setting can be overridden on a per-volume basis using the
``ram_cache_cutoff`` parameter in :file:`volume.config`. When set,
the per-volume cutoff takes precedence over this global setting for
that specific volume.

.. ts:cv:: CONFIG proxy.config.cache.ram_cache.algorithm INT 1

Two distinct RAM caches are supported, the default (1) being the simpler
Expand Down
48 changes: 48 additions & 0 deletions doc/admin-guide/files/remap.config.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,54 @@ will pass "1" and "2" to plugin1.so and "3" to plugin2.so.

This will pass "1" and "2" to plugin1.so and "3" to plugin2.so

.. _remap-config-cache-volume-selection:

Cache Volume Selection
======================

The ``@volume`` directive allows you to override the default cache volume selection
for specific remap rules, bypassing the hostname-based volume selection configured in
:file:`hosting.config`. This provides fine-grained control over which cache volumes
are used for different URL patterns.

Format
------

::

@volume=<volume_list>

Where ``<volume_list>`` can be either:

- A single volume number: ``@volume=4``
- Multiple comma-separated volume numbers: ``@volume=3,4,5``

Volume numbers must be between 1 and 255 (volume 0 is reserved and not usable).
All specified volumes must be defined in :file:`volume.config`.

Examples
--------

::

# Single volume for API requests (backward compatibility)
map https://api.example.com/ https://api-origin.example.com/ @volume=4

# Multiple volumes for load distribution across SSD volumes
map https://cdn.example.com/ https://cdn-origin.example.com/ @volume=2,3,4

# Single high-performance volume for critical services
map https://checkout.example.com/ https://checkout-origin.example.com/ @volume=1

# Everything else gets the default volume allocations (hosting.config rules)
map https://www.example.com/ https://origin.example.com/

.. note::

When using ``@volume``, ensure that the target volumes have appropriate disk space and
performance characteristics for the expected traffic patterns. For multiple volumes,
consider the combined capacity and performance of all specified volumes.

.. _remap-config-named-filters:

NextHop Selection Strategies
Expand Down
82 changes: 73 additions & 9 deletions doc/admin-guide/files/volume.config.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,65 @@ Optional directory entry sizing

You can also add an option ``avg_obj_size=<size>`` to the volume configuration
line. This overrides the global :ts:cv:`proxy.config.cache.min_average_object_size`
configuration for this volume. This is useful if you have a volume that is dedicated
for say very small objects, and you need a lot of directory entries to store them.
configuration for this volume. The size supports multipliers (K, M, G, T) for
convenience (e.g., ``avg_obj_size=64K`` or ``avg_obj_size=1M``). This is useful
if you have a volume that is dedicated for say very small objects, and you need
a lot of directory entries to store them.

Optional fragment size setting
------------------------------

You can also add an option ``fragment_size=<size>`` to the volume configuration
line. This overrides the global :ts:cv:`proxy.config.cache.target_fragment_size`
configuration for this volume. This allows for a smaller, or larger, fragment size
for a particular volume. This may be useful together with ``avg_obj_size`` as well,
since a larger fragment size could reduce the number of directory entries needed
for a large object.
configuration for this volume. The size supports multipliers (K, M, G, T) for
convenience (e.g., ``fragment_size=512K`` or ``fragment_size=2M``). This allows
for a smaller, or larger, fragment size for a particular volume. This may be
useful together with ``avg_obj_size`` as well, since a larger fragment size could
reduce the number of directory entries needed for a large object.

Note that this setting has a maximmum value of 4MB.
Note that this setting has a maximum value of 4MB.

Optional RAM cache size allocation
-----------------------------------

You can add an option ``ram_cache_size=<size>`` to the volume configuration line
to allocate a dedicated RAM cache pool for this volume. The size supports
multipliers (K, M, G, T) for convenience (e.g., ``ram_cache_size=512M`` or
``ram_cache_size=2G``). Setting ``ram_cache_size=0`` disables the RAM cache
for this volume, which is equivalent to ``ramcache=false``.

When ``ram_cache_size`` is specified for a volume, that amount is **automatically
subtracted** from the global :ts:cv:`proxy.config.cache.ram_cache.size` setting,
and the remainder is shared among volumes without private allocations. This ensures
total RAM cache usage never exceeds the configured global limit.

For example, if the global RAM cache size is 4GB and you allocate 1GB to volume 1
and 512MB to volume 2, the remaining 2.5GB will be distributed among other volumes
using the normal proportional allocation based on disk space.

**Important notes:**

* If the sum of all ``ram_cache_size`` allocations exceeds the global RAM cache size,
a warning is logged and the private allocations are disabled, falling back to
the standard shared allocation.
* This setting only takes effect when :ts:cv:`proxy.config.cache.ram_cache.size`
is set to a positive value (not ``-1`` for automatic sizing).

Optional RAM cache cutoff override
-----------------------------------

You can add an option ``ram_cache_cutoff=<size>`` to the volume configuration line
to override the global :ts:cv:`proxy.config.cache.ram_cache_cutoff` setting for
this specific volume. The size supports multipliers (K, M, G, T) for convenience
(e.g., ``ram_cache_cutoff=64K`` or ``ram_cache_cutoff=1M``).

This cutoff determines the maximum object size that will be stored in the RAM cache.
Objects larger than this size will only be stored on disk. Setting different cutoffs
per volume allows you to:

* Use larger cutoffs for volumes serving frequently accessed large objects
* Use smaller cutoffs for volumes with many small objects to maximize RAM cache hits
* Disable RAM caching entirely for certain objects by setting a very low cutoff

Exclusive spans and volume sizes
================================
Expand Down Expand Up @@ -126,5 +171,24 @@ ramcache has been disabled.::
volume=1 scheme=http size=20%
volume=2 scheme=http size=20%
volume=3 scheme=http size=20%
volume=4 scheme=http size=20% avg_obj_size=4096
volume=5 scheme=http size=20% ramcache=false fragment_size=524288
volume=4 scheme=http size=20% avg_obj_size=4K
volume=5 scheme=http size=20% ramcache=false fragment_size=512K

The following example shows advanced RAM cache configuration with dedicated
allocations and custom cutoffs::

# Volume 1: General content with 2GB dedicated RAM cache
volume=1 scheme=http size=40% ram_cache_size=2G

# Volume 2: Small API responses with custom cutoff and 512MB RAM cache
volume=2 scheme=http size=20% ram_cache_size=512M ram_cache_cutoff=64K

# Volume 3: Large media with higher cutoff for thumbnails
volume=3 scheme=http size=40% ram_cache_cutoff=1M

In this example, assuming a global ``proxy.config.cache.ram_cache.size`` of 4GB:

* Volume 1 gets a dedicated 2GB RAM cache allocation
* Volume 2 gets a dedicated 512MB RAM cache allocation and only caches objects up to 64KB
* Volume 3 shares from the remaining 1.5GB pool (4GB - 2GB - 512MB) and caches objects up to 1MB
* The automatic subtraction ensures total RAM usage stays within the 4GB limit
5 changes: 3 additions & 2 deletions include/iocore/cache/Cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct CacheDisk;
class URL;
class HTTPHdr;
class HTTPInfo;
struct CacheHostRecord;

using CacheHTTPHdr = HTTPHdr;
using CacheURL = URL;
Expand Down Expand Up @@ -83,9 +84,9 @@ struct CacheProcessor : public Processor {
Action *scan(Continuation *cont, std::string_view hostname = std::string_view{}, int KB_per_second = SCAN_KB_PER_SECOND);
Action *lookup(Continuation *cont, const HttpCacheKey *key, CacheFragType frag_type = CACHE_FRAG_TYPE_HTTP);
Action *open_read(Continuation *cont, const HttpCacheKey *key, CacheHTTPHdr *request, const HttpConfigAccessor *params,
CacheFragType frag_type = CACHE_FRAG_TYPE_HTTP);
CacheFragType frag_type = CACHE_FRAG_TYPE_HTTP, const CacheHostRecord *volume_host_rec = nullptr);
Action *open_write(Continuation *cont, const HttpCacheKey *key, CacheHTTPInfo *old_info, time_t pin_in_cache = 0,
CacheFragType frag_type = CACHE_FRAG_TYPE_HTTP);
CacheFragType frag_type = CACHE_FRAG_TYPE_HTTP, const CacheHostRecord *volume_host_rec = nullptr);
Action *remove(Continuation *cont, const HttpCacheKey *key, CacheFragType frag_type = CACHE_FRAG_TYPE_HTTP);

/** Mark physical disk/device/file as offline.
Expand Down
3 changes: 2 additions & 1 deletion include/proxy/ReverseProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ bool response_url_remap(HTTPHdr *response_header, UrlRewrite *table);
bool reloadUrlRewrite();
bool urlRewriteVerify();

int url_rewrite_CB(const char *name, RecDataT data_type, RecData data, void *cookie);
void init_remap_volume_host_records();
int url_rewrite_CB(const char *name, RecDataT data_type, RecData data, void *cookie);
8 changes: 6 additions & 2 deletions include/proxy/http/HttpTransact.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ using ink_time_t = time_t;

struct HttpConfigParams;
class HttpSM;
struct CacheHostRecord;

#include "iocore/net/ConnectionTracker.h"
#include "tscore/InkErrno.h"
Expand Down Expand Up @@ -493,6 +494,8 @@ class HttpTransact
URL *parent_selection_url = nullptr;
URL parent_selection_url_storage;

const CacheHostRecord *volume_host_rec = nullptr;

_CacheLookupInfo() {}
};

Expand Down Expand Up @@ -705,8 +708,9 @@ class HttpTransact

MgmtByte cache_open_write_fail_action = 0;

HttpConfigParams *http_config_param = nullptr;
CacheLookupInfo cache_info;
HttpConfigParams *http_config_param = nullptr;
CacheLookupInfo cache_info;

ResolveInfo dns_info;
RedirectInfo redirect_info;
ConnectionTracker::TxnState outbound_conn_track_state;
Expand Down
1 change: 1 addition & 0 deletions include/proxy/http/remap/RemapConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class UrlRewrite;
#define REMAP_OPTFLG_INTERNAL 0x0080u /* only allow internal requests to hit this remap */
#define REMAP_OPTFLG_IN_IP 0x0100u /* "in_ip=" option (used for ACL filtering)*/
#define REMAP_OPTFLG_STRATEGY 0x0200u /* "strategy=" the name of the nexthop selection strategy */
#define REMAP_OPTFLG_VOLUME 0x0400u /* "volume=" cache volume override */
#define REMAP_OPTFLG_MAP_ID 0x0800u /* associate a map ID with this rule */
#define REMAP_OPTFLG_INVERT 0x80000000u /* "invert" the rule (for src_ip and src_ip_category at least) */
#define REMAP_OPTFLG_ALL_FILTERS \
Expand Down
37 changes: 32 additions & 5 deletions include/proxy/http/remap/UrlMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#pragma once

#include <atomic>
#include <string>
#include <vector>

#include "tscore/ink_config.h"
Expand All @@ -36,6 +38,7 @@
#include "tscore/List.h"

class NextHopSelectionStrategy;
struct CacheHostRecord;

/**
* Used to store http referrer strings (and/or regexp)
Expand Down Expand Up @@ -112,20 +115,41 @@ class url_mapping
bool ip_allow_check_enabled_p = false;
acl_filter_rule *filter = nullptr; // acl filtering (linked list of rules)
LINK(url_mapping, link); // For use with the main Queue linked list holding all the mapping
NextHopSelectionStrategy *strategy = nullptr;
std::string remapKey;
std::atomic<uint64_t> _hitCount = 0; // counter can overflow
NextHopSelectionStrategy *strategy = nullptr;
std::string remapKey;
std::atomic<uint64_t> _hitCount = 0; // counter can overflow
std::atomic<CacheHostRecord *> volume_host_rec = nullptr;

CacheHostRecord *
getVolumeHostRec() const
{
return volume_host_rec.load(std::memory_order_acquire);
}

void
setVolume(const char *str)
{
if (str && *str) {
_volume_str = str;
}
}

const std::string &
getVolume() const
{
return _volume_str;
}

int
getRank() const
{
return _rank;
};
}
void
setRank(int rank)
{
_rank = rank;
};
}

void
setRemapKey()
Expand All @@ -145,9 +169,12 @@ class url_mapping
_hitCount++;
}

bool initVolumeHostRec(char *errbuf, size_t errbufsize);

private:
std::vector<RemapPluginInst *> _plugin_inst_list;
int _rank = 0;
std::string _volume_str;
};

/**
Expand Down
Loading