The YAML configuration snippet provided is using a custom
filter called ThrottlingFilter and a RewritePath filter. To ensure that the ThrottlingFilter
is properly registered and integrated with your Spring Cloud Gateway, let's
break down the configuration steps:
Full YAML Configuration Example:
yaml
spring: cloud: gateway: routes: - id: throttled_route uri: http://localhost:8083 predicates: - Path=/service/throttle/** filters: -
RewritePath=/service/throttle(?<segment>/?.*), $\{segment} - name: ThrottlingFilter # Custom filter registered in your code args: maxRequests: 5 # Maximum allowed requests per time
window timeWindow: 10s # Time window in seconds |
Explanation of the Filters:
- RewritePath:
- This
filter rewrites the path of incoming requests by using regex.
- The
part /service/throttle(?<segment>/?.*) matches the incoming request
path and extracts the remaining part into a named group called segment.
- $\{segment}
dynamically replaces the matched group in the final URL.
- ThrottlingFilter:
- This
custom filter applies rate-limiting logic by reading maxRequests and timeWindow
from the YAML configuration.
- You
need to implement the actual logic of the ThrottlingFilter in Java.
Custom ThrottlingFilter Implementation in Java:
Here’s an example of how to create a ThrottlingFilter in
Java that reads values from the YAML configuration and implements throttling:
java
import
org.springframework.cloud.gateway.filter.GatewayFilter; import
org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import
org.springframework.http.HttpStatus; import
org.springframework.stereotype.Component; import
reactor.core.publisher.Mono; import
java.time.Duration; import
java.util.concurrent.ConcurrentHashMap; import
java.util.concurrent.atomic.AtomicInteger; @Component public class
ThrottlingFilter extends
AbstractGatewayFilterFactory<ThrottlingFilter.Config> { public static class Config { private int maxRequests; private Duration timeWindow; // Getters and setters public int getMaxRequests() { return maxRequests; } public void setMaxRequests(int
maxRequests) { this.maxRequests = maxRequests; } public Duration getTimeWindow() { return timeWindow; } public void setTimeWindow(Duration
timeWindow) { this.timeWindow = timeWindow; } } // Store request counts and start times
per client IP private final
ConcurrentHashMap<String, AtomicInteger> requestCounts = new
ConcurrentHashMap<>(); private final
ConcurrentHashMap<String, Long> windowStartTimes = new
ConcurrentHashMap<>(); public ThrottlingFilter() { super(Config.class); } @Override public GatewayFilter apply(Config config)
{ return (exchange, chain) -> { String clientIp =
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); long currentTime =
System.currentTimeMillis();
windowStartTimes.putIfAbsent(clientIp, currentTime);
requestCounts.putIfAbsent(clientIp, new AtomicInteger(0)); long windowStartTime =
windowStartTimes.get(clientIp); AtomicInteger requestCount =
requestCounts.get(clientIp); // Check if time window has
expired if (currentTime - windowStartTime
> config.getTimeWindow().toMillis()) { // Reset the window and count
windowStartTimes.put(clientIp, currentTime); requestCount.set(0); } // Increment the request count
and check if it exceeds the limit if
(requestCount.incrementAndGet() > config.getMaxRequests()) { // Too many requests, return
429 (Too Many Requests)
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); return
exchange.getResponse().setComplete(); } // Continue the filter chain return chain.filter(exchange); }; } } |
Key Points:
- Config
class: This class holds the parameters (maxRequests and timeWindow)
from the YAML configuration.
- ConcurrentHashMap:
Used to keep track of request counts and time windows for each client IP.
- Throttling
logic: If the number of requests exceeds maxRequests within timeWindow,
it returns HTTP 429 (Too Many Requests).
How it Works:
- The
YAML configuration passes maxRequests and timeWindow values to the filter.
- Each
client is tracked by their IP address, and the number of requests made
within the time window is counted.
- If
the request count exceeds the configured limit, the filter returns a 429
status to throttle the request.
Dependencies in pom.xml:
Ensure you have the necessary dependencies in your pom.xml:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId> </dependency> |
This will ensure that the ThrottlingFilter is correctly
integrated with Spring Cloud Gateway.
Testing the Setup:
To test, you can send multiple requests to http://localhost:8083/service/throttle/**.
After 5 requests within 10 seconds (based on the configuration), subsequent
requests should be rejected with a 429 (Too Many Requests) status. After 10
seconds, the request counter resets, and requests can be made again.
In Spring Cloud Gateway (SCG), the RewritePath filter is
used to rewrite the request path before forwarding it to the backend service.
This can be useful when your gateway needs to forward requests to backend
services where the path structure is different from the incoming requests. You
can use regular expressions and path variables to define how the rewriting
should work.
Here are some examples of different types of RewritePath
usage and explanations:
Basic Syntax of RewritePath:
yaml
filters:
- RewritePath=/<regex>, /<replacement> |
- <regex>:
A regular expression used to match the incoming request path.
- <replacement>:
The replacement path that will be sent to the backend service.
Example 1: Simple Path Replacement
YAML Configuration:
yaml
spring: cloud: gateway: routes: - id: simple_rewrite uri: http://localhost:8080 predicates: - Path=/api/v1/customers/** filters: -
RewritePath=/api/v1/customers/(?<segment>.*), /customers/${segment} |
Explanation:
- Incoming
Request: /api/v1/customers/123
- Regex:
/api/v1/customers/(?<segment>.*) captures everything after /api/v1/customers/
in the group segment.
- Replacement:
/customers/${segment} rewrites the path by replacing /api/v1/customers/
with /customers/.
- Forwarded
Request: /customers/123
This example rewrites the incoming path so that the backend
service receives a cleaner or differently structured URL.
Example 2: Remove a Section of the Path
YAML Configuration:
yaml
spring: cloud: gateway: routes: - id: remove_section uri: http://localhost:8080 predicates: - Path=/internal/service/** filters: -
RewritePath=/internal/service/(?<segment>.*), /${segment} |
Explanation:
- Incoming
Request: /internal/service/orders/567
- Regex:
/internal/service/(?<segment>.*) matches the path after /internal/service/
and stores it in the segment.
- Replacement:
/${segment} removes /internal/service and leaves just the remaining part
of the path.
- Forwarded
Request: /orders/567
Here, we remove the /internal/service part of the path when
forwarding the request to the backend service.
Example 3: Add a Prefix to the Path
YAML Configuration:
yaml
spring: cloud: gateway: routes: - id: add_prefix uri: http://localhost:8080 predicates: - Path=/products/** filters: -
RewritePath=/products/(?<segment>.*), /api/v2/products/${segment} |
Explanation:
- Incoming
Request: /products/789
- Regex:
/products/(?<segment>.*) captures the part of the path after /products/.
- Replacement:
/api/v2/products/${segment} adds a prefix (/api/v2/) to the original path.
- Forwarded
Request: /api/v2/products/789
This example shows how to add a new prefix to the request
path before it reaches the backend.
Example 4: Change a Subpath Using Regex Groups
YAML Configuration:
yaml
spring: cloud: gateway: routes: - id: subpath_rewrite uri: http://localhost:8080 predicates: -
Path=/store/(category|product)/(?<id>\d+) filters: -
RewritePath=/store/(category|product)/(?<id>\d+), /api/$1/${id} |
Explanation:
- Incoming
Request: /store/category/42
- Regex:
/store/(category|product)/(?<id>\d+) captures either category or product
and stores it in $1. The digits after that are stored in the named group id.
- Replacement:
/api/$1/${id} rewrites the path to /api/category/42.
- Forwarded
Request: /api/category/42
This example demonstrates the use of multiple regex groups
to capture different parts of the path and use them in the replacement string.
Example 5: Complex Path Rewriting with Multiple Groups
YAML Configuration:
yaml
spring: cloud: gateway: routes: - id: complex_rewrite uri: http://localhost:8080 predicates: -
Path=/company/(?<companyId>\d+)/employee/(?<employeeId>\d+) filters: -
RewritePath=/company/(?<companyId>\d+)/employee/(?<employeeId>\d+),
/employee/${employeeId}/company/${companyId} |
Explanation:
- Incoming
Request: /company/123/employee/456
- Regex:
/company/(?<companyId>\d+)/employee/(?<employeeId>\d+)
captures 123 as companyId and 456 as employeeId.
- Replacement:
/employee/${employeeId}/company/${companyId} swaps the order of companyId
and employeeId in the path.
- Forwarded
Request: /employee/456/company/123
Here, we're capturing both companyId and employeeId and
changing the order of their appearance in the forwarded path.
Example 6: Redirect Based on Path Segments
YAML Configuration:
yaml
spring: cloud: gateway: routes: - id: dynamic_path_rewrite uri: http://localhost:8080 predicates: - Path=/app/{section}/{id} filters: -
RewritePath=/app/(?<section>.*)/(?<id>.*),
/newapp/${section}/${id} |
Explanation:
- Incoming
Request: /app/store/789
- Regex:
/app/(?<section>.*)/(?<id>.*) captures the section and id
parts.
- Replacement:
/newapp/${section}/${id} changes the URL prefix from /app to /newapp.
- Forwarded
Request: /newapp/store/789
This example changes the prefix of the path and keeps the
rest intact.
General Tips:
- Regex
Groups: You can use named capturing groups (?<name>) to capture
specific parts of the path and reuse them in the replacement.
- Replacement:
The replacement can be as simple or complex as needed, depending on the
requirements of the backend service.
- Debugging:
If you face issues with path rewriting, make sure to test your regular
expressions separately to ensure they work as expected.
These examples show how flexible and powerful the RewritePath
filter can be in SCG. It allows you to transform the path of the incoming
request based on your backend’s requirements, making it easier to work with
different services and URLs.
Flowchart ThrottlingFilter with RewritePath filter in cloud gateway |
Sequence Diagram ThrottlingFilter with RewritePath filter in cloud gateway |
For More Related information, visit
Ø Mastering Debounce, Throttle, Rate Limit & Backoff in Java
Ø Setting
up Custom Filters using Debouncing, Throttling, Rate Limiting, and Exponential
Backoff
Ø Custom
gateway filters in Spring Cloud Gateway
Ø Custom
Filters in Microservices
Ø Mastering
Debounce, Throttle, Rate Limit & Backoff in Java
Ø Microservices:
Custom Filters for Debouncing, Throttling, Rate Limits & Backoff
Ø Spring
Cloud Gateway uses a RewritePath filter
For More DSA Related information, visit
Ø
Bench
mark of compiler using Ackerman function
Ø
To
check if the rows of a matrix are circularly identical in Java
Ø
Frequency
Weaving Logic & Spiral Printing of a Rectangle
Ø
Zig Zag
Matrix print multiple way
Ø
Gready
Algorithm’s or knapsack algorithms
Ø
understanding
recursive method for binary tree
Ø
Dynamic
Programming: Max Square Sub-matrix of 1s in a Matrix
Ø
Previous and
Next Date Palindrome
Ø
Karatsuba's
Algorithm for multiplying two large numbers
Ø
Multiplication
In different Way
Ø
Time
Analysis for Congested Routes Using Shortest Path Algorithms
Ø
Sorting
Of a list multiple attribute wise two technique
Ø
Seat
Arrangement in Sorting Order Like 1A-1E, 3C-3G etc
For More Java Related information, visit
Ø
Streams
Lambdas Collectors and Functional Interfaces in Java 8
Ø
Java
8 support static method or default method or both in the interface
Ø
Serialization
understanding
Ø
Garbage
Collection Under Standing
Ø
How
work Garbage Collection in Java
Ø
Under
Standing Of Mutable and Immutable Class
For Other information, visit
Ø
How
to get the neighbor of binary tree
Ø OWASP
(Open Web Application Security Project)
Ø Mastering
Debounce, Throttle, Rate Limit & Backoff in Java
Ø How
to draw sequence diagram and other diagrams using plantuml
Ø
Molecular
weight of chemistry in Java code
Ø
String
to xml or html Beautifier
Ø
Key
Components of Apache Kafka for Scalable Messaging
Ø
Build
a Video Stream Microservice with Kafka & REST API in Java
Ø
Kafka
general questions and answers
Ø
How
to convert XML to Object and Object to XML
Ø
To
securely obtain employee information utilizing TLS 1.3 or TLS 1.2
Ø
Convert
Floating-Point Values from SQL Server to Oracle in Java
Ø
Mastering
Design Patterns Practical Implementation Tips
0 Comments