官方文档:Istio / 故障注入Istio / 设置请求超时

前提条件:

  • 部署服务(我这里是官方bookinfo程序)

  • 服务注入sidecar

部署在这里提到过,原文地址:istio服务网格入门-灰度发布 - (sreok.cn)

故障注入

将请求转发给reviews v2版本

只有这个版本才会调用ratings服务

kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2
EOF

设置ratings服务注入延迟

如果是jason用户的请求,就注入3秒的延迟,比例是100%请求

kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    fault:
      delay:
        fixedDelay: 3s
        percentage:
          value: 100
    route:
    - destination:
        host: ratings
        subset: v1
  - route:
    - destination:
        host: ratings
        subset: v1
EOF

此时请求bookinfo程序,流量被转移到reviews v2版本,没有任何问题

当登录用户为jason时,延迟被注入,按照预期,我们引入的3秒延迟不会影响到 reviews 服务,但是因为 reviewsratings 服务间的超时被硬编码为 10 秒。 但是,在 productpagereviews 服务之间也有一个 3 秒的硬编码的超时,再加 1 次重试,一共 6 秒。 结果,productpagereviews 的调用在 6 秒后提前超时并抛出错误了。

简单来说,productpage在等待reviews,reviews在等待ratings,productpage最多等待3秒就会重试,每次重试都会让reviews 重新请求ratings,所以reviews 与ratings直接的请求必须在3秒内响应,否则就会抛出错误

可以再次尝试将注入延迟改为2.9秒(只要不超过3秒就会成功,但存在一定误差,这个误差可能时大量请求导致的,我这里是测试,没有其他人的请求,所有可以设置2.9秒)

kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    fault:
      delay:
        fixedDelay: 2.9s
        percentage:
          value: 100
    route:
    - destination:
        host: ratings
        subset: v1
  - route:
    - destination:
        host: ratings
        subset: v1
EOF

这是实际上是官方提供给我们测试的BUG,reviews v3修复了这BUG,将ratings的超时时间设置为2.5秒

更新reviews

kubectl apply -f - << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v3
EOF

此时将流量转发给reviews v3版本,ratings响应时间只要超过2.5秒,reviews就不会继续等待,立即返回给productpage,避免ratings故障影响reviews服务

延迟如果在2.5秒内,响应没问题,超过2.5秒,抛出异常

这个时候ratings服务还是设置3s延迟,模拟ratings故障导致无法响应reviews服务,reviews服务也会在2.5秒后,将响应返回给productpage服务,不会影响reviews服务。

请求超时

保留ratings 服务的延迟注入,我设置了3秒,这时设置reviews超时时间

设置reviews 超时时间

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v3
    timeout: 1s
EOF

过程:

=> productpage v1(硬编码3s超时,1次重试)

=> reviews v3(硬编码2.5s超时,设置超时1s,此时会提前超时)

=> ratings v1(设置延时3s响应,延时只要大于等于超时就会响应失败)

解析:

  1. productpage请求reviews服务,reviews请求ratings服务,ratings服务延时3s响应

  2. 1秒后reviews服务超时,因为reviews还在等待reviews响应,而ratings要3s后才会响应

  3. productpage因为硬编码会再次重试,还是以上步骤,1秒后reviews服务再次返回超时

  4. productpage发送两次请求,共等待了2秒后返回给客户端,并且此时reviews是不可用的

注意:

productpage硬编码的3s超时没有触发,是因为reviews返回了超时

reviews硬编码2.5s超时没有触发,是因为设置了超时时间(作用就是这个)

结果:

2秒后抛出错误:Sorry, product reviews are currently unavailable for this book.

原因:

reviews服务1秒内没有收到ratings服务的响应,reviews服务超时

这个能解决什么问题?

在故障注入时,我们发现一个bug,就是调用链的下游超时时间大于上游,此时站在架构层解决的方式就可以使用timeout来拦截流量使下游小于上游的超时时间。避免影响中间层服务。

注意:

  1. 超时时间只能设置小于硬编码的超时时间

  2. 如遇到上面的bug问题,应及时提交并协助修复,高耦合istio并不是最佳方案