cloud_native_patterns_-_designing_change-tolerant_software_by_cornelia_davis

Cloud Native Patterns - Designing change-tolerant software by Cornelia Davis

Patterns used in cloud-native applications

The cloud native patterns that follow are listed roughly in the order in which they are introduced in the book:

  • Request/Response — A protocol for communication between services where a client makes a request of a remote service and in most cases expects a response. This may be done synchronously or asynchronously and is most often done over HTTP.
  • Event-driven — A protocol where entities in a distributed system communicate events, and these events are the means by which the services in a cloud-native application are kept up to date.
  • Multiple service instances — Deployment of more than one instance of apps/services to support resilience, scalability, and cloud-native operational practices.
  • Horizontal scaling — The creation of additional application instances to increase capacity for a service.
  • Stateless services — Apps/services that do not store state in memory or on local disk that is needed for subsequent invocations of the service.
  • Stateful services — Services such as databases and message queues designed to persist state. Used to provide persistent data for stateless services.
  • Configuration service — A (stateful) service that is used to deliver configuration values to multiple app instances to ensure consistent operations.
  • Configuration as code — Managing configurations through files that are versioned and checked into source control.
  • Zero-downtime upgrades — A means of upgrading all app/service instances while the app remains fully functional.
  • Rolling upgrades — A technique whereby an app is upgraded with zero downtime by upgrading subsets of all instances incrementally, in batches.
  • Blue/green upgrades — A technique whereby an app is upgraded by deploying a full set of new app instances and then switching over to those in one fell swoop.
  • Liveness probes — The periodic calling of application health endpoints and the re-creation of app instances when the health check fails.
  • Server-side load balancing — A means of routing requests across multiple app instances where the client makes the requests to a single entity—the load balancer.
  • Client-side load balancing — A means of routing requests across multiple app instances where the client is aware of and controls routing to the multiple instances of a service.
  • Service discovery — The means by which a client will find the address or addresses for a service it will invoke.
  • Retry — A technique whereby a client repeats a service request when it has received no response.
  • Safe service — A service that may be invoked zero or more times, yielding the same outcome.
  • Idempotent service — A service that may be invoked once or more than once, yielding the same outcome.
  • Fallbacks — Application logic that is executed when a request to a downstream service fails to generate a result.
  • Circuit-breaker — A technique used to stop requests to a failing service instance and then allow them through when the service resumes normal operations.
  • API gateways — A service proxy used for many things, including access control, auditing, routing and much more.
  • Sidecars — An approach to service proxying where the proxy sits right next to the service.
  • Service mesh — The network of and control plane for sidecars.
  • Distributed tracing — A means by which a thread of execution through a series of related but distributed services can be traced for troubleshooting purposes.
  • Event sourcing — A pattern where the source of truth in the software is an event log from which materialized views serve the needs of service instances.

Table of Contents

Copyright

Brief Table of Contents

Table of Contents

Foreword

Preface

Acknowledgments

About this book

About the author

About the cover illustration

Part 1. The cloud-native context

Chapter 1. You keep using that word: Defining “cloud-native”

1.1. Today’s application requirements

1.2. Introducing cloud-native software

1.3. Cloud-native and world peace

Summary

Chapter 2. Running cloud-native applications in production

2.1. The obstacles

2.2. The enablers

Summary

Chapter 3. The platform for cloud-native software

3.1. The cloud(-native) platform evolution

3.2. Core tenets of the cloud-native platform

3.3. Who does what?

3.4. More cloud-native platform capabilities

Summary

Part 2. Cloud-native patterns

Chapter 4. Event-driven microservices: It’s not just request/response

4.1. We’re (usually) taught imperative programming

4.2. Reintroducing event-driven computing

4.3. My global cookbook

4.4. Introducing Command Query Responsibility Segregation

4.5. Different styles, similar challenges

Summary

Chapter 5. App redundancy: Scale-out and statelessness

5.1. Cloud-native apps have many instances deployed

5.2. Stateful apps in the cloud

5.3. HTTP sessions and sticky sessions

5.4. Stateful services and stateless apps

Summary

Chapter 6. Application configuration: Not just environment variables

6.1. Why are we even talking about config?

6.2. The app’s configuration layer

6.3. Injecting system/environment values

6.4. Injecting application configuration

Summary

Chapter 7. The application lifecycle: Accounting for constant change

7.1. Having empathy for operations

7.2. Single-app lifecycle, multiple-instance lifecycles

7.3. Coordinating across different app lifecycles

7.4. Let’s see this in action: Credential rotation and app lifecycle

7.5. Dealing with ephemeral runtime environments

7.6. Visibility of app lifecycle state

7.7. Serverless

Summary

Chapter 8. Accessing apps: Services, routing, and service discovery

8.1. The service abstraction

8.2. Dynamic routing

8.3. Service discovery

Summary

Chapter 9. Interaction redundancy: Retries and other control loops

9.1. Request retries

9.2. Fallback logic

9.3. Control loops

Summary

Chapter 10. Fronting services: Circuit breakers and API gateways

10.1. Circuit breakers

10.2. API gateways

10.3. The service mesh

Summary

Chapter 11. Troubleshooting: Finding the needle in the haystack

11.1. Application logging

11.2. Application metrics

11.3. Distributed tracing

Summary

Chapter 12. Cloud-native data: Breaking the data monolith

12.1. Every microservice needs a cache

12.2. Moving from request/response to event driven

12.3. The event log

12.4. Event sourcing

12.5. We’re just scratching the surface

Summary

Patterns used in cloud-native applications

  • Index
  • List of Figures
  • List of Tables
  • List of Listings

List of Figures

Chapter 1. You keep using that word: Defining “cloud-native”

Figure 1.1. AWS partitions the services it offers into regions and availability zones. Regions map to geographic areas, and AZs provide further redundancy and isolation within a single region.

Figure 1.2. Applications deployed onto AWS may be deployed into a single AZ (IMDb), or in multiple AZs (Nest) but only a single region, or in multiple AZs and multiple regions (Netflix). This provides different resiliency profiles.

Figure 1.3. If applications are properly architected and deployed, digital solutions can survive even a broad outage, such as of an entire region.

Figure 1.4. User requirements for software drive development toward cloud-native architectural and management tenets.

Figure 1.5. Architectural and management tenets lead to the core characteristics of cloud-native software: it’s highly distributed and must operate in a constantly changing environment even as the software is constantly evolving.

Figure 1.6. Familiar elements of a basic software architecture

Figure 1.7. Cloud-native software takes familiar concepts and adds extreme distribution, with redundancy everywhere, and constant change.

Figure 1.8. Key entities in the model for cloud-native software: apps, data, and interactions

Figure 1.9. The online banking software is a composition of apps and data services. Many types of interaction protocols are in play.

Figure 1.10. What appears to a user as a single experience with Wizard’s Bank is realized by independently developed and managed software assets.

Figure 1.11. A decomposed and loosely coupled data fabric requires techniques for cohesive data management.

Figure 1.12. Dispensing funds without access to the source of record is ill-advised.

Figure 1.13. Applying some cloud-native patterns, such as redundancy and properly distributed deployments, brings benefit even in software that isn’t fully cloud-native.

Chapter 2. Running cloud-native applications in production

Figure 2.1. Factors that contribute to the difficulty in deploying software and keeping it running well in production

Figure 2.2. Testing two apps in sequence is straightforward when all tests pass.

Figure 2.3. A failing test immediately complicates the process for preproduction testing.

Figure 2.4. Explicit attention to these four factors develops a system of efficiency, predictability, and stability.

Figure 2.5. Every dev/test cycle doesn’t result in a ship; instead, every cycle results in software that’s ready to ship. Shipping then becomes a business decision.

Figure 2.6. A traditional software delivery lifecycle front-loads a lot of development work and a long testing cycle before creating the artifacts that can then be released into production.

Figure 2.7. Continuous delivery is concerned with allowing business drivers, not IT readiness, to determine when software is shipped.

Figure 2.8. When the development schedule slips, you need to decide between two unpalatable options.

Figure 2.9. Shorter iterations designed for continuous delivery allow for an agile release process while maintaining software quality.

Figure 2.10. Even when environment-specific values are organized into property files, including property files in the deployable artifact, you’ll have different artifacts throughout the SDLC.

Figure 2.11. The desired outcome is to be able to consistently establish apps running in standardized environments. Note that the app is the same across all environments; the runtime environment is standardized within an SDLC stage.

Figure 2.12. The assembly of standardized base images, controlled environment configurations, and single deployable artifacts is automated.

Figure 2.13. Data tells you how parallel deployments of multiple versions of your apps are operating. You use that data to program control flows to those apps, supporting safe rollouts of new software in production.

Figure 2.14. The desired state of your deployed software

Figure 2.15. When the actual state doesn’t match the desired state, the eventually consistent system initiates actions to bring them back into alignment.

Chapter 3. The platform for cloud-native software

Figure 3.1. Infrastructure-as-a-service (IaaS) offerings from major cloud platform providers

Figure 3.2. Accessing application logs in an infrastructure-centric environment is tedious.

Figure 3.3. Accessing application logs in an app-centric environment is simple.

Figure 3.4. The cloud-native platform abstracts infrastructure concerns, allowing teams to focus on their applications instead of these lower-level concerns.

Figure 3.5. A host usually has multiple containers running on it. These containers share the OS kernel from the host. But each container has its own root operating filesystem, runtime environment, and application code.

Figure 3.6. When studying the capabilities of a cloud-native platform, at times we’ll think of the container as a black box within which your application runs. A bit later, we’ll drill into the details of what’s running in the container.

Figure 3.7. Management of workloads across availability zones is handled by the cloud-native platform.

Figure 3.8. The state of applications running on the platform is managed by continually comparing the desired state to the actual state and then executing corrective actions when necessary.

Figure 3.9. The recommendations service finds the favorites service via DNS lookup and routing.

Figure 3.10. The recommendations service directly accesses the favorites service via IP address; the routing function is distributed.

Figure 3.11. The configuration service of the cloud-native platform provides important configuration capabilities for microservice-based application deployments.

Figure 3.12. The cloud-native platform presents a contract that allows consumers to deploy and manage their software without being exposed to low-level infrastructure details. Nonfunctional requirements such as performance guarantees are realized via SLAs that are achieved via specific platform configurations.

Figure 3.13. The right abstractions support the formation of autonomous platform and application teams. Each is responsible for deployment, monitoring, scaling, and upgrading their respective products.

Figure 3.14. Code commits generate deployable artifacts that are deployed into a dev environment that looks similar to production, but has development versions of services such as databases and message queues (depicted by the symbols on the right).

Figure 3.15. The same deployable artifact is deployed into a staging environment, where it’s bound to services (depicted by the symbols on the right) that more closely match those that exist in production.

Figure 3.16. The same artifact is deployed into similar environments throughout the SDLC and must absorb the unavoidable differences across the environments.

Figure 3.17. The platform must include a mechanism that allows the contract between app and runtime environment and bound services to serve the needs of the SDLC.

Figure 3.18. Control functions that are on the critical path for every release of every app reduce the number of deployments that can be performed.

Figure 3.19. By deploying to a platform that implements controls, you can reduce to mere minutes the time between having an app ready for deployment and performing that deployment.

Figure 3.20. The assembly of standardized base images, controlled environment configurations, and single deployable artifacts is automated.

Figure 3.21. The structure of the container image clearly separates the concerns of the app team from those of the platform team.

Figure 3.22. The right platform enables app teams to operate independently from platform teams.

Figure 3.23. True multitenancy in the compute tier shares resources in the control plane, as well as in the compute layer (the Linux host and kernel) while using containers to achieve resource isolation.

Chapter 4. Event-driven microservices: It’s not just request/response

Figure 4.1. Diagram appearing in a presentation from Scott Mansfield of Netflix shows a single request to retrieve the homepage for a user results in a significant fan-out of requests to downstream microservices.

Figure 4.2. Contrast the base primitive of request/response to event-driven invocation styles.

Figure 4.3. The Abundant Sunshine website will display a list of posts made by my favorite food bloggers. The aggregation is a composition of the network of people I follow and posts made by those individuals.

Figure 4.4. Rendering a portion of the web page depends on a series of coordinated requests and responses.

Figure 4.5. Users, the connections between them, and the posts each has recently made

Figure 4.6. The composite result generated by the Connections’ Posts microservice is produced by making calls to the Connections and Posts microservices and aggregating results.

Figure 4.7. Events are the means through which related microservices are connected.

Figure 4.8. When a request is received, the Connections’ Posts service can generate a result without depending on other services in the system.

Figure 4.9. The Posts service not only persists the new post that was created, but also delivers an event reporting that this post has been created.

Figure 4.10. Microservices can implement both request/response and event-driven patterns. Events are primarily used to loosely couple microservices.

Figure 4.11. Rendering the web page now only requires execution of the Connections’ Posts microservice. Through event handling, it already has all of the data it needs to satisfy the request, so no downstream requests and responses are required.

Figure 4.12. The Connections service generates an event when a new connection has been recorded.

Figure 4.13. The Posts service generates an event when a new post has been recorded.

Figure 4.14. The event handler for the Connections’ Posts service processes events as they occur.

Figure 4.15. The Connections’ Posts service generates and delivers a response when a request is received. This is completely independent from the operations of the other microservices in our solution.

Figure 4.16. Separating the write logic from the read logic allows you to support different models for these different concerns. This leads to more elegant, maintainable code.

Figure 4.17. The retry is a key pattern used in request/response microservice architectures to compensate for network partitions. In event-driven systems, the use of an event store is a key technique that compensates for network instability.

Chapter 5. App redundancy: Scale-out and statelessness

Figure 5.1. Given the same input, the result produced by an app instance must be the same, regardless of whether there are one, two, or one hundred instances of the app.

Figure 5.2. The cloud-native app must ensure consistent results in spite of possible differences in other contextual influencers.

Figure 5.3. Architecting apps for multi-instance deployments affords significant gains in the efficiency of resource use as well as resilience and other operational benefits.

Figure 5.4. My terminal configuration allows me to send requests to the microservices while watching the results in the other windows.

Figure 5.5. The deployment topology of the cookbook software, refactored into separate components and deployed into a cloud setting. At the moment, each app has only a single instance deployed.

Figure 5.6. Logically, you have a single app that serves a series of requests. Because each user logs in before trying any Get Data calls, you expect each of those will succeed.

Figure 5.7. When a single logical entity is deployed as multiple instances, care must be taken to ensure that the distributed set of events continues to be treated as a whole.

Figure 5.8. When you add a second instance of the Connections’ Posts app, its local list of valid tokens differs from that of the first. This is exactly the problem with stateful apps in cloud-native software.

Figure 5.9. Sticky sessions are implemented by the load balancer and are used to tie a specific user to a specific instance of an app.

Figure 5.10. A load balancer supporting sticky sessions will attempt to stick specific users to specific app instances, but may be forced to send a request to a different instance. In cloud-native software, you must assume that instances come and go with some regularity. If you don’t, the user experience suffers.

Figure 5.11. Storing valid tokens in a stateful service that’s bound to all instances of the Connections’ Posts service allows apps to be stateless but our overall software solution to be stateful.

Figure 5.12. Your new deployment replaces the Connections’ Posts service with a stateless version and adds a Redis server to store authentication tokens.

Chapter 6. Application configuration: Not just environment variables

Figure 6.1. The cloud-native app must ensure consistent outcomes despite differences in contextual influencers such as request history (different app instances have processed a different set of requests) and system environment values (such as IP addresses). Application configuration should be the same across instances but may differ at times.

Figure 6.2. Application configuration changes are often brought about from changes in the infrastructure, which are either anticipated (as depicted here, a rolling upgrade) or unexpected.

Figure 6.3. Apps have a specific configuration layer that supports both system environment and application configuration. This layer allows the implementation to use values regardless of how their values are provided.

Figure 6.4. The application source references properties that are defined in the property file. The property file acts as a specification of the configuration parameters for the app, and can indicate that values should come from env variables (INSTANCE_IP).

Figure 6.5. This software deployment topology currently requires a great deal of hand edits of connections between the services. These manual configurations will be progressively eliminated as you proceed through more cloud-native patterns.

Figure 6.6. Responsible for the deployment and management of the app instances, Kubernetes establishes the environment variables defined in the deployment manifest, drawing values from the infrastructure entities it has established for the app.

Figure 6.7. Application configuration is facilitated through the use of a source code-control system that will persist configuration values, and a configuration service that provides managed access to that data.

Figure 6.8. The application configuration layer depends on the property file as the means for injecting values; those values come in through the use of a config server.

Figure 6.9. The property file acts as the common configuration layer for both system config and application config. System config data is injected via env variables, and app config data is injected via a configuration service.

Chapter 7. The application lifecycle: Accounting for constant change

Figure 7.1. A simple depiction of the stages in an app’s lifecycle

Figure 7.2. Both instances of the Posts service are running with the same configuration and act as a single logical application.

Figure 7.3. Because the two instances of the Posts service have different configurations applied, the outcome of issuing a request will differ greatly depending on whether a request is routed to the first instance of the app or the second. This must be avoided, even during a zero-downtime upgrade.

Figure 7.4. Application configuration is best applied when the application is started. Most application frameworks naturally function this way.

Figure 7.5. The blue/green deployment is used when an app can’t tolerate having multiple versions running side by side (when the multiple versions can’t be made to act as a single logical instance).

Figure 7.6. During rolling upgrades, production traffic is routed to more than one version of the app. The app must be able to function as a single logical whole, even as requests are being distributed over different versions.

Figure 7.7. One consideration when deciding between blue/green and rolling upgrades is the resource requirement. Note that during a blue/green deployment, double the resources are needed for the Posts API, whereas the rolling upgrade has only a slight increase in the resource requirements.

Figure 7.8. Application lifecycle events must be coordinated across different components of your software.

Figure 7.9. This credential rotation pattern is an exemplar of the consideration that the software architect/developer must pay mind to. The goal is to ensure that the software has zero downtime during application lifecycle events that affect numerous apps.

Figure 7.10. During the rolling upgrade of the Connections’ Posts service, the different instances will be sending different secrets. The apps have been designed to support this app lifecycle approach.

Figure 7.11. Application startup is an important event that many other components in the cloud-native software will be interested in.

Figure 7.12. Apps have the responsibility for broadcasting lifecycle events because other components will be affected. Those other components likewise have the responsibility for adapting to those changes.

Figure 7.13. Application lifecycle states and transitions between them. In the happy path, when apps are started and stopped, there’s an opportunity to broadcast app lifecycle change events. But when something goes awry, state-change broadcasts will be incorrect or may never even be generated.

Figure 7.14. Control loops play an important role in cloud-native systems, providing redundancy that compensates for “glitches” in the system.

Figure 7.15. All lifecycle stages are passed through for a single-function invocation.

Figure 7.16. Serverless computing requires a platform that optimizes the early stages, and the developer is responsible for optimizing the starting and execution of the app.

Chapter 8. Accessing apps: Services, routing, and service discovery

Figure 8.1. In cloud-native software, apps are deployed as multiple instances. For the software to function predictably, you want each set of app instances to operate as a single logical entity.

Figure 8.2. Each set of app instances is represented by a logical entity that defines the behavior of the app. That behavior is expected from all instances.

Figure 8.3. Your software is defined as a composition of services. Each service is implemented as a set of service instances.

Figure 8.4. The single logical app represented by a set of app instances is a service. The protocol that allows a client to find and access its dependent services is service discovery. The means for distributing incoming requests across the set of app instances is dynamic routing.

Figure 8.5. The Google search service is addressed via the name www.google.com, and that name is mapped to a concrete IP address via DNS. The Google platform keeps the list of routes to search service instances up to date, and load-balances requests among them.

Figure 8.6. Until now, the configuration of your blog aggregation software lacked the use of any type of service discovery protocol and bound the Connections’ Posts service to the Posts service via IP address. This results in a brittle deployment.

Figure 8.7. With centralized, or server-side, load balancing, a client request is handled by a cluster of load balancers that has a list of routes to service instances. The load balancer distributes the client requests across different app instances.

Figure 8.8. With client-side load balancing, the client sends requests directly to the service instances and performs the task of distributing requests across all instances. The list of routes to service instances is maintained within the client itself.

Figure 8.9. The manifest for the Posts (abstract) service and the service instances that implement it. The list of service instance routes is kept up to date via a control loop that uses the service selector to find all app instances that meet certain criteria (in this case, the label app: posts).

Figure 8.10. Concrete implementation of the Posts service running in Minikube. The Kube Proxy is a load-balancer implementation and includes the list of IP addresses to all instances of the Posts service.

Figure 8.11. At the time of service access, the service discovery protocol allows a client to refer to a service by name, resulting in a more resilient binding between them.

Figure 8.12. The service discovery protocol must account for the eventually consistent nature of the Domain Name System.

Figure 8.13. DNS entries that map domain names to IP addresses

Figure 8.14. Service discovery differs depending on whether client-side load balancing or server-side load balancing is used.

Figure 8.15. Kubernetes provides an implementation of the service discovery protocol with the inclusion of a domain name service and processes that automatically create and access entries in that registry.

Chapter 9. Interaction redundancy: Retries and other control loops

Figure 9.1. Certain design patterns applied on both sides of an interaction will yield far more robust and reliable systems. We’ll cover client-side patterns in this chapter, and service-side patterns in the next.

Figure 9.2. Retries can insulate parts of your distributed system from errors in other parts.

Figure 9.3. Restricted networks act like restricted highways, backing up requests that keep coming in the same volumes as before. Even when the restrictions are lifted, it can take some time before all of the queued-up traffic is moving again.

Figure 9.4. The client, the Connections’ Posts service, will retry on connection or read timeouts to the Posts service. It will continue trying until it receives a success status code from the HTTP request to the Posts service.

Figure 9.5. A deployment containing five instances of the Connections’ Posts service and four of the Posts service results in 20 ways that an instance of the former may connect to an instance of the latter. There are four connections between instances of the Posts service and the single instance of the MySQL service. Retries are an effective way of finding a healthy path through the network of microservices.

Figure 9.6. Thinking ahead, you cache results when they’re available, so that when you later experience trouble, you have those cached values to use as a part of your fallback logic.

Figure 9.7. Implementation of client-side patterns such as retries and fallbacks yields a far more robust system. (You’ll turn to the services side of the interaction in the next chapter.)

Chapter 10. Fronting services: Circuit breakers and API gateways

Figure 10.1. Just as the client can and should implement certain patterns to act as a good participant in the interaction, so too should the service. These are the patterns covered in this chapter.

Figure 10.2. You model the operation of the circuit breaker via three states and define the conditions or events that cause transitions between them. When the circuit is Closed, traffic flows freely. When the circuit is Open, requests won’t reach the service. The Half-Open state is transitory, the means by which the circuit can be reset to Closed.

Figure 10.3. At times when a service is unavailable—because of network outages, trouble with the service itself, or another issue—one of the main benefits of circuit breakers is that they significantly reduce the amount of time wasted while waiting for responses that are at that moment unlikely to come.

Figure 10.4. For your first test run, you’ll be running with the naïve retries on the client side of the interaction, and a simple circuit breaker at the front of the service.

Figure 10.5. The deployment topology has versions of the Connections’ Posts and Connections services from the previous chapter and provides a new version of the Posts service. This implementation wraps the main Posts logic in a circuit breaker.

Figure 10.6. The default Hystrix implementation trips the circuit when 50% of requests fail and moves from the Open state to a Half-Open state seconds after entering the Open state. Successful or unsuccessful requests made while in the Half-Open state will transition the circuit breaker to Closed and Open states, respectively.

Figure 10.7. Failures can occur on either side of an interaction, and fallbacks provide safeguards.

Figure 10.8. The API gateway fronts all services and becomes the policy configuration and enforcement point for them.

Figure 10.9. You can think of the gateway as a single logical entity, something that’s needed for administration. But for cloud-native architectures, the implementation is best distributed.

Figure 10.10. The distributed gateway runs as a sidecar to each service. In Kubernetes this is achieved by running two containers in a single pod—one that’s the primary service and the other a gateway sidecar.

Figure 10.11. Figure 10.7 redrawn with retry behavior on the client side of the interaction implemented in a sidecar, and the circuit breaker on the service side also implemented in a sidecar.

Figure 10.12. The abstract “gateway” of figure 10.10 is now made concrete with an Envoy sidecar, one of several sidecar implementations.

Figure 10.13. A service mesh brings together sidecars and a control plane for their management.

Chapter 11. Troubleshooting: Finding the needle in the haystack

Figure 11.1. With a pull-based metrics-gathering approach, each service implements a metrics endpoint that’s accessed at a regular interval to capture and store the values for subsequent search and analysis.

Figure 11.2. The collector that implements the metrics aggregator must reach each service instance at every interval and must therefore control the load balancing. It will interact through a service discovery protocol to keep up to date with IP address changes.

Figure 11.3. The metrics gatherer must address each service instance individually, and because those IP addresses are accessible only from within a runtime environment such as Kubernetes (external access is via load balancer), the metrics gather is also generally deployed within that network space. In the case of Kubernetes, this also allows you to use the built-in DNS service for service discovery.

Figure 11.4. In a push-based metrics solution, each service sends metrics to an aggregation and storage service at a certain interval.

Figure 11.5. When a service mesh is used, the application services are simply configured to connect to the local sidecar proxy, and the service mesh control plane is used to keep the configuration of the metrics delivery components up to date.

Figure 11.6. Diagram appearing in a presentation from Scott Mansfield of Netflix shows a request to the Netflix homepage results in a series of downstream service invocations. Distributed tracing allows you to gain visibility into this complex call tree.

Figure 11.7. Requests carry tracers that are propagated in downstream requests. The tracers are then available in the runtime context of a service invocation and annotates data that’s aggregated into a distributed tracing service.

Figure 11.8. From the annotated log output, you can piece together some of the flow of a single request—that with trace ID 2e30. Notice that you can’t see where the calls to the services came from.

Figure 11.9. Here, the service invocations are overlaid on the time, trace ID, and span ID stamped log output shown in the previous figure. This information isn’t currently appearing in your logs.

Figure 11.10. Zipkin provides a user interface that allows for search through the data stored in the distributed metrics database and pulls together entries that are related through a common trace ID. This display shows five such traces, each of which draws together five individual service requests, represented as spans.

Figure 11.11. Zipkin display showing the details of a single request to the Connections’ Posts service. This service request resulted in four downstream requests: one to the Connections service, one to the Posts service, and then two more requests to the Connections service. The latency for each request, represented as a span, is also shown.

Figure 11.12. While the network was disrupted, requests to the Connections’ Posts service resulted in failed downstream requests. You see, for example, that what normally was satisfied with four downstream requests resulted in many more requests/spans. The bars reporting the time and number of spans (for example, “26.488s 22 spans”) are also now colored red, indicating that some of those downstream requests returned errors.

Figure 11.13. The details of one of the request traces show repeated failed calls to the Posts service, each taking roughly 500 ms. This is the value of the request time-out on the HTTP invocations made from the Connections’ Posts service.

Figure 11.14. When the network is restored, downstream requests again succeed, but you can see from the time taken to fulfill Connections’ Posts requests that a backlog of traffic had been generated and required time to dissipate.

Chapter 12. Cloud-native data: Breaking the data monolith

Figure 12.1. User requirements for software drive our development toward cloud-native architectural and management tenets. For cloud-native data, we’ll turn our focus to modularity and the autonomy that comes from it.

Figure 12.2. Independent microservices that share a single database are not autonomous.

Figure 12.3. A simple topology with an aggregating service communicating with dependent services via request/response.

Figure 12.4. Whenever one of the dependent services is unavailable or otherwise not functioning correctly, the Connections’ Posts service will also fail to generate a result.

Figure 12.5. A cache added to the Connections’ Posts service will store the responses from successful requests to dependent services. The source of truth for the data remains in the databases tied to each of the downstream services; the storage local to the Connections’ Posts service is not an authoritative copy.

Figure 12.6. By adding a cache to Connections’ Posts, you add a degree of autonomy to the service and achieve greater resilience as a result.

Figure 12.7. When changes occur in downstream services, events describing those changes are sent to interested parties where their local storage is updated.

Figure 12.8. The event-driven approach allows the Connections’ Posts service to operate with complete autonomy, using the data in the local storage. Missed events, however, can corrupt that local storage, “successfully” returning incorrect results.

Figure 12.9. Events are usually of interest to numerous parties, so when they’re not properly delivered, this can cause inconsistencies to propagate throughout the system.

Figure 12.10. With the addition of an event log, you’ve now completely decoupled each of the three services from one another. Events are produced into and consumed from the event log, and the event log is responsible for retaining the events until they’re no longer needed.

Figure 12.11. Events are produced into and consumed from the event log, which maintains those events as long as they’re needed. Through use of the event log, you’ve entirely decoupled the services from one another.

Figure 12.12. The full event and data topology of our implementation. The Posts and Connections services both “own” data (source of truth) and produce events (dotted arrows) when changes occur in that data. Posts and Connections’ Posts both store data they don’t own (local storage) and update that data by handling events (solid arrows).

Figure 12.13. The directory structure for our three microservices, showing the organization of event-producing and -consuming code, as well as read APIs and both “owned” data storage and “local” data storage.

Figure 12.14. A service implements a write controller that’s responsible for taking changes to the first-class entities of the service, an event handler that’s responsible for maintaining a local database of nonprimary entity data that’s nevertheless part of the bounded context, and a read controller that supports querying data across these databases.

Figure 12.15. The event topology defines the topics that will hold events and the producers and consumers of each. The Connections service produces users and connection events. The Posts service produces post events and consumes user events. The Connections’ Posts service consumes user, connection, and post events.

Figure 12.16. Messaging systems, largely standardized with JMS, provide support for queues and topics. Queues retain messages until each one is consumed. Topics don’t retain any messages, instead simply delivering them to all available subscribers.

Figure 12.17. Event topics in Kafka have behaviors that are a hybrid between JMS topics and queues. Like the old-school topics, events are delivered to all unique group IDs—there are multiple subscribers. But within a set of listeners that share the same group ID, the behavior is like a queue, delivering the event to one of the listeners.

Figure 12.18. Our derivation of cloud-native data begins by breaking apart the data monolith so that the data supports the bounded contexts of the microservices. Microservices get their own databases, and where needed, data is kept consistent across the distributed data fabric through eventing.

Figure 12.19. The write controller only writes to the event log, which is now the source of truth. The local database for the microservice stores only projections derived from the event log data; this derivation is implemented in the event handler.

Figure 12.20. The event log is the single source of truth. All microservice-local stores are projections derived from the events in the event log, by the event handlers. The microservice-local stores are only projections.

List of Tables

Chapter 9. Interaction redundancy: Retries and other control loops

Table 9.1. Employing a simple retry with other patterns can eliminate or lessen negative impacts.

Chapter 10. Fronting services: Circuit breakers and API gateways

Table 10.1. A circuit breaker provides significant protections against retry storms.

Table 10.2. Results from the network outage simulations show the benefit of applying certain cloud-native patterns to service interactions.

Chapter 12. Cloud-native data: Breaking the data monolith

Table 12.1. Service roles in our event-driven software architecture

Table 12.2. Service roles in our event-sourced software architecture

List of Listings

Chapter 4. Event-driven microservices: It’s not just request/response

Listing 4.1. Method from ConnectionsPostsController.java

Listing 4.2. Method from PostsWriteController.java

Listing 4.3. Method from EventsController.java of Connections’ Posts service

Chapter 5. App redundancy: Scale-out and statelessness

Listing 5.1. LoginController.java

Listing 5.2. CloudnativeApplication.java

Listing 5.3. ConnectionsPostsController.java

Listing 5.4. CloudnativeApplication.java

Listing 5.5. LoginController.java

Listing 5.6. ConnectionsPostsController.java

Chapter 6. Application configuration: Not just environment variables

Listing 6.1. application.properties

Listing 6.2. PostsController.java

Listing 6.3. cookbook-deployment-connectionsposts.yaml

Listing 6.4. Utils.java

Listing 6.5. PostsController.java

Listing 6.6. ConnectionsPostsController.java

Listing 6.7. Connections’ Posts application.properties

Chapter 7. The application lifecycle: Accounting for constant change

Listing 7.1. Utils.java

Listing 7.2. Method from PostsController.java

Listing 7.3. Method from ConnectionsPostsController.java

Listing 7.4. Method from the Utils class of the ConnectionsPosts service

Listing 7.5. Method from Posts_Controller.java

Listing 7.6. Excerpt from cookbook-deployment-posts.yaml

Chapter 8. Accessing apps: Services, routing, and service discovery

Listing 8.1. Excerpt from cookbook-deployment-connectionsposts.yaml

Listing 8.2. Excerpt from redis-deployment.yam

Chapter 9. Interaction redundancy: Retries and other control loops

Listing 9.1. Excerpt from ConnectionsPostsController.java

Listing 9.2. Excerpt from ConnectionsPostsController.java

Listing 9.3. Method from PostsServiceClient.java

Listing 9.4. Excerpt from pom.xml for the Connections’ Posts service

Listing 9.5. Method from PostsServiceClient.java

Listing 9.6. Method from PostsServiceClient.java

Chapter 10. Fronting services: Circuit breakers and API gateways

Listing 10.1. Method from PostsService.java

Listing 10.2. Methods from PostsService.java

Chapter 11. Troubleshooting: Finding the needle in the haystack

Listing 11.1. Log output from Connections’ Posts

Listing 11.2. Log output from Connections

Listing 11.3. Log output from Posts

Listing 11.4. Added to pom.xml of each of the three microservices

Listing 11.5. Added to deployment yaml file for each of the three microservices

Chapter 12. Cloud-native data: Breaking the data monolith

Listing 12.1. Method from ConnectionsWriteController.java

Listing 12.2. Method from ConnectionsWriteController.java

Listing 12.3. Methods from EventHandler.java

Listing 12.4. Method from PostsWriteController.java

Listing 12.5. Method from EventHandler.java


Index

[SYMBOL][A][B][C][D][E][F][G][H][I][J][K][L][M][N][O][P][Q][R][S][T][U][V][W][Y][Z]

SYMBOL

401 – Unauthorized response

500 status code

A

A/B testing

access logging

actual state

/actuator/metrics endpoint

all argument, 2nd, 3rd, 4th

Amazon Web Services (AWS), 2nd

AOP dependency

Apache Avro

Apache Kafka

Apache Log4j

API endpoints

API gateways

case for

topology

app health endpoints

app instances

application configuration

configuration layer

dynamic scaling

infrastructure changes causing configuration changes

injecting application configuration

config server, 2nd

security

injecting system/environment values

building microservices

running apps

setting up

updating with zero downtime

application lifecycle

app lifecycle events

blue/green upgrades

coordinating across different lifecycles

credential rotation

building microservices

running apps

setting up

ephemeral runtime environments

operational concerns

parallel deployments

rolling upgrades

serverless computing

state visibility

application logging

application metrics

pulling metrics

pushing metrics

application.properties file, 2nd, 3rd, 4th

applicationConfiguration key

ApplicationContextAware class

ApplicationPreparedEvent

applications

dynamic routing

client-side load balancing

route freshness

server-side load balancing

in cloud-native model

requirements for

data-driven

Internet of Things (IoT)

mobile support

multidevice support

shortened feedback cycles

zero downtime

service abstraction

blog aggregator

Google searches

service discovery

example of

in Kubernetes

on web

with client-side load-balancing

stateless

in cloud

stateful services and

apt get function

at-least-once delivery

auth token

authentication

Authentication app

authorization

availability, 2nd

availability zones (AZs), 2nd, 3rd, 4th

AWS (Amazon Web Services), 2nd

AWS Elastic Beanstalk

AZs (availability zones), 2nd, 3rd, 4th

Azure App Service

B

-b command line switch

back-off policy

@Backoff annotation

blog aggregator, service abstraction

blue/green deployment, 2nd, 3rd

blue/green upgrades

built-in DNS service

C

CAP theorem, 2nd

Cassandra database

CD (continuous delivery)

centralized load balancing

change, 2nd

as exception

as rule

change control, 2nd

different approach in treating

support for

circuit breakers

implementing

running apps

setting up

software circuit breakers

CLI (command-line interface)

client library

client-side load balancing

dynamic routing

service discovery

client-side patterns

Closed state, circuit breaker

cloud

cloud-native software versus

evolution of cloud-native software

stateful apps in

decomposing monolith and binding to database

poor handling of session state

Cloud Architecture Strategy, AWS

Cloud Foundry, 2nd

Cloud Foundry Operations Manager application

cloud-native applications

cloud-native data

caching

event log

event payload

idempotency

implementing event-driven microservices

topics and queues

event sourcing

implementing

source of truth

moving from request/response to event driven

cloud-native interactions

cloud-native platform

cloud-native repository

cloud-native software, 2nd, 3rd

application requirements

data-driven

Internet of Things

mobile support

multidevice support

shortened feedback cycles

zero downtime

cloud versus

defined

example of

interfacing with existing solutions

model for

cloud-native apps

cloud-native data

cloud-native interactions

reasons for not going cloud-native

cloud-native software delivery lifecycle

enablers

change is the rule

continuous delivery

repeatability

safe deployments

obstacles

change is exception

production instability

risky deployments

snowflakes

cloud-native software platforms

capabilities of

change control

containers, controlling what goes into

control functions

software development lifecycle (SDLC), support for entire

upgrading and vulnerability patching

core tenets of

containers

support for

evolution of

cloud

infrastructure-centric versus app-centric environment

map of responsibilities

cloudnative-circuitbreaker directory

cloudnative-connections microservice

cloudnative-eventlog module

cloudnative-posts microservice

cloudnative-requestresponse directory

cloudnative-statelessness directory

cloudnative-troubleshooting directory

CloudnativeApplication Spring Boot configuration

CloudnativeApplication.java file, 2nd

CMDB (configuration management database), 2nd

Cockcroft, Adrian

com.corneliadavis.cloudnative.connections.secrets property

com.corneliadavis.cloudnative.posts.secrets property, 2nd

com.corneliadavis.cloudnative.posts.write package, 2nd

command prompt, MYSQL

Command Query Responsibility Segregation (CQRS)

command-line interface (CLI)

Common Vulnerabilities and Exposures (CVE)

compliance

config layer

config map, Kubernetes

config package

config server, 2nd

running apps

setting up

configuration data store

configuration layer

configuration management database (CMDB), 2nd

configuredSecretsIn string

connection event

ConnectionEvent

CONNECTIONPOSTSCONTROLLER_IMPLEMENTRETRIES variable, 2nd

Connections microservice, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th, 12th, 13th, 14th, 15th, 16th, 17th, 18th, 19th

connections package

Connections service, configuring and deploying

Connections URL, 2nd, 3rd, 4th

Connections’ Posts microservice, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th, 12th, 13th, 14th, 15th, 16th, 17th, 18th, 19th, 20th

Connections’ Posts microservice

Connections’ Posts microservice

Connections’ Posts microservice

Connections’ Posts microservice

Connections’ Posts microservice

Connections’ Posts microservice

Connections’ Posts microservice

Connections’ Posts microservice

Connections’ Posts microservice

Connections’ Posts microservice

ConnectionsPosts controller

connectionsposts logs

connectionsposts package

connectionsposts-svc service

ConnectionsPostsController

ConnectionsPostsController.java file, 2nd, 3rd, 4th, 5th

ConnectionsWriteController

consistency, favoring availability over

containers

controlling what goes into

overview

continuous delivery (CD)

control functions, 2nd

control loops, 2nd, 3rd

controlling

types of

control plane

control-related functions

cookbook-deployment-connectionposts.yaml file

cookbook-deployment-kubernetes-connectionposts.yaml file

Core DNS, 2nd

CORS (cross-origin resource sharing)

cost management

Couchbase database

CrashLoopBackOff

create database command

create database cookbook command

credential rotation, 2nd, 3rd

building microservices

running apps

setting up

credentials, 2nd

CredHub, Pivotal

cross-origin resource sharing (CORS)

CRUD services, 2nd

curl command, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th, 12th, 13th, 14th, 15th, 16th, 17th, 18th, 19th

curl localhost:8080/connectionsosts/cdavisafc command

curl localhost:8081/posts command

curl localhost:8082/connections command

curl localhost:8082/users command

cursor

CVE (Common Vulnerabilities and Exposures)

D

daemonset controller

data-driven, as application requirement

DELETE operation

deleteDeploymentComplete.sh, 2nd

deployable artifacts, 2nd

deployApps.sh, 2nd, 3rd

deployment

parallel

risky

design patterns

desired state

distributed tracing

assembling traces via Zipkin

implementation details

running apps

setting up

tracer output

distribution, support for

DNS (Domain Name System), 2nd, 3rd

Docker

docker build command, 2nd, 3rd

Docker container

Docker Hub, 2nd, 3rd, 4th, 5th, 6th, 7th

Docker images, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th

docker push command, 2nd

Domain Name System (DNS), 2nd, 3rd

drawFromConfigServer

dynamic routing, 2nd

client-side load balancing

route freshness

server-side load balancing

dynamic scaling

E

EC2 (Elastic Compute Cloud platform), 2nd

Amazon and reliability support

availability in other countries

Elasticsearch

ELK stack

EmbeddedServletContainer

encryption of data in flight

endpoints controller

enterprise service bus (ESB)

environment variables, 2nd, 3rd, 4th

Envoy, 2nd, 3rd

ephemeral runtime environments

ESB (enterprise service bus)

Eureka

event handler, 2nd, 3rd

event log, 2nd, 3rd

event payload

idempotency

implementing event-driven microservices

running apps

setting up

topics and queues

event payload

event sourcing, 2nd

implementing

source of truth

event store/log

event topology

event-driven programming model, 2nd

cloud-native data

implementing event-driven microservices

running apps

setting up

microservices

obtaining and building

running

request/response programming model versus

setting up

studying code

event-driven software architecture

event-sourcing patterns

eventlogstart tag

EventsController

eventual consistency, 2nd

exactly-once delivery

F

FaaS (function-as-a-service)

failures, 2nd

fallback logic, 2nd

fallbackMethod1

fallbackMethod2

fat jar

favorites service

feedback cycles, shortened

foobar

front-loaded cycle

function-as-a-service (FaaS)

G

GAE (Google App Engine)

GCP (Google Cloud Platform), 2nd, 3rd, 4th, 5th

Get Data calls

get method

GET operation

get pods output

GET request

getByUsername method

getPostsByUserId method

Git

git checkout master command

GitHub, 2nd, 3rd

GKE (Google Kubernetes Engine)

Google App Engine (GAE)

Google Cloud Platform (GCP), 2nd, 3rd, 4th, 5th

Google Kubernetes Engine (GKE)

Google searches, service abstraction

group ID

groupId, 2nd

H

H2 dependency

Half-Open state, circuit breaker, 2nd, 3rd

hardcoding strings

HEAD request

health endpoints and probes

/healthz endpoint

@HistrixCommand() annotation, 2nd, 3rd, 4th

horizontal scaling

HTTP 401 – Unauthorized response

HTTP error

HTTP POST event, 2nd

HTTP requests

HTTP sessions

Hystrix, 2nd, 3rd

I

–i switch

IaaS (infrastructure-as-a-service)

idempotency

idempotent method

identity store

imperative programming

in-memory hash map

independent microservices, 2nd, 3rd

infect endpoint

infrastructure as code

infrastructure-as-a-service (IaaS)

INSTANCE_IP variable, 2nd, 3rd, 4th, 5th

IoT (Internet of Things)

IP addresses, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th

ip variable

ipaddress property, 2nd, 3rd

IPADDRESS variable

isHealthy Boolean

Istio, 2nd

isValidSecret method

J

J2EE (Java 2 Platform, Enterprise Edition)

JAR files, 2nd, 3rd, 4th, 5th

Java 2 Platform, Enterprise Edition (J2EE)

java command

Java Development Kit (JDK)

Java Runtime Environment (JRE)

JavaScript

JBoss, 2nd

jdbc URL

JDK (Java Development Kit)

JMeter, 2nd, 3rd, 4th, 5th, 6th

JRE (Java Runtime Environment)

K

Kafka, 2nd, 3rd

key/value pairs

key/value store, 2nd

keys * command

Kibana

kind clients

kind retries

Kube DNS

Kube Proxy

kubectl apply command, 2nd, 3rd, 4th

kubectl command, 2nd, 3rd

kubectl create -f cookbook-deployment-connections.yaml

kubectl create -f cookbook-deployment-posts.yaml

kubectl create -f mysql-deployment.yaml command

kubectl create -f redis-deployment.yaml command

kubectl create command

kubectl create namespace command

kubectl delete deploy command

kubectl delete deploy jmeter-deployment command, 2nd

kubectl exec command

$ kubectl get all command

kubectl get all command, 2nd, 3rd, 4th, 5th, 6th, 7th

kubectl get pods command, 2nd

kubectl logs -f pod/posts-fc74d75bc-92txh command

kubectl logs -l app=connections command

kubectl logs -l app=connectionsposts command

kubectl logs -l app=posts command

kubectl logs command

kubectl logs –f <podname> command

kubectl logs –f command

Kubernetes, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th, 12th, 13th, 14th, 15th, 16th, 17th, 18th, 19th, 20th

Kubernetes

Kubernetes

Kubernetes

Kubernetes

Kubernetes

Kubernetes

Kubernetes

Kubernetes

eventual consistency and

service discovery in

L

latency

load balancers, 2nd

load balancing, 2nd

load spikes

LoadBalancer

./loadData.sh command

loadData.sh script

local storage

localhost

Logback

/login endpoint

LoginController.java file, 2nd

Logstash

look-aside caching

loose coupling, 2nd, 3rd

M

manageability

Mansfield, Scott

medium trust code

messaging systems

metrics gatherer

microservices, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th, 12th

credential rotation

decomposing monolith and binding to database

event driven

running apps

setting up

obtaining and building

event-driven programming model

request/response programming model

running

event-driven programming model

request/response programming model

system/environment values

Microsoft Azure

Minikube, 2nd, 3rd, 4th, 5th, 6th

minikube command

minikube service –url sccs command

minikube service list command

minikube service mysql –url command

mobile devices, support for

Model, View, Controller (MVC) pattern

modularity

MongoDB

msql CLI

MVC (Model, View, Controller) pattern

mvn clean install command, 2nd, 3rd, 4th, 5th

my global cookbook

MySQL, 2nd, 3rd, 4th, 5th

mysql CLI, 2nd, 3rd, 4th, 5th, 6th

mysql command

mysql-57bdb878f5-dhlck pod

mysql-deployment.yaml

N

namespaces controller

Netflix, 2nd, 3rd, 4th, 5th

Netflix Eurek

Netflix Ribbon

network disruption

NewFromConnectionsController class

newPost method

Nginx

O

oldSecret

onApplicationEvent method

Open state, circuit breaker, 2nd

OpenSSH

openssh function

operating system version (os.version)

OPTIONS request

OS kernel, 2nd

OS root filesystem

P

parallel deployments

partition tolerance

PID (process ID)

PII (personally identifiable information)

ping

pipelines

Pivotal Cloud Cache

pods, 2nd, 3rd

POM files

pom.xml files

post event

POST request, 2nd, 3rd

PostEvent

Posts microservice, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th, 11th, 12th, 13th, 14th, 15th, 16th, 17th, 18th, 19th, 20th

Posts microservice

Posts microservice

Posts microservice

Posts microservice

posts package

Posts service, configuring and deploying, 2nd

Posts URL, 2nd, 3rd, 4th

PostsController class

PostsController.java file, 2nd, 3rd, 4th

PostsService class, 2nd

PostsServiceClient class

postsServiceClient.getPosts

PostSummary class

PostsWriteController

Process ID (PID)

production instability, 2nd

Prometheus

property files, 2nd, 3rd, 4th, 5th

pull-based approach

PUT operation

Q

queues

R

RabbitMQ

read controller

Read role, 2nd

read-through caching

Ready to Ship software

recommendations service

@Recover annotation, 2nd

recovery point objectives (RPOs)

recovery time objectives (RTOs)

Redis, 2nd, 3rd, 4th, 5th, 6th, 7th

Redis IP, 2nd

Redis port, 2nd

redis-cli, 2nd, 3rd

redis-svc

redundancy, 2nd, 3rd

/refresh URL

regions

repeatability

control of deployable artifact

control of environment

control of process

replica sets

replication controller

request durability

request resilience

request retries

kind clients

retry storms

running apps

setting up

simple retries

running apps

setting up

when not to retry

request/response pattern, 2nd, 3rd

request/response programming model

cloud-native data

event-driven programming model versus

microservices

obtaining and building

running

setting up

studying code

resilience, 2nd, 3rd

resiliency patterns

resilient interactions

control loops

controlling

types of

fallback logic

request retries

kind clients

retry storms

simple retries

when not to retry

ResourceAccessException

responsiveness

RESTful service

restricted networks

restTemplate, 2nd

retry behavior

retry logic disabled

retry logic enabled

retry pattern

retry storms, 2nd, 3rd

fallback logic

running apps

setting up

@Retryable method, 2nd, 3rd

returning cached results command

Ribbon client

risky deployments

rolling upgrades, 2nd, 3rd

route commands

route freshness

routing, 2nd

RPOs (recovery point objectives)

RTOs (recovery time objectives)

runbook

Running App Version

S

S3 (Simple Storage Service)

safe methods

scale-out/in

SCCS (Spring Cloud Configuration Server), 2nd, 3rd, 4th, 5th, 6th

SCCS URL

SDLC (Software Development Lifecycle), 2nd

continuous delivery

streamlined

traditional

variability across

security, 2nd

sequential programming model

server-side load balancing

serverless computing

service abstraction

blog aggregator

Google searches

service discovery, 2nd, 3rd, 4th

example of

in Kubernetes

on web

with client-side load-balancing

service mesh, 2nd, 3rd

control plane

sidecars

service roles, 2nd

service-side patterns

session ID

session state, poor handling of

configuring and deploying Connections and Posts services

configuring and deploying connections’ Posts service

deploying and configuring database

introducing cloud-native platform

side effects

sidecars, 2nd

single logical app

single logical entity

Site Reliability Engineering (SRE)

SLAs (service-level agreements), 2nd

sleep command

sleepWindowMilliseconds

SLF4J

snowflakes, 2nd, 3rd, 4th, 5th, 6th, 7th

SO (special order) application

software artifacts

software delivery lifecycle

Software Development Lifecycle (SDLC), 2nd, 3rd, 4th, 5th

software-defined compute

source code control (SCC) system

source of the truth, 2nd

source-level debugging

span ID, 2nd

special order (SO) application

Splunk, 2nd

Spring Boot application, 2nd, 3rd, 4th, 5th

Spring Boot JPA

Spring Cloud

Spring Cloud Configuration Server (SCCS), 2nd, 3rd, 4th, 5th

Spring Cloud Sleuth

Spring Framework, 2nd

Spring Retry, 2nd

spring.zipkin.baseUrl property

SQS (Simple Queue Service)

SRE (Site Reliability Engineering)

ssh, 2nd

SSH access, 2nd

state visibility

state-change broadcasts

state-change events

statefulness and statelessness

HTTP sessions and sticky sessions

multiple instance deployment

stateful apps in cloud

decomposing monolith and binding to database

poor handling of session state

stateful services and stateless apps

making apps stateless

stateful services as special services

status.podIP attribute

stderr, 2nd

stdout, 2nd

stem cells

sticky sessions, 2nd

system variables

System.getenv

System.out

system/environment values

building microservices

running apps

setting up

systemEnvironment key

T

targetPort

TCP liveness probes

TCP/UDP protocol level

theFirstSecret

theSecondSecret

tight coupling

tokens, 2nd

Tomcat container, 2nd, 3rd

topics

trace ID, 2nd

TRACE request

tracers

traditional load-balancing

troubleshooting

application logging

application metrics

pulling metrics from cloud-native applications

pushing metrics from cloud-native applications

distributed tracing

assembling traces via Zipkin

implementation details

running apps

setting up

tracer output

Twelve-Factor App, 2nd

U

UAT (user acceptance testing)

unauthenticated

unified log

upgrading

user acceptance testing (UAT)

user event

User Profile app

user-ID-to-username mapping data

UserEvent

Users URL, 2nd, 3rd, 4th

Utils class, 2nd, 3rd, 4th, 5th

Utils.java file, 2nd

V

valid login token

@Value annotation, 2nd

Vault, HashiCorp, 2nd

vent log topic

Version of Deployable Artifact

Version of the App Config

VERSIONING_TRIGGER

vertical scaling

VMs (virtual machines), 2nd

vulnerability patching

W

watch kubectl get all command

watch kubectl get pods command, 2nd

WebLogic, 2nd

WebSphere, 2nd

while loop, 2nd

Write and Event Producer

write controller, 2nd, 3rd

write logic (commands)

Y

YAML files, 2nd

Z

zero downtime, 2nd, 3rd

as application requirement

updating application configuration with

zero-downtime credential rotation pattern

Zipkin, 2nd

Zuul

cloud_native_patterns_-_designing_change-tolerant_software_by_cornelia_davis.txt · Last modified: 2024/04/28 03:28 by 127.0.0.1