Istio Service Mesh可以在請求途中會加入Circuit Breaking
、Request Timeouts等等策略。
重新設定回原先的Bookinfo
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-test-v2.yaml
Install
kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-delay.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- match:
- headers:
end-user:
exact: jason
fault:
delay:
percentage:
value: 100.0
fixedDelay: 7s
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
這邊是設定使用者json訪問網頁的時候會固定delay 7s
在瀏覽器中打開BookInfo的URL: http://localhost:31380/productpage
這裏登錄用戶名為 jason ,密碼隨便輸入即可
因為我們在ratings Service設定了delay 7s,所以會出現下列錯誤
Error fetching product reviews!
Sorry, product reviews are currently unavailable for this book.
發現了一個bug。在微服務中有hard-coded Timeout,導致reviews服務失敗。
在productpage和reviews服務之間Timeout設定6s,reviews和 ratings服務之間的hard-coded Timeout為10s。由於我們設定了7s delay,因此訪問/productpage會出現Timeout錯誤。
這類型的錯誤可能發生在很多情境下,其中獨立地開發不同的微服務。Istio的Fault injection可幫助您判斷此類異常錯誤,而不會影響最終結果。
這邊我們僅設定限制用戶 “jason” 會出現Timeout的錯誤狀況。如果您以任何其他用戶身份登入,則不會遇到任何Delay Timeout錯誤。
測試微服務的另一種方法是引入HTTP abort fault。在ratings Service中引入HTTP abort,測試用戶為jason 。
在這個案例中,我們希望網頁能夠立即加載,同時顯示Ratings service is currently unavailable這樣的消息。
#install
kubectl apply -f samples/bookinfo/networking/virtual-service-ratings-test-abort.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
...
spec:
hosts:
- ratings
http:
#設定http abort,ratings Service所有流量都回500 Error
- fault:
abort:
httpStatus: 500
percent: 100
match:
- headers:
end-user:
exact: jason
route:
- destination:
host: ratings
subset: v1
- route:
- destination:
host: ratings
subset: v1
在瀏覽器中打開BookInfo的URL: http://localhost:31380/productpage
這裏登錄用戶名為 jason ,密碼隨便輸入即可
能立即看到Ratings service is currently unavailable畫面。
因為我們只設定jason
這個帳號,所以除了jason外的用戶都會看到網頁上看到評級星標的評論成功顯示。
kubectl apply -f samples/bookinfo/networking/virtual-service-all-v1.yaml
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 Service delay 2s
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- fault:
delay:
percent: 100
fixedDelay: 2s
route:
- destination:
host: ratings
subset: v1
EOF
Setting Request timeout
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
timeout: 0.5s
EOF
因為前面已經設定ratings delay 2s,因此新增的設定生效reviews的畫面會不到。
在reviews Service的Request加入了0.5s的Timeout,預設的Timeout 15秒鐘被覆蓋掉了。因此網頁重新整理時,reviews Service會調用 ratings Service,ratings Service中有設定2s Timeout,這樣就讓 reviews Service要花費超過0.5s的時間來調用 ratings Service,觸發了我們加入的Timeout Rule。
這樣就會看到 Bookinfo 上沒有出現 reviews Service的內容,取而代之的是錯誤信息:Sorry, product reviews are currently unavailable for this book,出現這一錯誤的原因就是因為來自 reviews Service的Timeout。
除了像上面在VirtualService中進行Timeout Setting之外,還可以在istio-ingressgateway設置,在istio-ingressgateway中加入x-envoy-upstream-rq-timeout-ms Header。在這個 Header 中的逾時單位是毫秒而不是秒。
kubectl apply -f samples/httpbin/httpbin.yaml
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutiveErrors: 1
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 100
EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
...
spec:
host: httpbin
trafficPolicy:
connectionPool:
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
tcp:
maxConnections: 1
outlierDetection:
baseEjectionTime: 180.000s
consecutiveErrors: 1
interval: 1.000s
maxEjectionPercent: 100
DestinationRule除了可以設定Circuit Breaking,還可以設定connectionPool以及loadBalancer在trafficPolicy之下,
現在我們已經設置了 httpbin Service,接下來需要創建一個Client,用來向httpbin Service發送請求,觀察是否會觸發Circuit Breaking。這裏要使用一個簡單的負載測試客戶端,名字叫 fortio。這個客戶端可以控制連接數量、並發數以及發送 HTTP 請求的延遲。
kubectl apply -f samples/httpbin/sample-client/fortio-deploy.yaml
FORTIO_POD=$(kubectl get pod | grep fortio | awk '{ print $1 }')
kubectl exec -it $FORTIO_POD -c fortio /usr/local/bin/fortio -- load -curl http://httpbin:8000/get
我們在上面的Circuit Breaking有設定maxConnections: 1 以及 http1MaxPendingRequests: 1這兩項規則
接下來嘗試一下,一次兩個Thread(-c 2),發送20次請求(-n 20)
kubectl exec -it $FORTIO_POD -c fortio /usr/local/bin/fortio -- load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get
稍微修改一下,一次三個Thread(-c 3),發送30次請求(-n 30)
kubectl exec -it $FORTIO_POD -c fortio /usr/bin/fortio -- load -c 3 -qps 0 -n 30 -loglevel Warning http://httpbin:8000/get
查詢 istio-proxy 的狀態,獲取更多相關信息
kubectl exec $FORTIO_POD -c istio-proxy -- pilot-agent request GET stats | grep httpbin | grep pending
cluster.outbound|80||httpbin.springistio.svc.cluster.local.upstream_rq_pending_active: 0
cluster.outbound|80||httpbin.springistio.svc.cluster.local.upstream_rq_pending_failure_eject: 0
cluster.outbound|80||httpbin.springistio.svc.cluster.local.upstream_rq_pending_overflow: 12
cluster.outbound|80||httpbin.springistio.svc.cluster.local.upstream_rq_pending_total: 39
upstream_rq_pending_overflow是12,說明有12次請求被視為熔斷。
今天主要講解比較進階的幾個常見應用,明天會再講一些更特別的應用情境