proxy-buffering
The proxy-buffering plugin dynamically disables the NGINX proxy_buffering directive.
You should disable buffering in scenarios when configuring API7 gateways with server-sent events (SSE) upstream services, or services that respond with chunked data, such as the etcd watch events.
Examples
Configure With SSE Upstream
The following example demonstrates how to disable proxy_buffering on a route with an SSE upstream service.
Start a sample upstream service for SSE:
- Docker
- Kubernetes
docker run -d -p 8080:8080 jmalloc/echo-server
Create a Kubernetes manifest file for the deployment of the SSE server:
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: sse-server
spec:
replicas: 1
selector:
matchLabels:
app: sse-server
template:
metadata:
labels:
app: sse-server
spec:
containers:
- name: echo-server
image: jmalloc/echo-server
ports:
- containerPort: 8080
Create another Kubernetes manifest file for the SSE service:
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: sse-service
spec:
selector:
app: sse-server
ports:
- protocol: TCP
port: 8080
targetPort: 8080
type: ClusterIP
Apply the manifests:
kubectl apply -f sse-deployment.yaml -f sse-service.yaml
Create a route to the upstream and configure proxy-buffering:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-buffering-route",
"uri": "/.sse",
"plugins": {
"proxy-buffering": {
"disable_proxy_buffering": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8080": 1
}
}
}'
services:
- name: sse-service
routes:
- uris:
- /.sse
name: proxy-buffering-route
plugins:
proxy-buffering:
disable_proxy_buffering: true
upstream:
type: roundrobin
nodes:
- host: 127.0.0.1
port: 8080
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: proxy-buffering-plugin-config
spec:
plugins:
- name: proxy-buffering
config:
disable_proxy_buffering: true
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: proxy-buffering-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /.sse
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: proxy-buffering-plugin-config
backendRefs:
- name: sse-service
port: 8080
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: proxy-buffering-route
spec:
ingressClassName: apisix
http:
- name: proxy-buffering-route
match:
paths:
- /.sse
upstreams:
- serviceName: sse-service
servicePort: 8080
plugins:
- name: proxy-buffering
config:
disable_proxy_buffering: true
Apply the configuration:
kubectl apply -f proxy-buffering-ic.yaml
Send a request to the route:
curl "http://127.0.0.1:9080/.sse" -H "Accept: text/event-stream"
You should receive a HTTP/1.1 200 OK response and see continuous event stream similar to the following:
event: server
data: 162291b28f55
id: 1
event: request
data: GET /.sse HTTP/1.1
data:
data: Host: 127.0.0.1:9080
data: Accept: text/event-stream
data: User-Agent: curl/7.74.0
data: X-Forwarded-For: 172.19.0.1
data: X-Forwarded-Host: 127.0.0.1
data: X-Forwarded-Port: 9080
data: X-Forwarded-Proto: http
data: X-Real-Ip: 172.19.0.1
data:
id: 2
event: time
data: 2023-10-19T02:13:53Z
id: 3
event: time
data: 2023-10-19T02:13:54Z
id: 4
event: time
data: 2023-10-19T02:13:55Z
id: 5
...
(Optional) See Buffering in Effect
You will see the proxy buffering effect on SSE when proxy_buffering is not turned off in this section. For demonstration, the proxy buffer size will be adjusted to a larger value.
Add the following snippet to the configuration file:
nginx_config:
http_configuration_snippet: |
server {
listen 9080;
location /sse {
proxy_buffering on;
proxy_buffers 4 2m;
}
}
❶ Though explicitly configured, proxy_buffering is on by default.
❷ Configure proxy_buffers to use 4 buffers, each with a size of 2 MB.
Reload the gateway for changes to take effect.
Recreate the route without proxy-buffering:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "proxy-buffering-route",
"uri": "/.sse",
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:8080": 1
}
}
}'
services:
- name: sse-service
routes:
- uris:
- /.sse
name: proxy-buffering-route
upstream:
type: roundrobin
nodes:
- host: 127.0.0.1
port: 8080
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: proxy-buffering-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /.sse
backendRefs:
- name: sse-service
port: 8080
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: proxy-buffering-route
spec:
ingressClassName: apisix
http:
- name: proxy-buffering-route
match:
paths:
- /.sse
upstreams:
- serviceName: sse-service
servicePort: 8080
Apply the configuration:
kubectl apply -f proxy-buffering-ic.yaml
Send a request to the route:
curl "http://127.0.0.1:9080/.sse" -H "Accept: text/event-stream"
You should receive a HTTP/1.1 200 OK response and see the same event stream. However, note that events are not received at a regular interval due to the effect of the buffer, which is undesirable when working with an SSE upstream.