Add max cache item size.

This commit is contained in:
Ara Sadoyan
2026-10-23 15:27:23 +02:00
parent 56c41e2c19
commit 72756a00dd
8 changed files with 32 additions and 6 deletions
Generated
+1 -1
View File
@@ -130,7 +130,7 @@ checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
[[package]]
name = "aralez"
version = "0.95.1"
version = "0.95.2"
dependencies = [
"ahash",
"anyhow",
+1
View File
@@ -87,6 +87,7 @@ Built on Rust, on top of **Cloudflare’s Pingora engine**, **Aralez** delivers
| **cache_size_mb** | `50` | Optional. Enable internal cache with size in megabytes of value. Cache is entirely disabled when this line is commented out. |
| **cache_enabled** | `bool` | Optional. Disabled by default |
| **cache_storage** | `memory, redis://host:port` | Optional Defaults to memory works with Redis, Valkey, Dragonfly (requires redis:// prefix) |
| **cache_item_max_size** | `5` | Optional. Set maximum size for cached items in megabytes. Defaults to 0 , no max size. |
| **cache_ttl** | `60` | Optional. Set internal cache with size in megabytes of value. Defaults to 50Mb if cache_enabled: true |
| **tcp_keepalive_idle** | `60` | Seconds of inactivity before the kernel starts sending keepalive probes to a downstream client. Defaults to 60 |
| **tcp_keepalive_interval** | `10` | Seconds between individual keepalive probes if the client does not respond. Defaults to 10 |
+1
View File
@@ -10,6 +10,7 @@ cache_enabled: true # Optional. Disabled by default
cache_storage: memory # memory | redis://host:port . Optional Defaults to memory works with Redis, Valkey, Dragonfly (requires redis:// prefix)
cache_size_mb: 50 # Optional. Set internal cache with size in megabytes of value. Defaults to 50Mb if cache_enabled: true
cache_ttl: 60 # Optional. Set Default TTL in seconds for cached items, works if cache control headers are not set via upstream. Defaults to 60 if cache_enabled: true
cache_item_max_size: 5 # Optional. Set maximum size for cached items in megabytes. Defaults to 0 , no max size.
config_api_enabled: true # Boolean to enable/disable remote config push capability.
config_address: 127.0.0.1:3000 # HTTP API address for pushing upstreams.yaml from remote location
proxy_address_http: 0.0.0.0:80 # Proxy HTTP bind address
+6 -2
View File
@@ -170,9 +170,13 @@ impl Storage for RedisCache {
let (internal_bytes, header_bytes) = meta.serialize()?;
let mut conn = (*self.client).clone();
let _: RedisResult<()> = conn.set_ex(&internal_key, &internal_bytes, ttl).await;
let _: RedisResult<()> = conn.set_ex(&header_key, &header_bytes, ttl).await;
if let Err(e) = conn.set_ex::<_, _, ()>(&internal_key, &internal_bytes, ttl).await {
log::error!("Failed to cache body to Redis: {}", e);
}
if let Err(e) = conn.set_ex::<_, _, ()>(&header_key, &header_bytes, ttl).await {
log::error!("Failed to cache headers to Redis: {}", e);
}
Ok(Box::new(RedisMissHandler {
client: self.client.clone(),
body_key,
+2 -1
View File
@@ -21,7 +21,8 @@ pub async fn init_cache(config: Arc<AppConfig>) {
CACHE_TTL.set(ttl).ok();
if let Some(size) = config.cache_size_mb {
let cache_size = size * 1024 * 1024;
drop(EVICTION.set(Manager::new(cache_size)));
let manager = Manager::new(cache_size);
let _ = EVICTION.set(manager);
}
GLOBAL_STORAGE.set(Box::new(MemCache::new())).ok();
info!("Cache initialized successfully. Storage: {}", cache_storage);
+17 -1
View File
@@ -13,7 +13,7 @@ use pingora::ErrorSource::Upstream;
use pingora::http::{Method, RequestHeader, ResponseHeader, StatusCode};
use pingora::prelude::*;
use pingora_cache::cache_control::CacheControl;
use pingora_cache::{CacheKey, CacheMetaDefaults, RespCacheable};
use pingora_cache::{CacheKey, CacheMetaDefaults, NoCacheReason, RespCacheable};
use pingora_core::listeners::ALPN;
use pingora_core::prelude::HttpPeer;
use pingora_proxy::{ProxyHttp, Session};
@@ -89,6 +89,22 @@ impl ProxyHttp for LB {
Ok(())
}
fn response_cache_filter(&self, _session: &Session, resp: &ResponseHeader, _ctx: &mut Self::CTX) -> Result<RespCacheable> {
if let Some(item_size) = self.config.cache_item_max_size {
if let Some(content_length_str) = resp.headers.get("content-length") {
match content_length_str.to_str().ok().and_then(|s| s.parse::<usize>().ok()) {
Some(content_length) => {
if content_length > item_size {
return Ok(RespCacheable::Uncacheable(NoCacheReason::Custom("Response too large")));
}
}
None => {
return Ok(RespCacheable::Uncacheable(NoCacheReason::Custom("Response too large")));
}
}
} else {
return Ok(RespCacheable::Uncacheable(NoCacheReason::Custom("Response too large")));
}
};
let cc = CacheControl::from_resp_headers(resp);
let defaults = CacheMetaDefaults::new(
|status| {
+3 -1
View File
@@ -281,7 +281,9 @@ pub fn parce_main_config(path: &str) -> AppConfig {
} else if let Ok(jwt_key) = env::var("JWT_KEY") {
cfo.master_key = Some(jwt_key);
};
if let Some(cs) = cfo.cache_item_max_size {
cfo.cache_item_max_size = Some(cs * 1024 * 1024);
}
// log_builder(&cfo, &cfo.log_file);
cfo.hc_method = cfo.hc_method.to_uppercase();
if let Some((ip, port_str)) = cfo.config_address.rsplit_once(':') {
+1
View File
@@ -115,6 +115,7 @@ pub struct AppConfig {
pub cache_enabled: Option<bool>,
pub cache_storage: Option<String>,
pub cache_size_mb: Option<usize>,
pub cache_item_max_size: Option<usize>,
pub cache_ttl: Option<u64>,
pub access_log: Option<String>,
pub pid_file: Option<String>,