When both MicroProfile and Istio Fault Tolerance capabilities are enabled, there is a compounding effect that may be unexpected.
If both MicroProfile and Istio set their own Retry policies on a service,
the maximum number of retries that occur is not equivalent to either of the number of retries specified in MicroProfile or Istio.
The number of retries set by MicroProfile and Istio are actually multiplied.
If you want to use Istio as your service mesh and only its fault tolerance capabilities,
you can turn off MicroProfile Fault Tolerance by adding a property. This configuration avoids any overlap in behaviours.
MicroProfile Fault Tolerance offers a config property MP_Fault_Tolerance_NonFallback_Enabled
that disables all
MicroProfile Fault Tolerance capabilities except fallback. If MP_Fault_Tolerance_NonFallback_Enabled
is set to false, only
the @Fallback
behaviour is enabled. The other behaviours specified by the MicroProfile Fault Tolerance annotations,
including @Retry
, won’t take effect.
You will define the MP_Fault_Tolerance_NonFallback_Enabled
config property in a ConfigMap.
ConfigMaps store configuration settings about a Kubernetes pod. This configuration is loaded into the pod as an environment variable that is
used by the pod’s containers. The environment variables are defined in the pod’s specification by using the envFrom
field. To learn more about ConfigMaps,
check out the Configuring microservices running in Kubernetes guide.
Use the MP_Fault_Tolerance_NonFallback_Enabled
config property to disable the retries performed by MicroProfile,
so that only Istio performs retries.
Update the services.yaml
file.
services.yaml
1
2apiVersion: networking.istio.io/v1alpha3
3kind: Gateway
4metadata:
5 name: sys-app-gateway
6spec:
7 selector:
8 istio: ingressgateway
9 servers:
10 - port:
11 number: 80
12 name: http
13 protocol: HTTP
14 hosts:
15 - "system.example.com"
16 - "inventory.example.com"
17
18---
19apiVersion: v1
20kind: Service
21metadata:
22 name: system-service
23 labels:
24 app: system
25spec:
26 ports:
27 - port: 9090
28 name: http
29 selector:
30 app: system
31---
32apiVersion: v1
33kind: Service
34metadata:
35 name: inventory-service
36 labels:
37 app: inventory
38spec:
39 ports:
40 - port: 9091
41 name: http
42 selector:
43 app: inventory
44---
45apiVersion: apps/v1
46kind: Deployment
47metadata:
48 name: system-deployment
49 labels:
50 app: system
51spec:
52 selector:
53 matchLabels:
54 app: system
55 template:
56 metadata:
57 labels:
58 app: system
59 spec:
60 containers:
61 - name: system-container
62 image: system:1.0-SNAPSHOT
63 ports:
64 - containerPort: 9090
65---
66apiVersion: apps/v1
67kind: Deployment
68metadata:
69 name: inventory-deployment
70 labels:
71 app: inventory
72spec:
73 selector:
74 matchLabels:
75 app: inventory
76 template:
77 metadata:
78 labels:
79 app: inventory
80 spec:
81 containers:
82 - name: inventory-container
83
84 image: inventory:1.0-SNAPSHOT
85
86 ports:
87 - containerPort: 9091
88
89 envFrom:
90 - configMapRef:
91 # tag::configName2[]
92 name: inventory-config
93 # end::configName2[]
94
95
96---
97
98apiVersion: v1
99kind: ConfigMap
100metadata:
101
102 name: inventory-config
103
104data:
105
106 MP_Fault_Tolerance_NonFallback_Enabled: "false"
107
108
109
Add a ConfigMap
into the services.yaml
file, and
set the MP_Fault_Tolerance_NonFallback_Enabled
config property to false.
Add the envFrom
field
to inject the ConfigMap
with the MP_Fault_Tolerance_NonFallback_Enabled
property into your pods.
The name
of the ConfigMap
, which is inventory-config
,
becomes the environment variable name
that is specified in the envFrom
field.
Deploy your microservices again to turn off all MicroProfile Fault Tolerance capabilities, except fallback:
kubectl replace --force -f services.yaml
Wait until all of your deployments are ready and available.
Run the kubectl get pods
command to get the new [system-pod-name]
.
Pause the system
service pod to simulate that the service is unavailable:
kubectl exec -it [system-pod-name] -- /opt/ol/wlp/bin/server pause
Make a request to the service by using curl
:
curl -H Host:inventory.example.com http://localhost/inventory/systems/system-service -I
If the curl
command is unavailable, then use Postman.
curl -H Host:inventory.example.com http://`minikube ip`:$INGRESS_PORT/inventory/systems/system-service -I
Because the system
service is unavailable, the request still returns a 503
response code.
This time, however, the request was retried several times with Istio, without any retries from MicroProfile.
See the number of times that the service was retried:
kubectl logs [system-pod-name] -c istio-proxy | grep -c system-service:9090
kubectl logs [system-pod-name] -c istio-proxy | find /C "system-service:9090"
You will see the following output:
The above command returns 15, indicating that a total of 15 requests are made to the system
service.
Because MicroProfile’s Retry policy is disabled, only Istio’s retries are performed.
1apiVersion: networking.istio.io/v1alpha3
2kind: VirtualService
3metadata:
4 name: system-virtual-service
5spec:
6 hosts:
7 - "system.example.com"
8 gateways:
9 - sys-app-gateway
10 http:
11 - route:
12 - destination:
13 port:
14 number: 9090
15 host: system-service
16---
17apiVersion: networking.istio.io/v1alpha3
18kind: VirtualService
19metadata:
20 name: inventory-virtual-service
21spec:
22 hosts:
23 - "inventory.example.com"
24 gateways:
25 - sys-app-gateway
26 http:
27
28 - route:
29 - destination:
30 port:
31 number: 9091
32 host: inventory-service
33
34 retries:
35
36 attempts: 4
37
38
39 retryOn: 5xx
40
41
42