Last week, we experienced a sudden surge in traffic to our CDN origin server. The root cause was that a batch of files on the CDN had expired, triggering a massive number of origin fetches.
CDN Origin Fetch Process
- First Fetch: If the origin server returns a
Last-Modifiedheader, the CDN records it. - Subsequent Fetches (After Expiry): Once the cached file expires, if the origin previously returned a
Last-Modifiedheader, the CDN will access the origin using anIf-Modified-Sinceheader (containing the value from the originalLast-Modified). If the file has not changed, the origin returns a 304 status. However, if the origin did not return aLast-Modifiedheader initially, the CDN will download the entire file, and the origin returns a 200 status.
The traffic spike occurred because the origin server was not returning the Last-Modified header. The solution is to ensure the origin server returns this header.
However, there are several important considerations. Let’s examine the Nginx configuration preceding the origin server:
location ~ /(?<name>.+?)/.* {
expires 100d;
rewrite ^/.+?/(.*)$ /$1 break;
proxy_cache m_wdjcdn_com;
proxy_cache_key "$request_uri";
proxy_cache_valid 200 30d;
proxy_set_header Host $name.cdn.xxxx.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://new-source-nodes;
}
- Local Static Files: If the origin files are served directly from the local disk (using the
rootdirective) rather than being proxied to a backend viaproxy_pass, this issue does not arise. This is because Nginx fully supportsLast-ModifiedandIf-Modified-Sincesemantics for static files. - Proxy Cache Impact: Without the
proxy_cachedirective, even if the origin returns aLast-Modifiedheader, a 304 response will not be generated. This is because Nginx does not save the headers unless they are cached locally. When files are cached to the local disk, Nginx retains them, allowing it to return a 304 response. if_modified_sinceDirective: Nginx has a directive calledif_modified_since, which defaults toexact. This means the value of theIf-Modified-Sinceheader must exactly match the previously obtainedLast-Modifiedvalue; otherwise, a 200 response is sent. You can changeif_modified_sincetobefore, which allows theIf-Modified-Sincevalue to be greater than or equal to theLast-Modifiedvalue (i.e., indicating the resource has been updated).
http://nginx.org/en/docs/http/ngx_http_core_module.html