Welcome! Log In Create A New Profile

Advanced

[PATCH] Disable ETag handling in slice filter

Timo Beckers
December 27, 2016 09:28AM
Hi,

We use Nginx to locally cache large binary content. Cache efficiency
is of high importance, so the slice filter is excellent for this
purpose! Here's a (very) short relevant configuration snippet for a
particular location we use:

slice 1m;
proxy_cache data;
proxy_pass http://$host$request_uri;
proxy_cache_key $uri$slice_range;
proxy_set_header Range $slice_range;

Since we've adopted the slice filter, we've been seeing a lot of 'etag
mismatch in slice response' errors because the upstream provider
serves content from multiple CDNs that provide the exact same URI
namespace. For example, consider the following resource:

/tpr/hs/data/7c/bf/7cbf4dbce9233a57ff6c1cbf84db77d8

Level3 serves this resource with ETag 74bc439-54261c855fd64.
Akamai serves this resource with ETag
1273157742232ec1b8d3afc4c41a2a9c:1480362585.

Since we value cache efficiency over anything else, adding the host to
the cache key is not an option. The alternative is pinning proxy_pass
to one specific CDN, but that approach has several other downsides.
So, I decided to try my hand at (slightly) altering the filter to make
it more configurable, I've posted the result below. Further
improvements might include:

- A (regex?) transformation for the ETag field, but that wouldn't be
useful in the scenario above
- exporting the ETag field out of the slice filter as a variable,
effectively making the cache mutable

'slice_etag' might be slightly too obscure to people unfamiliar with
the internals, perhaps 'slice_match_etag' would be more descriptive,
but I'll leave that up to the maintainers.

I've seen 'ngx_flag_t' in other *_conf_t typedefs, I hope that's
appropriate. I'm not a C programmer, but I did the best I could. Any
feedback is highly appreciated.


Take care,

Timo


# HG changeset patch
# User Timo Beckers <timo@incline.eu>
# Date 1482843958 -3600
# Tue Dec 27 14:05:58 2016 +0100
# Node ID 9e8c70191f0a9db9ad08bfb959fc1b1404d312ec
# Parent 54cf51c4f07add000b824036d4dce4bc60e67bcf
Slice filter: add slice_etag config var to disable etag handling

When caching 206 requests from multiple CDNs that serve identical resources
but have a different ETag scheme, this setting can be used to disable the
ETag checking during processing of response headers.

This comes in handy when seeing an excessive amount of 'etag mismatch in
slice response' errors and the cache is short-lived enough to ensure
clients don't receive stale content.

diff -r 54cf51c4f07a -r 9e8c70191f0a
src/http/modules/ngx_http_slice_filter_module.c
--- a/src/http/modules/ngx_http_slice_filter_module.c Mon Dec 26
14:27:05 2016 +0300
+++ b/src/http/modules/ngx_http_slice_filter_module.c Tue Dec 27
14:05:58 2016 +0100
@@ -12,6 +12,7 @@

typedef struct {
size_t size;
+ ngx_flag_t etag;
} ngx_http_slice_loc_conf_t;


@@ -48,6 +49,13 @@

static ngx_command_t ngx_http_slice_filter_commands[] = {

+ { ngx_string("slice_etag"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_slice_loc_conf_t, etag),
+ NULL },
+
{ ngx_string("slice"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
@@ -123,22 +131,26 @@
return NGX_ERROR;
}

- h = r->headers_out.etag;
+ slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module);

- if (ctx->etag.len) {
- if (h == NULL
- || h->value.len != ctx->etag.len
- || ngx_strncmp(h->value.data, ctx->etag.data, ctx->etag.len)
- != 0)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "etag mismatch in slice response");
- return NGX_ERROR;
+ if (slcf->etag) {
+ h = r->headers_out.etag;
+
+ if (ctx->etag.len) {
+ if (h == NULL
+ || h->value.len != ctx->etag.len
+ || ngx_strncmp(h->value.data, ctx->etag.data, ctx->etag.len)
+ != 0)
+ {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "etag mismatch in slice response");
+ return NGX_ERROR;
+ }
}
- }

- if (h) {
- ctx->etag = h->value;
+ if (h) {
+ ctx->etag = h->value;
+ }
}

if (ngx_http_slice_parse_content_range(r, &cr) != NGX_OK) {
@@ -157,8 +169,6 @@
"http slice response range: %O-%O/%O",
cr.start, cr.end, cr.complete_length);

- slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module);
-
end = ngx_min(cr.start + (off_t) slcf->size, cr.complete_length);

if (cr.start != ctx->start || cr.end != end) {
@@ -480,6 +490,7 @@
}

slcf->size = NGX_CONF_UNSET_SIZE;
+ slcf->etag = NGX_CONF_UNSET;

return slcf;
}
@@ -492,6 +503,7 @@
ngx_http_slice_loc_conf_t *conf = child;

ngx_conf_merge_size_value(conf->size, prev->size, 0);
+ ngx_conf_merge_off_value(conf->etag, prev->etag, 1);

return NGX_CONF_OK;
}
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[PATCH] Disable ETag handling in slice filter

Timo Beckers 1698 December 27, 2016 09:28AM

Re: [PATCH] Disable ETag handling in slice filter

Maxim Dounin 792 December 27, 2016 10:04AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 278
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready