Use route-level circuit breaking

Updated at:

Open source Istio provides circuit breaking only at the service level -- all routes to a service share the same policy, and the rules take effect only after routing has occurred. If one API fails, circuit breaking affects every route to that service.

Service Mesh (ASM) extends Istio with route-level circuit breaking. The com.aliyun.break filter evaluates circuit breaking rules per route *before* traffic reaches the upstream service. A failing API triggers circuit breaking only for its own route while other routes continue to serve requests normally.

How route-level circuit breaking works

Standard Istio circuit breaking uses two settings in the trafficPolicy field of a destination rule:

  • ConnectionPoolSettings -- Limits the maximum number of connections, pending requests, and requests per connection to a service. Excess requests are queued, timed out, or retried.

  • OutlierDetection -- Periodically scans upstream hosts and ejects unhealthy ones from the load balancing pool based on consecutive errors.

The following example shows a standard Istio destination rule with circuit breaking settings. For more information, see Destination Rule.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
    outlierDetection:
      consecutive5xxErrors: 1
      interval: 1s
      baseEjectionTime: 3m
      maxEjectionPercent: 100

This approach has two limitations:

  1. Circuit breaking applies at the service level, not individual APIs or routes.

  2. Circuit breaking takes effect only after routing has occurred.

ASM overcomes both limitations through the ASMCircuitBreaker CustomResourceDefinition (CRD). On the data plane, ASM extends the Envoy filter chain with com.aliyun.break filter to evaluate circuit breaking rules *before* the request is routed to the upstream service. On the control plane, the ASMCircuitBreaker CRD provides a declarative interface -- no need to manage the underlying Envoy configuration directly.

Route-level circuit breaking supports both HTTP and gRPC protocols.

Prerequisites

Before you begin, make sure that you have:

Istio gateway

Deploy the following Istio gateway:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: bookinfo-gateway
  namespace: default
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - bf2.example.com
    port:
      name: http
      number: 80
      protocol: http

Virtual service

Deploy the following virtual service that routes /productpage and /httpbin through the gateway:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: bookinfo
  namespace: default
spec:
  gateways:
  - bookinfo-gateway
  hosts:
  - bf2.example.com
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    name: productpage-route-name1
    route:
    - destination:
        host: productpage
        port:
          number: 9080
  - match:
    - uri:
        prefix: /httpbin
    name: httpbin-route-name1
    rewrite:
      uri: /
    route:
    - destination:
        host: httpbin.foo.svc.cluster.local
        port:
          number: 80

Scenario overview

This tutorial demonstrates route-level circuit breaking with two services behind the same ingress gateway:

  • Bookinfo (default namespace) -- serves the /productpage route

  • HTTPBin (foo namespace) -- serves the /httpbin route

A circuit breaking rule targets only httpbin-route-name1. When HTTPBin triggers circuit breaking, requests to /httpbin receive a custom error response. Requests to /productpage continue normally, proving that route-level circuit breaking isolates failures to individual routes.

Scenario diagram

ASMCircuitBreaker field reference

The ASMCircuitBreaker CRD defines circuit breaking rules per route. The following example targets the nginx-route-name1 route on the bf2.example.com:80 virtual host:

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMCircuitBreaker
metadata:
  name: ingressgateway
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: istio-ingressgateway
  isGateway: true
  configs:
    - match:
        vhost:
          name: "bf2.example.com"
          port: 80
          route:
            name_match: nginx-route-name1
      breaker_config:
        slow_request_rt: 0.1s
        break_duration: 90s
        window_size: 10s
        max_slow_requests: 10
        min_request_amount: 3
        error_percent:
          value: 60
        custom_response:
          header_to_add:
            x-envoy-circuitbreak: "true"
          body: "hello, break!"
          status_code: 499
FieldDescriptionExample valueTuning guidance
isGatewayApplies the rule to a gateway when set to true. Set to false to apply to a sidecar proxy. Default: false.trueSet to true for ingress gateway rules.
slow_request_rtResponse time threshold. Requests exceeding this duration are counted as slow.0.1sLower values catch more requests as slow. Start with your P99 latency and adjust.
max_slow_requestsMaximum slow requests allowed per detection window. Circuit breaking triggers when this count is exceeded.10Set lower for stricter protection at the cost of more frequent circuit breaking. Set higher to tolerate occasional spikes.
error_percent.valueMaximum error rate (%). Circuit breaking triggers when the error rate exceeds this value and total requests meet min_request_amount.60Lower values trigger circuit breaking earlier. Common range: 50--80%.
min_request_amountMinimum requests required before circuit breaking can trigger. Prevents false positives during low traffic.3Set higher in low-traffic environments to avoid false positives.
window_sizeSliding window duration for counting slow requests and errors.10sShorter windows react faster but are more sensitive to bursts. Longer windows smooth out noise.
break_durationHow long circuit breaking stays active. All matching requests receive the custom response during this period. After this period expires, the circuit resets and requests are allowed through again.90sSet based on the expected recovery time of the upstream service.
custom_responseHTTP response returned while circuit breaking is active. Supports status_code, body, and header_to_add.See YAML aboveUse a distinctive status code and header so that clients and monitoring can distinguish circuit breaking responses from actual upstream errors.

For all available fields, see Description of ASMCircuitBreaker fields.

Configure and verify a circuit breaking rule

Create a circuit breaking rule for the httpbin-route-name1 route on the bf2.example.com:80 virtual host, then verify that it triggers correctly and affects only the targeted route.

Step 1: Create the ASMCircuitBreaker resource

Save the following YAML to a file named asmcircuitbreaker-test-gw.yaml:

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMCircuitBreaker
metadata:
  name: ingressgateway
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: istio-ingressgateway
  isGateway: true
  configs:
    - match:
        vhost:
          name: "bf2.example.com"
          port: 80
          route:
            name_match: httpbin-route-name1
      breaker_config:
        slow_request_rt: 0.1s
        break_duration: 90s
        window_size: 10s
        max_slow_requests: 10
        min_request_amount: 3
        error_percent:
          value: 60
        custom_response:
          header_to_add:
            x-envoy-overload: "true"
          body: "hello, break!"
          status_code: 499

Apply the resource:

kubectl apply -f asmcircuitbreaker-test-gw.yaml

This rule monitors the httpbin-route-name1 route over a 10-second sliding window. Circuit breaking triggers when either condition is met:

  • More than 10 slow requests (response time > 0.1 seconds)

  • Error rate exceeds 60%, with at least 3 total requests

Once triggered, all requests to /httpbin receive a 499 response with the body hello, break! for 90 seconds. After the 90-second break_duration expires, the circuit resets and requests flow to HTTPBin again.

Step 2: Trigger circuit breaking with simulated failures

Use curl to generate slow requests or error responses. The first few requests succeed normally because the thresholds have not been reached.

Simulate a 1-second delay (exceeds the 0.1-second slow_request_rt threshold):

curl -H 'host: bf2.example.com' http://${ASM_GATEWAY_IP}/httpbin/delay/1 -v

Simulate a 500 error:

curl -H 'host: bf2.example.com' http://${ASM_GATEWAY_IP}/httpbin/status/500 -v

Repeat either command at least 10 times within 10 seconds. As the counters accumulate within the sliding window, you will observe a progression:

  1. Initial requests -- The first few requests succeed normally (HTTP 200 from HTTPBin or the expected delay/error response from HTTPBin itself). Circuit breaking has not triggered because the thresholds have not been reached.

  2. Threshold crossed -- After enough requests exceed the configured thresholds within the 10-second window, subsequent requests return the custom circuit breaking response:

       < HTTP/1.1 499 Unknown
       < Content-Length: 12
       < Content-Type: text/plain
       < x-envoy-overload: true
       < Date: Thu, 13 Jan 2022 03:03:09 GMT
       < Server: istio-envoy
       <
       Hello,Break!

Three indicators confirm circuit breaking is active:

  • Status code: 499 (the custom status_code defined in the rule)

  • Header: x-envoy-overload: true (the custom header from header_to_add)

  • Body: Hello,Break! (the custom body)

Step 3: Verify that other routes are unaffected

While circuit breaking is active for /httpbin, send a request to the Bookinfo /productpage route:

curl -H 'host: bf2.example.com' http://${ASM_GATEWAY_IP}/productpage -v

A successful HTTP 200 response confirms that the circuit breaking rule only affects the httpbin-route-name1 route. Bookinfo continues to serve requests normally because the rule targets a specific route, not the entire service.

What to read next