Microservices with Spring Boot and Spring Cloud - Second Edition

Book description

Create and deploy production-quality microservices-based applications — New edition updated for the smooth running of Spring, Java, Kubernetes, and Istio, with an introduction to Helm 3 and support for Mac and Windows with WSL2

Key Features

  • Build cloud-native production-ready microservices with this comprehensively updated guide
  • Understand the challenges of building large-scale microservice architectures
  • Learn how to get the best out of Spring Cloud, Kubernetes, and Istio in combination

Book Description

Want to build and deploy microservices, but don't know where to start? Welcome to Microservices with Spring Boot and Spring Cloud.

This edition features the most recent versions of Spring, Java, Kubernetes, and Istio, demonstrating faster and simpler handling of Spring Boot, local Kubernetes clusters, and Istio installation. The expanded scope includes native compilation of Spring-based microservices, support for Mac and Windows with WSL2, and an introduction to Helm 3 for packaging and deployment. A revamped security chapter now follows the OAuth 2.1 specification and makes use of the newly launched Spring Authorization Server from the Spring team.

You'll start with a set of simple cooperating microservices, then add persistence and resilience, make your microservices reactive, and document their APIs using OpenAPI.

Next, you'll learn how fundamental design patterns are applied to add important functionality, such as service discovery with Netflix Eureka and edge servers with Spring Cloud Gateway. You'll deploy your microservices using Kubernetes and adopt Istio, then explore centralized log management using the Elasticsearch, Fluentd, and Kibana (EFK) stack, and then monitor microservices using Prometheus and Grafana.

By the end of this book, you'll be building scalable and robust microservices using Spring Boot and Spring Cloud.

What you will learn

  • Build reactive microservices using Spring Boot
  • Develop resilient and scalable microservices using Spring Cloud
  • Use OAuth 2.1/OIDC and Spring Security to protect public APIs
  • Implement Docker to bridge the gap between development, testing, and production
  • Deploy and manage microservices with Kubernetes
  • Apply Istio for improved security, observability, and traffic management
  • Write and run automated microservice tests with JUnit, testcontainers, Gradle, and bash

Who this book is for

If you're a Java or Spring Boot developer learning how to build microservice landscapes from scratch, then this book is for you. You don't need any prior knowledge about microservices architecture to get started, but a solid grasp and enough experience in Java and Spring Boot to build apps autonomously is a must.

Table of contents

  1. Preface
    1. Who this book is for
    2. What this book covers
    3. To get the most out of this book
    4. Get in touch
  2. Part I: Getting Started with Microservice Development Using Spring Boot
    1. Introduction to Microservices
      1. Technical requirements
      2. My way into microservices
        1. Benefits of autonomous software components
        2. Challenges with autonomous software components
        3. Enter microservices
        4. A sample microservice landscape
      3. Defining a microservice
      4. Challenges with microservices
      5. Design patterns for microservices
        1. Service discovery
          1. Problem
          2. Solution
          3. Solution requirements
        2. Edge server
          1. Problem
          2. Solution
          3. Solution requirements
        3. Reactive microservices
          1. Problem
          2. Solution
          3. Solution requirements
        4. Central configuration
          1. Problem
          2. Solution
          3. Solution requirements
        5. Centralized log analysis
          1. Problem
          2. Solution
          3. Solution requirements
        6. Distributed tracing
          1. Problem
          2. Solution
          3. Solution requirements
        7. Circuit breaker
          1. Problem
          2. Solution
          3. Solution requirements
        8. Control loop
          1. Problem
          2. Solution
          3. Solution requirements
        9. Centralized monitoring and alarms
          1. Problem
          2. Solution
          3. Solution requirements
      6. Software enablers
      7. Other important considerations
      8. Summary
    2. Introduction to Spring Boot
      1. Technical requirements
      2. Spring Boot
        1. Convention over configuration and fat JAR files
        2. Code examples for setting up a Spring Boot application
          1. The magic @SpringBootApplication annotation
          2. Component scanning
          3. Java-based configuration
      3. Spring WebFlux
        1. Code examples of setting up a REST service
          1. Starter dependencies
          2. Property files
          3. Sample RestController
      4. springdoc-openapi
      5. Spring Data
        1. Entity
        2. Repositories
      6. Spring Cloud Stream
        1. Code examples for sending and receiving messages
      7. Docker
      8. Summary
      9. Questions
    3. Creating a Set of Cooperating Microservices
      1. Technical requirements
      2. Introducing the microservice landscape
        1. Information handled by the microservices
          1. Product service
          2. Review service
          3. Recommendation service
          4. Product composite service
          5. Infrastructure-related information
        2. Temporarily replacing service discovery
      3. Generating skeleton microservices
        1. Using Spring Initializr to generate skeleton code
        2. Setting up multi-project builds in Gradle
      4. Adding RESTful APIs
        1. Adding an API and a util project
          1. The API project
          2. The util project
        2. Implementing our API
      5. Adding a composite microservice
        1. API classes
        2. Properties
        3. Integration component
        4. Composite API implementation
      6. Adding error handling
        1. The global REST controller exception handler
        2. Error handling in API implementations
        3. Error handling in the API client
      7. Testing APIs manually
      8. Adding automated microservice tests in isolation
      9. Adding semi-automated tests of a microservice landscape
        1. Trying out the test script
      10. Summary
      11. Questions
    4. Deploying Our Microservices Using Docker
      1. Technical requirements
      2. Introduction to Docker
        1. Running our first Docker commands
      3. Challenges with running Java in Docker
        1. Limiting available CPUs
        2. Limiting available memory
      4. Using Docker with one microservice
        1. Changes in source code
        2. Building a Docker image
        3. Starting up the service
        4. Running the container detached
      5. Managing a landscape of microservices using Docker Compose
        1. Changes in the source code
        2. Starting up the microservice landscape
      6. Automating tests of cooperating microservices
        1. Troubleshooting a test run
      7. Summary
      8. Questions
    5. Adding an API Description Using OpenAPI
      1. Technical requirements
      2. Introduction to using springdoc-openapi
      3. Adding springdoc-openapi to the source code
        1. Adding dependencies to the Gradle build files
        2. Adding OpenAPI configuration and general API documentation to the ProductCompositeService
        3. Adding API-specific documentation to the ProductCompositeService interface
      4. Building and starting the microservice landscape
      5. Trying out the OpenAPI documentation
      6. Summary
      7. Questions
    6. Adding Persistence
      1. Technical requirements
      2. Chapter objectives
      3. Adding a persistence layer to the core microservices
        1. Adding dependencies
        2. Storing data with entity classes
        3. Defining repositories in Spring Data
      4. Writing automated tests that focus on persistence
        1. Using Testcontainers
        2. Writing persistence tests
      5. Using the persistence layer in the service layer
        1. Logging the database connection URL
        2. Adding new APIs
        3. Calling the persistence layer from the service layer
        4. Declaring a Java bean mapper
        5. Updating the service tests
      6. Extending the composite service API
        1. Adding new operations in the composite service API
        2. Adding methods in the integration layer
        3. Implementing the new composite API operations
        4. Updating the composite service tests
      7. Adding databases to the Docker Compose landscape
        1. The Docker Compose configuration
        2. Database connection configuration
        3. The MongoDB and MySQL CLI tools
      8. Manual tests of the new APIs and the persistence layer
      9. Updating the automated tests of the microservice landscape
      10. Summary
      11. Questions
    7. Developing Reactive Microservices
      1. Technical requirements
      2. Choosing between non-blocking synchronous APIs and event-driven asynchronous services
      3. Developing non-blocking synchronous REST APIs
        1. An introduction to Project Reactor
        2. Non-blocking persistence using Spring Data for MongoDB
          1. Changes in the test code
        3. Non-blocking REST APIs in the core services
          1. Changes in the APIs
          2. Changes in the service implementations
          3. Changes in the test code
          4. Dealing with blocking code
        4. Non-blocking REST APIs in the composite services
          1. Changes in the API
          2. Changes in the service implementation
          3. Changes in the integration layer
          4. Changes in the test code
      4. Developing event-driven asynchronous services
        1. Handling challenges with messaging
          1. Consumer groups
          2. Retries and dead-letter queues
          3. Guaranteed order and partitions
        2. Defining topics and events
        3. Changes in the Gradle build files
        4. Consuming events in the core services
          1. Declaring message processors
          2. Changes in the service implementations
          3. Adding configuration for consuming events
          4. Changes in the test code
        5. Publishing events in the composite service
          1. Publishing events in the integration layer
          2. Adding configuration for publishing events
          3. Changes in the test code
      5. Running manual tests of the reactive microservice landscape
        1. Saving events
        2. Adding a health API
        3. Using RabbitMQ without using partitions
        4. Using RabbitMQ with partitions
        5. Using Kafka with two partitions per topic
      6. Running automated tests of the reactive microservice landscape
      7. Summary
      8. Questions
  3. Part II: Leveraging Spring Cloud to Manage Microservices
    1. Introduction to Spring Cloud
      1. Technical requirements
      2. The evolution of Spring Cloud
      3. Using Netflix Eureka for service discovery
      4. Using Spring Cloud Gateway as an edge server
      5. Using Spring Cloud Config for centralized configuration
      6. Using Resilience4j for improved resilience
        1. Sample usage of the circuit breaker in Resilience4j
      7. Using Spring Cloud Sleuth and Zipkin for distributed tracing
      8. Summary
      9. Questions
    2. Adding Service Discovery Using Netflix Eureka
      1. Technical requirements
      2. Introducing service discovery
        1. The problem with DNS-based service discovery
        2. Challenges with service discovery
        3. Service discovery with Netflix Eureka in Spring Cloud
      3. Setting up a Netflix Eureka server
      4. Connecting microservices to a Netflix Eureka server
      5. Setting up the configuration for development use
        1. Eureka configuration parameters
        2. Configuring the Eureka server
        3. Configuring clients to the Eureka server
      6. Trying out the discovery service
        1. Scaling up
        2. Scaling down
        3. Disruptive tests with the Eureka server
          1. Stopping the Eureka server
          2. Stopping a review instance
          3. Starting up an extra instance of the product service
      7. Starting up the Eureka server again
      8. Summary
      9. Questions
    3. Using Spring Cloud Gateway to Hide Microservices behind an Edge Server
      1. Technical requirements
      2. Adding an edge server to our system landscape
      3. Setting up Spring Cloud Gateway
        1. Adding a composite health check
        2. Configuring a Spring Cloud Gateway
          1. Routing rules
      4. Trying out the edge server
        1. Examining what is exposed outside the Docker engine
        2. Trying out the routing rules
          1. Calling the product composite API through the edge server
          2. Calling the Swagger UI through the edge server
          3. Calling Eureka through the edge server
          4. Routing based on the host header
      5. Summary
      6. Questions
    4. Securing Access to APIs
      1. Technical requirements
      2. Introduction to OAuth 2.0 and OpenID Connect
        1. Introducing OAuth 2.0
        2. Introducing OpenID Connect
      3. Securing the system landscape
      4. Protecting external communication with HTTPS
        1. Replacing a self-signed certificate at runtime
      5. Securing access to the discovery server
        1. Changes in the Eureka server
        2. Changes in Eureka clients
      6. Adding a local authorization server
      7. Protecting APIs using OAuth 2.0 and OpenID Connect
        1. Changes in both the edge server and the product-composite service
        2. Changes in the product-composite service only
          1. Changes to allow Swagger UI to acquire access tokens
        3. Changes in the test script
      8. Testing with the local authorization server
        1. Building and running the automated tests
        2. Testing the protected discovery server
        3. Acquiring access tokens
          1. Acquiring access tokens using the client credentials grant flow
          2. Acquiring access tokens using the authorization code grant flow
        4. Calling protected APIs using access tokens
        5. Testing Swagger UI with OAuth 2.0
      9. Testing with an external OpenID Connect provider
        1. Setting up and configuring an account in Auth0
        2. Applying the required changes to use Auth0 as an OpenID provider
          1. Changing the configuration in the OAuth resource servers
          2. Changing the test script so it acquires access tokens from Auth0
        3. Running the test script with Auth0 as the OpenID Connect provider
        4. Acquiring access tokens using the client credentials grant flow
        5. Acquiring access tokens using the authorization code grant flow
        6. Calling protected APIs using the Auth0 access tokens
        7. Getting extra information about the user
      10. Summary
      11. Questions
    5. Centralized Configuration
      1. Technical requirements
      2. Introduction to the Spring Cloud Configuration server
        1. Selecting the storage type of the configuration repository
        2. Deciding on the initial client connection
        3. Securing the configuration
          1. Securing the configuration in transit
          2. Securing the configuration at rest
        4. Introducing the config server API
      3. Setting up a config server
        1. Setting up a routing rule in the edge server
        2. Configuring the config server for use with Docker
      4. Configuring clients of a config server
        1. Configuring connection information
      5. Structuring the configuration repository
      6. Trying out the Spring Cloud Configuration server
        1. Building and running automated tests
        2. Getting the configuration using the config server API
        3. Encrypting and decrypting sensitive information
      7. Summary
      8. Questions
    6. Improving Resilience Using Resilience4j
      1. Technical requirements
      2. Introducing the Resilience4j resilience mechanisms
        1. Introducing the circuit breaker
        2. Introducing the time limiter
        3. Introducing the retry mechanism
      3. Adding the resilience mechanisms to the source code
        1. Adding programmable delays and random errors
          1. Changes in the API definitions
          2. Changes in the product-composite microservice
          3. Changes in the product microservice
        2. Adding a circuit breaker and a time limiter
          1. Adding dependencies to the build file
          2. Adding annotations in the source code
          3. Adding fail-fast fallback logic
          4. Adding configuration
        3. Adding a retry mechanism
          1. Adding the retry annotation
          2. Adding configuration
        4. Adding automated tests
      4. Trying out the circuit breaker and retry mechanism
        1. Building and running the automated tests
        2. Verifying that the circuit is closed under normal operations
        3. Forcing the circuit breaker to open when things go wrong
        4. Closing the circuit breaker again
        5. Trying out retries caused by random errors
      5. Summary
      6. Questions
    7. Understanding Distributed Tracing
      1. Technical requirements
      2. Introducing distributed tracing with Spring Cloud Sleuth and Zipkin
      3. Adding distributed tracing to the source code
        1. Adding dependencies to build files
        2. Adding configuration for Spring Cloud Sleuth and Zipkin
        3. Adding Zipkin to the Docker Compose files
      4. Trying out distributed tracing
        1. Starting up the system landscape with RabbitMQ as the queue manager
        2. Sending a successful API request
        3. Sending an unsuccessful API request
        4. Sending an API request that triggers asynchronous processing
        5. Monitoring trace information passed to Zipkin in RabbitMQ
        6. Using Kafka as a message broker
      5. Summary
      6. Questions
  4. Part III: Developing Lightweight Microservices Using Kubernetes
    1. Introduction to Kubernetes
      1. Technical requirements
      2. Introducing Kubernetes concepts
      3. Introducing Kubernetes API objects
      4. Introducing Kubernetes runtime components
      5. Creating a Kubernetes cluster using Minikube
        1. Working with Minikube profiles
        2. Working with the Kubernetes CLI, kubectl
        3. Working with kubectl contexts
        4. Creating a Kubernetes cluster
      6. Trying out a sample deployment
      7. Managing a local Kubernetes cluster
        1. Hibernating and resuming a Kubernetes cluster
        2. Terminating a Kubernetes cluster
      8. Summary
      9. Questions
    2. Deploying Our Microservices to Kubernetes
      1. Technical requirements
      2. Replacing Netflix Eureka with Kubernetes Services
      3. Introducing how Kubernetes will be used
      4. Using Spring Boot's support for graceful shutdown and probes for liveness and readiness
      5. Introducing Helm
        1. Running Helm commands
        2. Looking into a Helm chart
        3. Helm templates and values
        4. The common library chart
          1. The ConfigMap template
          2. The Secrets template
          3. The Service template
          4. The Deployment template
        5. The components charts
        6. The environment charts
      6. Deploying to Kubernetes for development and test
        1. Building Docker images
        2. Resolving Helm chart dependencies
        3. Deploying to Kubernetes
        4. Changes in the test script for use with Kubernetes
        5. Testing the deployment
          1. Testing Spring Boot's support for graceful shutdown and probes for liveness and readiness
      7. Deploying to Kubernetes for staging and production
        1. Changes in the source code
        2. Deploying to Kubernetes
        3. Cleaning up
      8. Summary
      9. Questions
    3. Implementing Kubernetes Features to Simplify the System Landscape
      1. Technical requirements
      2. Replacing the Spring Cloud Config Server
        1. Changes required to replace the Spring Cloud Config Server
      3. Replacing the Spring Cloud Gateway
        1. Changes required to replace the Spring Cloud Gateway
      4. Automating certificate provisioning
      5. Testing with Kubernetes ConfigMaps, Secrets, Ingress, and the cert-manager
        1. Rotating certificates
        2. Deploying to Kubernetes for staging and production
      6. Verifying that the microservices work without Kubernetes
        1. Changes in the Docker Compose files
        2. Testing with Docker Compose
      7. Summary
      8. Questions
    4. Using a Service Mesh to Improve Observability and Management
      1. Technical requirements
      2. Introducing service meshes using Istio
        1. Introducing Istio
        2. Injecting Istio proxies into microservices
        3. Introducing Istio API objects
      3. Simplifying the microservice landscape
        1. Replacing Kubernetes Ingress controller with Istio ingress gateway
        2. Replacing the Zipkin server with Istio's Jaeger component
      4. Deploying Istio in a Kubernetes cluster
        1. Setting up access to Istio services
      5. Creating the service mesh
        1. Source code changes
          1. Content in the _istio_base.yaml template
          2. Content in the _istio_dr_mutual_tls.yaml template
        2. Running commands to create the service mesh
      6. Observing the service mesh
      7. Securing a service mesh
        1. Protecting external endpoints with HTTPS and certificates
        2. Authenticating external requests using OAuth 2.0/OIDC access tokens
        3. Protecting internal communication using mutual authentication (mTLS)
      8. Ensuring that a service mesh is resilient
        1. Testing resilience by injecting faults
        2. Testing resilience by injecting delays
      9. Performing zero-downtime updates
        1. Source code changes
          1. Virtual services and destination rules
          2. Deployments and services
          3. Tying things together in the prod-env Helm chart
        2. Deploying v1 and v2 versions of the microservices with routing to the v1 version
        3. Verifying that all traffic initially goes to the v1 version of the microservices
        4. Running canary tests
        5. Running blue/green deployment
          1. A short introduction to the kubectl patch command
          2. Performing the blue/green deployment
      10. Running tests with Docker Compose
      11. Summary
      12. Questions
    5. Centralized Logging with the EFK Stack
      1. Technical requirements
      2. Introducing Fluentd
        1. Overview of Fluentd
        2. Configuring Fluentd
      3. Deploying the EFK stack on Kubernetes
        1. Building and deploying our microservices
        2. Deploying Elasticsearch and Kibana
          1. A walkthrough of the manifest files
          2. Running the deploy commands
        3. Deploying Fluentd
          1. A walkthrough of the manifest files
          2. Running the deploy commands
      4. Trying out the EFK stack
        1. Initializing Kibana
        2. Analyzing the log records
        3. Discovering the log records from microservices
        4. Performing root cause analyses
      5. Summary
      6. Questions
    6. Monitoring Microservices
      1. Technical requirements
      2. Introduction to performance monitoring using Prometheus and Grafana
      3. Changes in source code for collecting application metrics
      4. Building and deploying the microservices
      5. Monitoring microservices using Grafana dashboards
        1. Installing a local mail server for tests
        2. Starting up the load test
        3. Using Kiali's built-in dashboards
        4. Importing existing Grafana dashboards
        5. Developing your own Grafana dashboards
          1. Examining Prometheus metrics
          2. Creating the dashboard
          3. Trying out the new dashboard
        6. Exporting and importing Grafana dashboards
      6. Setting up alarms in Grafana
        1. Setting up a mail-based notification channel
        2. Setting up an alarm on the circuit breaker
        3. Trying out the circuit breaker alarm
      7. Summary
      8. Questions
    7. Installation Instructions for macOS
      1. Technical requirements
      2. Installing tools
        1. Installing Homebrew
        2. Using Homebrew to install tools
        3. Install tools without Homebrew
        4. Post-installation actions
        5. Verifying the installations
      3. Accessing the source code
        1. Using an IDE
        2. The structure of the code
    8. Installation Instructions for Microsoft Windows with WSL 2 and Ubuntu
      1. Technical requirements
      2. Installing tools
        1. Installing tools on Windows
          1. Installing WSL 2 – Windows Subsystem for Linux v2
          2. Installing Ubuntu 20.04 on WSL 2
          3. Installing Windows Terminal
          4. Installing Docker Desktop for Windows
          5. Installing Visual Studio Code and its extension for Remote WSL
        2. Installing tools on the Linux server in WSL 2
          1. Installing tools using apt install
          2. Installing the Spring Boot CLI using sdk install
          3. Installing the remaining tools using curl and install
          4. Verifying the installations
      3. Accessing the source code
        1. The structure of the code
    9. Native Compiled Java Microservices
      1. Technical requirements
      2. When to native compile Java source code
      3. Introducing the GraalVM project
      4. Introducing the Spring Native project
      5. Compiling source code to a native image
        1. Changes in the source code
          1. Updates to the Gradle build files
          2. Providing native hints as annotations
          3. When underlying frameworks and libraries don't support native compilation
        2. Installing the tracing agent
          1. Installing the tracing agent on macOS
          2. Installing the tracing agent on Ubuntu under WSL 2 in Microsoft Windows
        3. Running the tracing agent
        4. Creating the native images
      6. Testing with Docker Compose
      7. Testing with Kubernetes
      8. Summary
      9. Questions
  5. Other Books You May Enjoy
  6. Index

Product information

  • Title: Microservices with Spring Boot and Spring Cloud - Second Edition
  • Author(s): Magnus Larsson
  • Release date: July 2021
  • Publisher(s): Packt Publishing
  • ISBN: 9781801072977