The great thing about software development is that there is always something new to learn! The terrible thing about software development is that there is always something new to learn! Luckily, there are tons of wonderful people sharing their knowledge every week in helpful and entertaining newsletters … and unfortunately, it can be really easy...
Twelve-factor apps make a strong case for designing and implementing your microservices for failure. What that means is with the proliferation of microservices, failure is inevitable, and applications should be fault-tolerant. Istio, a service mesh, can help make your microservices resilient without changing application code.
Building and packaging microservices is one part of the story. Given that a highly salable and distributed microservices deployment is going to face failures at different layers, how do we make these microservices resilient and fault-tolerant? How do we enforce policy decisions, such as fine-grained access control and rate limits? How do we enable timeouts/retries, health checks, etc.? Even though some language-specific frameworks address these issues, the implementation is often framework- or language-specific. If the underlying framework or language changes, the resiliency features need to be reimplemented or ported over. And in some cases, applications also have the responsibility of implementing the code and configuration required for resiliency and fault-tolerance. A service-mesh architecture attempts to resolve these issues by extracting the common resiliency features needed by a microservices framework away from the applications and frameworks and into the platform itself. Istio provides an easy way to create this service mesh. In this developer journey, we demonstrate how to build, deploy, and connect your Java™ MicroProfile microservices, leveraging Istio service mesh. We then show how to configure and use circuit breakers, timeouts/retries, rate limits, and other advanced resiliency features from Istio without changing the application code.
- In this step, the user deploys a Java application that is configured to run in a Kubernetes Cluster. The application, MicroProfile, is composed of five microservices. The application is written in Angular and Java. The ‘Vote’ microservice has two versions. V1 stores its data locally, and V2 stores its data with the Cloudant® database. The user ensures that the Istio service mesh control plane is running on Kubernetes.
- To enable the application to use Istio features, the user injects Istio envoys on the application. Envoys are deployed as sidecars on each microservice. Injecting Envoy into a microservice means that the Envoy sidecar would manage the incoming and outgoing calls for the service. The user also creates ingress to enable ingress traffic from Istio ingress.
- The user now configures advanced Istio features for the MicroProfile and creates a circuit breaker for the Cloudant database. We specify maximum active connections to Cloudant and maximum pending requests. If we sent more than the allowed maximum requests at once to Cloudant, it will have pending requests up to the specified threshold and deny additional requests until the pending ones process.
- Another circuit breaker that can be used is based on the health of the instances in a load-balancing pool. User creates a load-balancing pool with two instances of Cloudant, then uses a circuit breaker to detect and eject an instance when no longer healthy.
- User creates a timeout and retries rule for the ‘Vote’ microservice connection to Cloudant. This rule times out responses that take more than the allowed response-time threshold. User also applies retries rule by telling Istio how many retries he wants and what the timeout should be for retry. The user creates a fault injection on Cloudant database to simulate the failure situation and verify the timeout and retries rule works properly.