mirror of
https://github.com/telemt/telemt.git
synced 2026-11-01 21:31:58 +03:00
CAS Contention in Traffic Bucket bounded
This commit is contained in:
@@ -33,45 +33,91 @@ const REGISTRY_SHARDS: usize = 64;
|
||||
const FAIR_EPOCH_MS: u64 = 20;
|
||||
const MAX_BORROW_CHUNK_BYTES: u64 = 32 * 1024;
|
||||
const CLEANUP_INTERVAL_SECS: u64 = 60;
|
||||
const RESERVE_CAS_ATTEMPT_LIMIT: usize = 16;
|
||||
const REFUND_CAS_ATTEMPT_LIMIT: usize = 8;
|
||||
const PACKED_USAGE_BITS: u32 = 28;
|
||||
const PACKED_USAGE_MASK: u64 = (1u64 << PACKED_USAGE_BITS) - 1;
|
||||
const PACKED_EPOCH_MAX: u64 = (1u64 << (u64::BITS - PACKED_USAGE_BITS)) - 1;
|
||||
|
||||
/// Traffic direction used by rate-limit accounting.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum RateDirection {
|
||||
/// Traffic received from a client.
|
||||
Up,
|
||||
/// Traffic sent to a client.
|
||||
Down,
|
||||
}
|
||||
|
||||
/// Result of an immediate traffic-budget request.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct TrafficConsumeResult {
|
||||
/// Number of bytes granted by all applicable limits.
|
||||
pub granted: u64,
|
||||
/// Whether the per-user limit prevented a grant.
|
||||
pub blocked_user: bool,
|
||||
/// Whether the per-CIDR limit prevented a grant.
|
||||
pub blocked_cidr: bool,
|
||||
}
|
||||
|
||||
/// Process-wide traffic-limiter counters and gauges.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct TrafficLimiterMetricsSnapshot {
|
||||
/// Per-user upload throttle events.
|
||||
pub user_throttle_up_total: u64,
|
||||
/// Per-user download throttle events.
|
||||
pub user_throttle_down_total: u64,
|
||||
/// Per-CIDR upload throttle events.
|
||||
pub cidr_throttle_up_total: u64,
|
||||
/// Per-CIDR download throttle events.
|
||||
pub cidr_throttle_down_total: u64,
|
||||
/// Per-user accumulated upload wait time in milliseconds.
|
||||
pub user_wait_up_ms_total: u64,
|
||||
/// Per-user accumulated download wait time in milliseconds.
|
||||
pub user_wait_down_ms_total: u64,
|
||||
/// Per-CIDR accumulated upload wait time in milliseconds.
|
||||
pub cidr_wait_up_ms_total: u64,
|
||||
/// Per-CIDR accumulated download wait time in milliseconds.
|
||||
pub cidr_wait_down_ms_total: u64,
|
||||
/// Per-user upload reservations that exhausted their CAS budget.
|
||||
pub user_reserve_cas_retry_exhausted_up_total: u64,
|
||||
/// Per-user download reservations that exhausted their CAS budget.
|
||||
pub user_reserve_cas_retry_exhausted_down_total: u64,
|
||||
/// Per-user upload refunds that exhausted their CAS budget.
|
||||
pub user_refund_cas_retry_exhausted_up_total: u64,
|
||||
/// Per-user download refunds that exhausted their CAS budget.
|
||||
pub user_refund_cas_retry_exhausted_down_total: u64,
|
||||
/// Per-CIDR upload reservations that exhausted their CAS budget.
|
||||
pub cidr_reserve_cas_retry_exhausted_up_total: u64,
|
||||
/// Per-CIDR download reservations that exhausted their CAS budget.
|
||||
pub cidr_reserve_cas_retry_exhausted_down_total: u64,
|
||||
/// Per-CIDR upload refunds that exhausted their CAS budget.
|
||||
pub cidr_refund_cas_retry_exhausted_up_total: u64,
|
||||
/// Per-CIDR download refunds that exhausted their CAS budget.
|
||||
pub cidr_refund_cas_retry_exhausted_down_total: u64,
|
||||
/// Active leases with a per-user rate limit.
|
||||
pub user_active_leases: u64,
|
||||
/// Active leases with a per-CIDR rate limit.
|
||||
pub cidr_active_leases: u64,
|
||||
/// Configured per-user rate-limit entries.
|
||||
pub user_policy_entries: u64,
|
||||
/// Configured per-CIDR rate-limit entries.
|
||||
pub cidr_policy_entries: u64,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct CasContentionMetrics {
|
||||
reserve_exhausted_total: AtomicU64,
|
||||
refund_exhausted_total: AtomicU64,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ScopeMetrics {
|
||||
throttle_up_total: AtomicU64,
|
||||
throttle_down_total: AtomicU64,
|
||||
wait_up_ms_total: AtomicU64,
|
||||
wait_down_ms_total: AtomicU64,
|
||||
contention_up: Arc<CasContentionMetrics>,
|
||||
contention_down: Arc<CasContentionMetrics>,
|
||||
active_leases: AtomicU64,
|
||||
policy_entries: AtomicU64,
|
||||
}
|
||||
@@ -86,6 +132,54 @@ struct AtomicRatePair {
|
||||
#[derive(Default)]
|
||||
struct DirectionBucket {
|
||||
state: AtomicU64,
|
||||
contention: Arc<CasContentionMetrics>,
|
||||
#[cfg(test)]
|
||||
forced_reserve_failures: AtomicU64,
|
||||
#[cfg(test)]
|
||||
forced_refund_failures: AtomicU64,
|
||||
#[cfg(test)]
|
||||
reserve_cas_attempts: AtomicU64,
|
||||
#[cfg(test)]
|
||||
refund_cas_attempts: AtomicU64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum BucketReserveError {
|
||||
StaleEpoch,
|
||||
Contended,
|
||||
RefundContended,
|
||||
ReserveAndRefundContended,
|
||||
FairShareContended,
|
||||
}
|
||||
|
||||
impl BucketReserveError {
|
||||
fn exhausted_reserve_budget(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Contended | Self::ReserveAndRefundContended
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum BucketRefundOutcome {
|
||||
Complete,
|
||||
Contended,
|
||||
}
|
||||
|
||||
struct ReserveCasBudget {
|
||||
remaining: usize,
|
||||
}
|
||||
|
||||
struct BucketReservation {
|
||||
granted: u64,
|
||||
debit: Option<DirectionDebit>,
|
||||
}
|
||||
|
||||
struct CidrReservation {
|
||||
granted: u64,
|
||||
aggregate_debit: Option<DirectionDebit>,
|
||||
user_debit: Option<DirectionDebit>,
|
||||
}
|
||||
|
||||
struct UserBucket {
|
||||
@@ -95,13 +189,11 @@ struct UserBucket {
|
||||
active_leases: AtomicU64,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct CidrDirectionBucket {
|
||||
used: Arc<DirectionBucket>,
|
||||
active_users: Arc<DirectionBucket>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct CidrUserDirectionState {
|
||||
used: Arc<DirectionBucket>,
|
||||
}
|
||||
@@ -165,6 +257,7 @@ struct TrafficLeaseBinding {
|
||||
cidr_user_share: Option<Arc<CidrUserShare>>,
|
||||
}
|
||||
|
||||
/// A live traffic-limiter binding for one authenticated client session.
|
||||
pub struct TrafficLease {
|
||||
limiter: Arc<TrafficLimiter>,
|
||||
user: String,
|
||||
@@ -173,6 +266,7 @@ pub struct TrafficLease {
|
||||
refresh: ParkingMutex<()>,
|
||||
}
|
||||
|
||||
/// Owns rate-limit policy, shared buckets, and limiter telemetry.
|
||||
pub struct TrafficLimiter {
|
||||
policy: ArcSwap<PolicySnapshot>,
|
||||
policy_update: ParkingMutex<()>,
|
||||
|
||||
Reference in New Issue
Block a user