Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
a5ab633
Almost complete rewrite of cache filter
ravenblackx Jan 13, 2025
2c982ee
Spelling
ravenblackx Jan 13, 2025
a766637
Namespace
ravenblackx Jan 13, 2025
f83b3b5
Post headers to asyncclient rather than send, because can be off-thread
ravenblackx Jan 14, 2025
6c1ffcd
AsyncStreams are not done until either onComplete or onReset
ravenblackx Jan 14, 2025
1d04c63
Make cache function as upstream http filter
ravenblackx Jan 14, 2025
5bf9cbb
Revert "Make cache function as upstream http filter"
ravenblackx Jan 14, 2025
f284875
Small fixes, test fixes
ravenblackx Jan 17, 2025
2d0a94d
Beginnings of toggling back to cacheable after being marked uncacheable
ravenblackx Jan 21, 2025
9c833a4
cancelWrap sendHeaders
ravenblackx Jan 21, 2025
5668868
Make UpstreamRequest bound to single thread after create
ravenblackx Jan 22, 2025
9ae974c
Consistently use first subscriber for request
ravenblackx Jan 22, 2025
4c7554a
Change behavior of HEAD-with-validation to just pass through
ravenblackx Jan 22, 2025
178eed5
Extra cache behavior expectation
ravenblackx Jan 23, 2025
3bc6c8b
Fix an asan error during teardown, maybe
ravenblackx Jan 23, 2025
41dd93b
Fix overly sticky uncacheable state
ravenblackx Jan 23, 2025
cb02408
Remove uninitialized dispatcher
ravenblackx Jan 23, 2025
0616fae
Make gcc happy, shard to prevent asan timeout
ravenblackx Jan 24, 2025
45a5301
More debug logs on cache insert failure
ravenblackx Jan 24, 2025
38b1699
Re-add accidentally removed line
ravenblackx Jan 24, 2025
5dea2d3
redundant std::move
ravenblackx Jan 28, 2025
b6343a7
Improve validation behavior
ravenblackx Jan 28, 2025
3d8ad86
Remove unused function
ravenblackx Jan 28, 2025
6762da0
Add test for cacheabilityreset
ravenblackx Jan 28, 2025
64e8fd9
Make cache filter useable as upstream
ravenblackx Jan 30, 2025
569a4b6
Merge branch 'main' into cache_stream
ravenblackx Jan 30, 2025
8ab502e
Make integration test mount the filter as an upstream filter
ravenblackx Jan 31, 2025
ec44bfd
Revert "Make integration test mount the filter as an upstream filter"
ravenblackx Feb 3, 2025
fd1dc74
Revert "Make cache filter useable as upstream"
ravenblackx Feb 3, 2025
53674bb
Optimize the common case of only one reader
ravenblackx Feb 3, 2025
d642a99
Finer-grained stats
ravenblackx Feb 4, 2025
afc46a9
Add more stats, fix invalidation
ravenblackx Feb 14, 2025
9f58973
Format
ravenblackx Feb 14, 2025
d35b96b
Revert accidental free-field update
ravenblackx Feb 14, 2025
8965ad9
Add override_upstream_cluster to support using an internal listener
ravenblackx Feb 18, 2025
b1cd455
Fix eviction
ravenblackx Mar 4, 2025
aa85b4d
Merge branch 'main' into cache_stream
ravenblackx Mar 18, 2025
7ed6add
Streamed -> Follower
ravenblackx Mar 18, 2025
ebdbd94
Describe ActiveCache
ravenblackx Mar 18, 2025
9af8e6c
Separate counter for failed validation
ravenblackx Mar 18, 2025
fa9e8b7
Merge branch 'main' into cache_stream
ravenblackx Apr 10, 2025
f744159
Cache key cluster name should be the original cluster name not the ov…
ravenblackx Apr 10, 2025
8f04e09
Merge branch 'main' into cache_stream
ravenblackx Apr 10, 2025
59c5484
Work with internal listener that resolves cluster after the cache
ravenblackx Apr 15, 2025
63d05ce
Big renames, more comments
ravenblackx May 8, 2025
55825f8
Format
ravenblackx May 9, 2025
aa3f2ea
Remove unused HttpSourceFactory
ravenblackx May 12, 2025
0e3200d
CacheFilterConfig descriptive comment
ravenblackx May 12, 2025
f8896f4
Oops, re-add HttpSourcePtr
ravenblackx May 12, 2025
7f7b6fb
Clarify range request edge case
ravenblackx May 14, 2025
dbd8011
Treat responses with Vary header as uncacheable for now
ravenblackx Jun 5, 2025
19da023
Reduce readability to improve coverage
ravenblackx Jun 5, 2025
88ccd12
Improve coverage of upstream_request
ravenblackx Jun 5, 2025
530db1b
Improve range_utils coverage
ravenblackx Jun 5, 2025
a79461d
More coverage of pass-through upstream wrappers
ravenblackx Jun 5, 2025
8374cef
Log noise, to be reverted, trying to diagnose CI
ravenblackx Jun 6, 2025
c27c6f1
Remove unused requestCacheControl() accessor
ravenblackx Jun 6, 2025
b0bf569
Improve cache_sessions coverage
ravenblackx Jun 6, 2025
e4b6673
Revert "Log noise, to be reverted, trying to diagnose CI"
ravenblackx Jun 6, 2025
77f9a13
Noisy logs part 2, to be reverted
ravenblackx Jun 6, 2025
7a95d1b
Even more noisy logs, to be reverted
ravenblackx Jun 6, 2025
ef866ad
Even noisier, and with fixed integration test framework
ravenblackx Jun 9, 2025
bf78b76
Moar debug
ravenblackx Jun 9, 2025
e570629
More dispatcher exits
ravenblackx Jun 10, 2025
2c54ecf
Merge branch 'main' into cache_stream
ravenblackx Jun 11, 2025
09c9a34
Fix late-trailers on unknown-size responses
ravenblackx Jun 13, 2025
d85e551
Remove debug prints
ravenblackx Jun 13, 2025
2f90e9c
Merge branch 'main' into cache_stream
ravenblackx Jul 21, 2025
078adc2
Test coverage for cache implementations
ravenblackx Jul 21, 2025
31ca2ab
Assert instead of check, and fail harder on a bug
ravenblackx Jul 21, 2025
e99fa82
Coverage for cache_filter.cc's rangeFromHeaders
ravenblackx Jul 22, 2025
9926e4b
Revert accidental change to dns_cache_manager_impl
ravenblackx Jul 22, 2025
0cf22a6
Revert whitespace-only change to fake_upstream.cc
ravenblackx Jul 22, 2025
7172515
Test coverage for unlikely bad upstream response case
ravenblackx Jul 22, 2025
0b184d9
Update docs
ravenblackx Jul 22, 2025
5f1938f
Indent @type under typed_config
ravenblackx Jul 23, 2025
5c5b9d2
Merge remote-tracking branch 'upstream/main' into cache_stream
ravenblackx Jul 23, 2025
9ee59c2
changelog
ravenblackx Jul 23, 2025
bca8b92
Improve error logging
ravenblackx Sep 11, 2025
67f6ec6
Make unexpected path non-crashing because it happens
ravenblackx Sep 11, 2025
215a048
Older absl doesn't have message on StatusOr. Also avoid logging faile…
ravenblackx Sep 12, 2025
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
14 changes: 13 additions & 1 deletion api/envoy/extensions/filters/http/cache/v3/cache.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE;
// [#protodoc-title: HTTP Cache Filter]

// [#extension: envoy.filters.http.cache]
// [#next-free-field: 7]
// [#next-free-field: 8]
message CacheConfig {
option (udpa.annotations.versioning).previous_message_type =
"envoy.config.filter.http.cache.v2alpha.CacheConfig";
Expand Down Expand Up @@ -93,4 +93,16 @@ message CacheConfig {
// causes the cache to validate with its upstream even if the lookup is a hit. Setting this
// to true will ignore these headers.
bool ignore_request_cache_control_header = 6;

// If this is set, requests sent upstream to populate the cache will go to the
// specified cluster rather than the cluster selected by the vhost and route.
//
// If you have actions to be taken by the router filter - either
// ``upstream_http_filters`` or one of the ``RouteConfiguration`` actions such as
// ``response_headers_to_add`` - then the cache's side-channel going directly to the
// routed cluster will bypass these actions. You can set ``override_upstream_cluster``
// to an internal listener which duplicates the relevant ``RouteConfiguration``, to
// replicate the desired behavior on the side-channel upstream request issued by the
// cache.
string override_upstream_cluster = 7;
}
17 changes: 17 additions & 0 deletions changelogs/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@ date: Pending

behavior_changes:
# *Changes that are expected to cause an incompatibility if applicable; deployment changes are likely required*
- area: cache_filter
change: |
CacheFilter (WIP) has been completely reworked. Any existing cache implementations
will need to be modified to fit the new API. The new cache API is much simpler, as
individual cache implementations no longer need to comprehend various http headers,
only read and write at keys. Cache filter now handles "thundering herds" - if
multiple requests for the same resource arrive before the cache is populated,
now only one request goes upstream, and there is only one insert to the cache.
Range requests now convert to an upstream request for the entire resource, to
populate the cache.
Surprising behavior change may result if there are any active filters upstream
of a CacheFilter, including if RouteConfiguration does any actions
(e.g. adding headers) - it is recommended that for anything other than the most
simplistic configuration (for which the CacheFilter should be the furthest
upstream filter), a CacheFilter should be configured to make its requests
to an InternalListener which duplicates the RouteConfiguration and any filter
chain upstream of the CacheFilter. This is recognized as far from ideal.

minor_behavior_changes:
# *Changes that may cause incompatibilities for some users, but should not for most*
Expand Down
1 change: 1 addition & 0 deletions docs/root/_static/cache-filter-internal-listener.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
bootstrap_extensions:
- name: envoy.bootstrap.internal_listener
typed_config:
"@type": type.googleapis.com/envoy.extensions.bootstrap.internal_listener.v3.InternalListener
static_resources:
listeners:
- address:
socket_address:
address: 0.0.0.0
port_value: 8000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: AUTO
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
response_headers_to_add:
- header:
key: x-something
value: something
domains:
- "*"
routes:
- match:
prefix: "/service/1"
route:
cluster: service1
- match:
prefix: "/service/2"
route:
cluster: service2
http_filters:
- name: "envoy.filters.http.cache"
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.cache.v3.CacheConfig"
override_upstream_cluster: cache_internal_listener_cluster
typed_config:
"@type": "type.googleapis.com/envoy.extensions.http.cache.simple_http_cache.v3.SimpleHttpCacheConfig"
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
- name: cache_internal_listener
internal_listener: {}
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: AUTO
stat_prefix: cache_internal_listener
route_config:
name: local_route
virtual_hosts:
- name: backend
response_headers_to_add:
- header:
key: x-something
value: something
domains:
- "*"
routes:
- match:
prefix: "/service/1"
route:
cluster: service1
- match:
prefix: "/service/2"
route:
cluster: service2
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

clusters:
- name: service1
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service1
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: service1
port_value: 8000
- name: service2
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service2
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: service2
port_value: 8000
- name: cache_internal_listener_cluster
load_assignment:
cluster_name: cache_internal_listener_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
envoy_internal_address:
server_listener_name: cache_internal_listener
25 changes: 24 additions & 1 deletion docs/root/configuration/http/http_filters/cache_filter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,25 @@ Cache filter
upstream than the cache filter, while non-cacheable requests still go through the
listener filter chain. It is therefore recommended for consistency that only the
router filter should be further upstream in the listener filter chain than the
cache filter.
cache filter, and even then only if the router filter does not perform any mutations
such as if ``request_headers_to_add`` is set.

.. image:: /_static/cache-filter-chain.svg
:width: 80%
:align: center

* For more complex filter chains where some filters must be upstream of the cache
filter for correct behavior, or if the router filter is configured to perform
mutations via
:ref:`RouteConfiguration <envoy_v3_api_field_config.route.v3.RouteConfiguration.request_headers_to_add>`
the recommended way to configure this so that it works correctly is to configure
an internal listener which duplicates the part of the filter chain that is
upstream of the cache filter, and the ``RouteConfiguration``.

.. image:: /_static/cache-filter-internal-listener.svg
:width: 80%
:align: center

The HTTP Cache filter implements most of the complexity of HTTP caching semantics.

For HTTP Requests:
Expand Down Expand Up @@ -50,6 +63,16 @@ Example filter configuration with a ``SimpleHttpCache`` cache implementation:
:lineno-start: 29
:caption: :download:`http-cache-configuration.yaml <_include/http-cache-configuration.yaml>`

The more complicated filter chain configuration required if mutations occur upstream of the cache filter
involves duplicating the full route config into an internal listener (unfortunately this is currently unavoidable):

.. literalinclude:: _include/http-cache-configuration-internal-listener.yaml
:language: yaml
:lines: 38-113
:linenos:
:lineno-start: 38
:caption: :download:`http-cache-configuration-internal-listener.yaml <_include/http-cache-configuration-internal-listener.yaml>`

.. seealso::

:ref:`Envoy Cache Sandbox <install_sandboxes_cache_filter>`
Expand Down
107 changes: 86 additions & 21 deletions source/extensions/filters/http/cache/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,87 @@ licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_cc_library(
name = "http_source_interface",
hdrs = ["http_source.h"],
deps = [
"//envoy/buffer:buffer_interface",
"//envoy/http:header_map_interface",
"//source/extensions/filters/http/cache:range_utils_lib",
"@com_google_absl//absl/functional:any_invocable",
],
)

envoy_cc_library(
name = "upstream_request_lib",
srcs = ["upstream_request_impl.cc"],
hdrs = [
"upstream_request.h",
"upstream_request_impl.h",
],
deps = [
":http_source_interface",
":range_utils_lib",
":stats",
"//source/common/buffer:watermark_buffer_lib",
"//source/common/common:cancel_wrapper_lib",
"//source/common/common:logger_lib",
"@com_google_absl//absl/types:variant",
],
)

envoy_cc_library(
name = "cache_sessions_lib",
srcs = [
"cache_sessions.cc",
],
hdrs = [
"cache_sessions.h",
],
deps = [
":http_cache_lib",
":stats",
":upstream_request_lib",
"//source/common/http:utility_lib",
],
)

envoy_cc_library(
name = "cache_sessions_impl_lib",
srcs = [
"cache_sessions_impl.cc",
],
hdrs = [
"cache_sessions_impl.h",
],
deps = [
":cache_sessions_lib",
":cacheability_utils_lib",
":upstream_request_lib",
"//source/common/common:cancel_wrapper_lib",
],
)

envoy_cc_library(
name = "cache_filter_lib",
srcs = [
"cache_filter.cc",
"upstream_request.cc",
],
hdrs = [
"cache_filter.h",
"filter_state.h",
"upstream_request.h",
],
deps = [
":cache_custom_headers",
":cache_entry_utils_lib",
":cache_filter_logging_info_lib",
":cache_headers_utils_lib",
":cache_insert_queue_lib",
":cache_sessions_impl_lib",
":cache_sessions_lib",
":cacheability_utils_lib",
":http_cache_lib",
":stats",
":upstream_request_lib",
"//source/common/buffer:buffer_lib",
"//source/common/common:cancel_wrapper_lib",
"//source/common/common:enum_to_int",
"//source/common/common:logger_lib",
"//source/common/common:macros",
Expand Down Expand Up @@ -65,24 +127,13 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "cache_insert_queue_lib",
srcs = ["cache_insert_queue.cc"],
hdrs = ["cache_insert_queue.h"],
deps = [
":http_cache_lib",
"//source/common/buffer:buffer_lib",
],
)

envoy_cc_library(
name = "cache_policy_lib",
hdrs = ["cache_policy.h"],
deps = [
":cache_headers_utils_lib",
":http_cache_lib",
"//source/common/http:header_map_lib",
"//source/common/stream_info:filter_state_lib",
],
)

Expand All @@ -91,6 +142,15 @@ envoy_proto_library(
srcs = ["key.proto"],
)

envoy_cc_library(
name = "cache_progress_receiver_interface",
hdrs = ["cache_progress_receiver.h"],
deps = [
"//envoy/http:header_map_interface",
"//source/extensions/filters/http/cache:range_utils_lib",
],
)

envoy_cc_library(
name = "http_cache_lib",
srcs = ["http_cache.cc"],
Expand All @@ -99,6 +159,8 @@ envoy_cc_library(
":cache_custom_headers",
":cache_entry_utils_lib",
":cache_headers_utils_lib",
":cache_progress_receiver_interface",
":http_source_interface",
":key_cc_proto",
":range_utils_lib",
"//envoy/buffer:buffer_interface",
Expand Down Expand Up @@ -137,6 +199,7 @@ envoy_cc_library(
hdrs = ["cache_headers_utils.h"],
deps = [
":cache_custom_headers",
":key_cc_proto",
"//envoy/common:time_interface",
"//envoy/http:header_map_interface",
"//source/common/common:matchers_lib",
Expand All @@ -159,12 +222,12 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "cache_filter_logging_info_lib",
srcs = ["cache_filter_logging_info.cc"],
hdrs = ["cache_filter_logging_info.h"],
envoy_cc_extension(
name = "stats",
srcs = ["stats.cc"],
hdrs = ["stats.h"],
deps = [
"//source/common/stream_info:filter_state_lib",
":cache_entry_utils_lib",
],
)

Expand All @@ -174,6 +237,8 @@ envoy_cc_extension(
hdrs = ["config.h"],
deps = [
":cache_filter_lib",
":cache_sessions_lib",
":stats",
"//source/extensions/filters/http/common:factory_base_lib",
"@envoy_api//envoy/extensions/filters/http/cache/v3:pkg_cc_proto",
],
Expand Down
Loading
Loading