Integrate Microservice Gateway with Rate Limit Server¶
The microservice gateway supports integration with third-party rate limit servers. This document demonstrates the steps to integrate with the default rate limit server.
Prerequisites¶
Select a Rate Limit Server¶
You have the option to choose the default rate limit server or integrate your own.
Default Rate Limit Server¶
Apply the provided rate limit server template directly. For specific logic, refer to the rate limit server code.
Default Rate Limit Server
---
# NOTE: this deployment is intended for demonstrating global
# rate limiting functionality only and should NOT be considered
# production-ready.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: ratelimit
name: gateway-rls
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
# This value of maxSurge means that during a rolling update
# the new ReplicaSet will be created first.
maxSurge: 50%
selector:
matchLabels:
app: ratelimit
template:
metadata:
labels:
app: ratelimit
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchLabels:
app: ratelimit
topologyKey: kubernetes.io/hostname
weight: 100
containers:
- name: redis
image: release-ci.daocloud.io/skoala/redis:6.2.6
env:
- name: REDIS_SOCKET_TYPE
value: tcp
- name: REDIS_URL
value: redis:6379
- name: ratelimit
image: release-ci.daocloud.io/skoala/envoy-ratelimit:v2 # latest a/o Mar 24 2022
ports:
- containerPort: 8080
name: http
protocol: TCP
- containerPort: 8081
name: grpc
protocol: TCP
- containerPort: 6070
name: debug
protocol: TCP
volumeMounts:
- name: ratelimit-config
mountPath: /data/ratelimit/config
readOnly: true
env:
- name: USE_STATSD
value: "false"
- name: LOG_LEVEL
value: debug
- name: REDIS_SOCKET_TYPE
value: tcp
- name: REDIS_URL
value: localhost:6379
- name: RUNTIME_ROOT
value: /data
- name: RUNTIME_SUBDIRECTORY
value: ratelimit
- name: RUNTIME_WATCH_ROOT
value: "false"
# need to set RUNTIME_IGNOREDOTFILES to true to avoid issues with
# how Kubernetes mounts configmaps into pods.
- name: RUNTIME_IGNOREDOTFILES
value: "true"
command: ["/bin/ratelimit"]
livenessProbe:
httpGet:
path: /healthcheck
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
volumes:
- name: ratelimit-config
configMap:
name: gateway-rls
---
apiVersion: v1
kind: Service
metadata:
name: gateway-rls
spec:
ports:
- port: 8081
name: grpc
protocol: TCP
- port: 6070
name: debug
protocol: TCP
selector:
app: ratelimit
type: NodePort
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gateway-rls
data:
ratelimit-config.yaml: |
domain: gateway-rls.skoala-dev
descriptors:
- name: test1
key: foo
value: goo
rate_limit:
name: test1
unit: Minute
requests_per_unit: 20
descriptors:
- name: test2
key: foo1
value: goo1
rate_limit:
name: test2
unit: Minute
requests_per_unit: 15
descriptors:
- name: test3
key: foo2
value: goo2
rate_limit:
name: test3
unit: Minute
requests_per_unit: 10
Integrating with a Rate Limit Server¶
-
Obtain the external access address of the gateway-rls deployed in the previous steps.
Rate Limit Server address: 10.6.222.21:32003
Rate Limit Server configuration address: http://10.6.222.21:32004
-
Create a global rate limit plugin in the plugin center.
- Rate Limit Response Header: Enable printing rate limit-related information in the response header.
- Fast Success: Allow continuing to access requests when the rate limit server is unreachable.
- Access Address: The address of the rate limit server, corresponding to port 8081, with the GRPC protocol.
- Load Balancing Policy: Access policy for multiple rate limit servers.
- Configuration Retrieval Interface: Address for retrieving rate limit server configuration, corresponding to port 6070, with the HTTP protocol.
- Timeout: Timeout for the rate limit server response.
-
Configure the gateway with the global rate limit plugin.
-
Create a domain and enable global rate limiting.
-
Create an API under the gateway, enter the newly created domain in the "Associated Domain" field, set the path matching to "/", and deploy the API. The API will inherit the global rate limit configuration of the domain by default, but you can also customize the rate limit rules.
-
Now you can access the API through the rate limit server.
while true; do curl -w " http_code: %{http_code}" http://gateway.demo:30000/; let count+=1; echo " count: ${count}"; done
The access result is as follows: after accessing 10 times, it is rate limited.
adservice-springcloud: hello world! http_code: 200 count: 1 adservice-springcloud: hello world! http_code: 200 count: 2 adservice-springcloud: hello world! http_code: 200 count: 3 adservice-springcloud: hello world! http_code: 200 count: 4 adservice-springcloud: hello world! http_code: 200 count: 5 adservice-springcloud: hello world! http_code: 200 count: 6 adservice-springcloud: hello world! http_code: 200 count: 7 adservice-springcloud: hello world! http_code: 200 count: 8 adservice-springcloud: hello world! http_code: 200 count: 9 adservice-springcloud: hello world! http_code: 200 count: 10 http_code: 429 count: 11 http_code: 429 count: 12 http_code: 429 count: 13 http_code: 429 count: 14 http_code: 429 count: 15 http_code: 429 count: 16 http_code: 429 count: 17 http_code: 429 count: 18 http_code: 429 count: 19 http_code: 429 count: 20 ...
Global Rate Limiting Based on IP¶
Note
The key for IP rate limit rules must be set as remote_address
.
Rate Limiting for All IPs¶
-
Edit the configmap of the rate limit server and add the following content to the descriptors (pay attention to the format):
-
The rate limit server will hot-reload the configuration. Just wait for the configuration to take effect. Alternatively, you can access the configuration interface of the rate limit server and check if the following configuration appears.
-
Configure the global rate limit policy for the domain (assuming that the gateway has enabled the global rate limit plugin).
-
Access the API based on the domain. Run the following command:
while true; do curl -w " http_code: %{http_code}" http://ip.test:30000/; let count+=1; echo " count: ${count}"; done
The access result is as follows: after accessing 5 times, it is rate limited.
adservice-springcloud: hello world! http_code: 200 count: 1 adservice-springcloud: hello world! http_code: 200 count: 2 adservice-springcloud: hello world! http_code: 200 count: 3 adservice-springcloud: hello world! http_code: 200 count: 4 adservice-springcloud: hello world! http_code: 200 count: 5 http_code: 429 count: 6 http_code: 429 count: 7 http_code: 429 count: 8 http_code: 429 count: 9 http_code: 429 count: 10 ...
Rate Limiting for Specific IPs¶
-
Edit the configmap of the gateway-rls and add the following content to the descriptors (pay attention to the format):
- Rate limit all IPs to 10 requests per minute.
- Rate limit IP 10.6.222.90 to 5 requests per minute.
- Rate limit IP 10.70.4.1 (local machine) to 3 requests per minute.
data: ratelimit-config.yaml: | domain: gateway-rls.test descriptors: - name: ip-rls key: remote_address rate_limit: name: ip-rule unit: Minute requests_per_unit: 10 - key: remote_address value: 10.6.222.90 rate_limit: unit: Minute requests_per_unit: 5 - key: remote_address value: 10.70.4.1 rate_limit: unit: Minute requests_per_unit: 3
-
The rate limit server will hot-reload the configuration. Just wait for the configuration to take effect. Alternatively, you can access the configuration interface of the rate limit server and check if the following configuration appears.
$ curl http://10.6.222.21:32004/rlconfig gateway-rls.test.remote_address: unit=MINUTE requests_per_unit=10, shadow_mode: false gateway-rls.test.remote_address_10.6.222.90: unit=MINUTE requests_per_unit=5, shadow_mode: false gateway-rls.test.remote_address_10.70.4.1: unit=MINUTE requests_per_unit=3, shadow_mode: false
-
Configure the global rate limit policy for the domain.
-
Access the API based on the domain. Run the following command:
while true; do curl -w " http_code: %{http_code}" http://ip.test:30000/; let count+=1; echo " count: ${count}"; done
The access result for executing the command on the local machine is as follows: it is rate limited after accessing 3 times.
adservice-springcloud: hello world! http_code: 200 count: 1 adservice-springcloud: hello world! http_code: 200 count: 2 adservice-springcloud: hello world! http_code: 200 count: 3 http_code: 429 count: 4 http_code: 429 count: 5 http_code: 429 count: 6 http_code: 429 count: 7 http_code: 429 count: 8 http_code: 429 count: 9 http_code: 429 count: 10 ...
The access result for executing the command on the host with IP 10.6.222.90 is as follows: it is rate limited after accessing 5 times.
adservice-springcloud: hello world! http_code: 200 count: 1 adservice-springcloud: hello world! http_code: 200 count: 2 adservice-springcloud: hello world! http_code: 200 count: 3 adservice-springcloud: hello world! http_code: 200 count: 4 adservice-springcloud: hello world! http_code: 200 count: 5 http_code: 429 count: 6 http_code: 429 count: 7 http_code: 429 count: 8 http_code: 429 count: 9 http_code: 429 count: 10 http_code: 429 count: 11 http_code: 429 count: 12 ...
The access result for executing the command on other hosts without additional rate limit rules is as follows: it is rate limited after accessing 10 times.
adservice-springcloud: hello world! http_code: 200 count: 1 adservice-springcloud: hello world! http_code: 200 count: 2 adservice-springcloud: hello world! http_code: 200 count: 3 adservice-springcloud: hello world! http_code: 200 count: 4 adservice-springcloud: hello world! http_code: 200 count: 5 adservice-springcloud: hello world! http_code: 200 count: 6 adservice-springcloud: hello world! http_code: 200 count: 7 adservice-springcloud: hello world! http_code: 200 count: 8 adservice-springcloud: hello world! http_code: 200 count: 9 adservice-springcloud: hello world! http_code: 200 count: 10 http_code: 429 count: 11 http_code: 429 count: 12 http_code: 429 count: 13 http_code: 429 count: 14 http_code: 429 count: 15 http_code: 429 count: 16 http_code: 429 count: 17 ...