Overview
The Sentinel Service is Argos Mesh’s security monitoring microservice that provides real-time DDoS attack detection. It consumes sales events from the Orders service, analyzes traffic patterns using a sliding window rate limiting algorithm, and publishes alerts when suspicious behavior is detected.
Sentinel uses Virtual Threads (Project Loom) for high-throughput event processing and Redis for distributed state management.
Architecture
Service Responsibilities
Traffic Monitoring Consumes sales events and tracks request rates per IP address
Rate Limiting Enforces 50 requests per 10-second window using Redis counters
Threat Detection Identifies DDoS attacks and suspicious traffic patterns
Alert Publishing Publishes critical alerts to the Notify service
Core Components
SalesListener
The SalesListener is the entry point for all sales events from RabbitMQ:
@ Component
public class SalesListener {
private final TrafficAnalyzer analyzer ;
private final RabbitTemplate rabbitTemplate ;
private final RedisService redisService ;
@ RabbitListener ( queues = "argos.sales.queue" )
public void processSalesEvents ( ProductSoldInternalEvent data ) {
String ip = data . ipAddress ();
if ( redisService . isBanned (ip)) {
return ; // Skip processing for already banned IPs
}
if ( analyzer . processAndCheckLimit (ip)) {
AlertInternalEvent event = new AlertInternalEvent (
"Suspicious behavior" ,
ip,
"CRITICAL" ,
LocalDateTime . now ()
);
rabbitTemplate . convertAndSend (
RabbitMQConfig . ALERT_EXCHANGE ,
"argos.alert.security" ,
event
);
} else {
System . out . println ( "[ Sentinel🛡️ ] Normal traffic of the IP: " + ip);
}
}
}
Event Reception
Listens to the argos.sales.queue for ProductSoldInternalEvent messages
Blacklist Check
Immediately returns if the IP is already banned (early exit optimization)
Traffic Analysis
Delegates to TrafficAnalyzer to check if the IP exceeds rate limits
Alert Generation
If suspicious behavior is detected, publishes an AlertInternalEvent with CRITICAL severity
TrafficAnalyzer
The TrafficAnalyzer implements the rate limiting algorithm using Redis:
@ Component
public class TrafficAnalyzer {
private final RedisService redisService ;
private final StringRedisTemplate redisTemplate ;
private static final int LIMIT = 50 ;
private static final int WINDOW_SECONDS = 10 ;
private static final String RATE_PREFIX = "rate:ip:" ;
public boolean processAndCheckLimit ( String ip ) {
if ( redisService . isBanned (ip)) return true ;
String key = RATE_PREFIX + ip;
Long currentCount = redisTemplate . opsForValue (). increment (key);
if (currentCount != null && currentCount == 1 ) {
redisTemplate . expire (key, Duration . ofSeconds (WINDOW_SECONDS));
}
if (currentCount != null && currentCount > LIMIT) {
redisService . banIp (ip, 10 );
return true ;
}
return false ;
}
}
Rate Limiting Algorithm
Sentinel implements a sliding window rate limiter using Redis atomic operations:
Algorithm Overview
Configuration
Redis Keys
How It Works
Increment Counter
For each request, increment the Redis counter for the IP: Long currentCount = redisTemplate . opsForValue (). increment ( "rate:ip:127.0.0.1" );
Set Expiration
If this is the first request (count = 1), set a TTL of 10 seconds: if (currentCount == 1 ) {
redisTemplate . expire (key, Duration . ofSeconds ( 10 ));
}
Check Threshold
If the count exceeds 50 requests, ban the IP: if (currentCount > 50 ) {
redisService . banIp (ip, 10 ); // Ban for 10 minutes
return true ; // Suspicious behavior detected
}
Rate Limit Parameters private static final int LIMIT = 50 ;
private static final int WINDOW_SECONDS = 10 ;
Request Limit 50 requests per time window
Time Window 10 seconds sliding window
This configuration allows burst traffic up to 50 requests, then automatically bans the IP for 10 minutes if exceeded.
Key Structure Rate Limiting Key:
Value: Integer counter
TTL: 10 seconds
Purpose: Tracks requests in the current window
Blacklist Key: blacklist:ip:<IP_ADDRESS>
Value: “BANNED”
TTL: 10 minutes (600 seconds)
Purpose: Marks IPs banned for suspicious behavior
RedisService
The RedisService manages IP blacklisting:
@ Service
public class RedisService {
private final StringRedisTemplate redisTemplate ;
private static final String BLACKLIST_PREFIX = "blacklist:ip:" ;
// Block an IP address for a specified duration
public void banIp ( String ipAddress , long durationMinutes ) {
redisTemplate . opsForValue (). set (
BLACKLIST_PREFIX + ipAddress,
"BANNED" ,
Duration . ofMinutes (durationMinutes)
);
}
public boolean isBanned ( String ipAddress ) {
return Boolean . TRUE . equals (
redisTemplate . hasKey (BLACKLIST_PREFIX + ipAddress)
);
}
}
Key Methods:
banIp(): Adds an IP to the blacklist with a TTL of 10 minutes
isBanned(): Checks if an IP exists in the blacklist
The blacklist is shared across services - the Orders service also checks this Redis key before processing sales.
Event Schemas
Sentinel consumes sales events from the Orders service:
public record ProductSoldInternalEvent (
Long productID,
Integer quantity,
String ipAddress,
LocalDateTime timeStamp
) {}
Key Fields:
ipAddress: Used for rate limiting and DDoS detection
timeStamp: Records when the sale occurred
AlertInternalEvent (Output)
When suspicious behavior is detected, Sentinel publishes alerts:
public record AlertInternalEvent (
String type, // "Suspicious behavior"
String sourceIp, // "127.0.0.1"
String severity, // "CRITICAL"
LocalDateTime timeStamp
) {}
RabbitMQ Configuration
Sentinel configures two sets of queues and exchanges:
public static final String QUEUE_SALE = "argos.sales.queue" ;
public static final String EXCHANGE_SOLD = "shop.exchange" ;
public static final String RK_SALES = "shop.event.sold" ;
Sales Event Consumption Queue: argos.sales.queueExchange: shop.exchangeRouting Key: shop.event.soldReceives sales events from the Orders service
Output: Alert Queue
public static final String QUEUE_ALERT = "argos.alert.queue" ;
public static final String ALERT_EXCHANGE = "alert.exchange" ;
public static final String RK_ALERT = "argos.alert.#" ;
Alert Publishing Queue: argos.alert.queueExchange: alert.exchangeRouting Key: argos.alert.securityPublishes alerts consumed by the Notify service
Virtual Threads Configuration
Sentinel leverages Java 21 Virtual Threads for high-throughput message processing:
spring.threads.virtual.enabled =true
spring.rabbitmq.listener.simple.prefetch =1
Virtual Threads
Prefetch Configuration
Why Virtual Threads? Virtual Threads (Project Loom) enable Sentinel to handle thousands of concurrent messages efficiently:
Lightweight: Each message is processed on a virtual thread with minimal memory overhead
Scalable: Can handle high-volume traffic without thread pool exhaustion
Non-blocking: Ideal for I/O-heavy operations like Redis lookups
Virtual threads are automatically used by Spring Boot when spring.threads.virtual.enabled=true is set.
Prefetch Setting spring.rabbitmq.listener.simple.prefetch =1
The prefetch count of 1 ensures:
Fair distribution of messages across multiple instances
Backpressure handling prevents overwhelming the service
Sequential processing per consumer for consistent rate limiting
Traffic Flow
Security Features
DDoS Prevention Automatically detects and blocks IPs exceeding 50 requests per 10 seconds
Distributed State Uses Redis for shared blacklist across multiple service instances
Automatic Unbanning IPs are automatically unbanned after 10 minutes using Redis TTL
Real-time Alerts Immediately notifies operators of critical security events
Deployment Considerations
Redis Connection
Ensure Redis is accessible for distributed rate limiting
RabbitMQ Configuration
Configure connection to the message broker: spring.rabbitmq.host =message_broker
spring.rabbitmq.port =5672
spring.rabbitmq.username =admin
spring.rabbitmq.password =admin123
Java 21 Runtime
Virtual threads require Java 21 or later
Horizontal Scaling
Multiple Sentinel instances can run concurrently, sharing Redis state
Next Steps
Orders Service Learn about the service that generates sales events
Notify Service See how alerts are delivered to operators
Redis Configuration Configure the Redis cache layer
Rate Limiting Deep dive into rate limiting strategies