Hands-On Microservices with Spring Boot and Spring Cloud

Book description

Apply microservices patterns to build resilient and scalable distributed systems

Key Features

  • Understand the challenges of building large-scale microservice landscapes
  • Build cloud-native production-ready microservices with this comprehensive guide
  • Discover how to get the best out of Spring Cloud, Kubernetes, and Istio when used together

Book Description

Microservices architecture allows developers to build and maintain applications with ease, and enterprises are rapidly adopting it to build software using Spring Boot as their default framework. With this book, you’ll learn how to efficiently build and deploy microservices using Spring Boot.

This microservices book will take you through tried and tested approaches to building distributed systems and implementing microservices architecture in your organization. Starting with a set of simple cooperating microservices developed using Spring Boot, you’ll learn how you can add functionalities such as persistence, make your microservices reactive, and describe their APIs using Swagger/OpenAPI. As you advance, you’ll understand how to add different services from Spring Cloud to your microservice system. The book also demonstrates how to deploy your microservices using Kubernetes and manage them with Istio for improved security and traffic management. Finally, you’ll explore centralized log management using the EFK stack and monitor microservices using Prometheus and Grafana.

By the end of this book, you’ll be able to build microservices that are scalable and robust 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.0/OIDC and Spring Security to protect public APIs
  • Implement Docker to bridge the gap between development, testing, and production
  • Deploy and manage microservices using Kubernetes
  • Apply Istio for improved security, observability, and traffic management

Who this book is for

This book is for Java and Spring developers and architects who want to learn how to break up their existing monoliths into microservices and deploy them either on-premises or in the cloud using Kubernetes as a container orchestrator and Istio as a service Mesh. No familiarity with microservices architecture is required to get started with this book.

Table of contents

  1. Title Page
  2. Copyright and Credits
    1. Hands-On Microservices with Spring Boot and Spring Cloud
  3. About Packt
    1. Why subscribe?
  4. Contributors
    1. About the author
    2. About the reviewer
    3. Packt is searching for authors like you
  5. Preface
    1. Who this book is for
    2. What this book covers
    3. To get the most out of this book
      1. Download the example code files
      2. Download the color images
      3. Code in Action
      4. Conventions used
    4. Get in touch
      1. Reviews
  6. Section 1: Getting Started with Microservice Development Using Spring Boot
  7. 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 microservice
        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
      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
  8. Introduction to Spring Boot
    1. Technical requirements
    2. Learning about 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. Beginning with Spring WebFlux
      1. Code examples of setting up a REST service using Spring WebFlux
        1. Starter dependencies
        2. Property files
        3. Sample RestController
    4. Exploring SpringFox
    5. Understanding Spring Data
      1. Entity
      2. Repositories
    6. Understanding Spring Cloud Stream
      1. Code examples for sending and receiving messages with Spring Cloud Stream
    7. Learning about Docker
    8. Summary
    9. Questions
  9. Creating a Set of Cooperating Microservices
    1. Technical requirements
      1. Tool installation
        1. Installing Homebrew
          1. Using Homebrew to install Java, curl, jq, and the Spring Boot CLI
        2. Using an IDE
      2. Accessing the source code
    2. Introducing the microservice landscape
      1. Information handled by microservices
        1. Product service
        2. Review service
        3. Recommendation service
        4. Product composite service
        5. Infrastructure-related information
      2. Temporarily replacing a discovery service
    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
      1. Preventing slow lookup of the localhost hostname
    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
  10. 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. Java without Docker
      2. Java in Docker
        1. CPU
        2. Memory
      3. Problems with Docker and Java SE 9 (or older)
    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. Testing them all together automatically
      1. Troubleshooting a test run
    7. Summary
    8. Questions
  11. Adding an API Description Using OpenAPI/Swagger
    1. Technical requirements
    2. Introduction to using SpringFox
    3. Changes in the source code
      1. Adding dependencies to the Gradle build files
      2. Adding configuration and general API documentation to Product Composite Service Application
      3. Adding API-specific documentation to ProductCompositeService
      4. Adding textual descriptions of the API to the property file 
    4. Building and starting the microservice landscape
    5. Trying out the Swagger documentation
    6. Summary
    7. Questions
  12. Adding Persistence
    1. Technical requirements
    2. But first, let's see where we are heading
    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
    5. Using the persistence layer in the service layer
      1. Log the database connection URL
      2. Adding new APIs
      3. The use of the persistence 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 connect 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
  13. 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 using Spring
      1. An introduction to Spring 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 integration layer
        3. Changes in the service implementation
        4. Changes in the test code
    4. Developing event-driven asynchronous services
      1. Configuring Spring Cloud Stream to handle 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. Publishing events in the composite service
        1. Declaring message sources and publishing events in the integration layer
        2. Adding configuration for publishing events
        3. Changes in the test code
      5. 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. 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 two partitions per topic
      5. Using Kafka with two partitions per topic
    6. Running automated tests of the reactive microservice landscape
    7. Summary
    8. Questions
  14. Section 2: Leveraging Spring Cloud to Manage Microservices
  15. Introduction to Spring Cloud
    1. Technical requirements
    2. The evolution of Spring Cloud
    3. Using Netflix Eureka as a discovery service
    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
  16. Adding Service Discovery Using Netflix Eureka and Ribbon
    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 configuration for use in the development process
      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
        4. Starting up the Eureka server again
    7. Summary
    8. Questions
  17. 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 a Spring Cloud Gateway
      1. Adding a composite health check
      2. Configuring a Spring Cloud Gateway
        1. Routing rules
          1. Routing requests to the product-composite API
          2. Routing requests to the Eureka server's API and web page
          3. Routing requests with predicates and filters
    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 Eureka through the edge server
        3. Routing based on the host header
    5. Summary
    6. Questions
  18. Securing Access to APIs
    1. Technical requirements
    2. Introduction to OAuth 2.0 and OpenID Connect
      1. Introduction to OAuth 2.0
      2. Introducing OpenID Connect
    3. Securing the system landscape
    4. Adding an authorization server to our system landscape
    5. Protecting external communication with HTTPS
      1. Replacing a self-signed certificate in runtime
    6. Securing access to the discovery service, Netflix Eureka
      1. Changes in the Eureka server
      2. Changes in Eureka clients
      3. Testing the protected Eureka server
    7. Authenticating and authorizing API access 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
      3. Changes in the test script
    8. Testing with the local authorization server
      1. Building and running the automated tests
      2. Acquiring access tokens
        1. Acquiring access tokens using the password grant flow
        2. Acquiring access tokens using the implicit grant flow
        3. Acquiring access tokens using the code grant flow
      3. Calling protected APIs using access tokens
    9. Testing with an OpenID Connect provider – Auth0
      1. Setting up an account and OAuth 2.0 client in Auth0
      2. Applying the necessary 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 password grant flow
      5. Acquiring access tokens using the implicit grant flow
      6. Acquiring access tokens using the authorization code grant flow
      7. Calling protected APIs using the Auth0 access tokens
      8. Getting extra information about the user
    10. Summary
    11. Questions
  19. 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
      2. Moving the partitioning configuration from Docker Compose files to the configuration repository
    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
  20. Improving Resilience Using Resilience4j
    1. Technical requirements
    2. Introducing the Resilience4j circuit breaker and retry mechanism
      1. Introducing the circuit breaker
      2. Introducing the retry mechanism
    3. Adding a circuit breaker and retry mechanism 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
        1. Adding dependencies to the build file
        2. Adding the circuit breaker and timeout logic
        3. Adding fast fail fallback logic
        4. Adding configuration
      3. Adding a retry mechanism
        1. Adding the retry annotation
        2. Handling retry-specific exceptions
        3. 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
  21. 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
  22. Section 3: Developing Lightweight Microservices Using Kubernetes
  23. 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 Kubernetes CLI, kubectl
      3. Working with kubectl contexts
      4. Creating a Kubernetes cluster
    6. Trying out a sample deployment
    7. Managing a Kubernetes cluster
      1. Hibernating and resuming a Kubernetes cluster
      2. Terminating a Kubernetes cluster
    8. Summary
    9. Questions
  24. Deploying Our Microservices to Kubernetes
    1. Technical requirements
    2. Replacing Netflix Eureka with Kubernetes services
    3. Introducing Kustomize
      1. Setting up common definitions in the base folder
    4. Deploying to Kubernetes for development and test
      1. Building Docker images
      2. Deploying to Kubernetes
      3. Changes in the test script for use with Kubernetes
        1. Reaching the internal actuator endpoint using Docker Compose
        2. Reaching the internal actuator endpoint using Kubernetes
        3. Choosing between Docker Compose and Kubernetes
      4. Testing the deployment
    5. Deploying to Kubernetes for staging and production
      1. Changes in the source code
      2. Deploying to Kubernetes
    6. Performing a rolling upgrade
      1. Preparing the rolling upgrade
      2. Upgrading the product service from v1 to v2
    7. Rolling back a failed deployment
      1. Cleaning up
    8. Summary
    9. Questions
  25. Implementing Kubernetes Features as an Alternative
    1. Technical requirements
    2. Replacing the Spring Cloud Config Server
      1. Changes in the source code to replace the Spring Cloud Config Server
    3. Replacing the Spring Cloud Gateway
      1. Changes in the source code for Spring Cloud Gateway
    4. Testing with Kubernetes ConfigMaps, secrets, and ingress resource
      1. Walking through the deploy script
      2. Running commands for deploying and testing
    5. Automating the provision of certificates 
      1. Deploying the Cert Manager and defining Let's Encrypt issuers
      2. Creating an HTTP tunnel using ngrok
      3. Provisioning certificates with the Cert Manager and Let's Encrypt
        1. Using Let's Encrypt's staging environment
        2. Using Let's Encrypt's production environment
      4. Cleaning up
    6. Verifying that microservices work without Kubernetes
      1. Changes in the source code for Docker Compose
      2. Testing with Docker Compose
    7. Summary
    8. Questions
  26. Using a Service Mesh to Improve Observability and Management
    1. Technical requirements
    2. Introduction to service mesh using Istio
      1. Injecting Istio proxies into existing microservices
      2. Introducing Istio API objects
      3. Introducing runtime components in Istio 
      4. Changes in the microservice landscape 
        1. Kubernetes Ingress resources are replaced with Istio Ingress Gateway as an edge server
        2. Simplifying the system landscape and replacing Zipkin with Jaeger
    3. Deploying Istio in a Kubernetes cluster
      1. Setting up access to Istio services
        1. An added bonus from using the minikube tunnel command
    4. Creating the service mesh
      1. Source code changes
        1. Updating the deployment scripts to inject Istio proxies
        2. Changing the file structure of the Kubernetes definition files
        3. Adding Kubernetes definition files for Istio
      2. Running commands to create the service mesh
    5. Observing the service mesh
    6. 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)
    7. Ensuring that a service mesh is resilient
      1. Testing resilience by injecting faults
      2. Testing resilience by injecting delays
    8. Performing zero-downtime deployments
      1. Source code changes
        1. Service and deployment objects for concurrent versions of microservices
        2. Added Kubernetes definition files for Istio
      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 tests
        1. A short introduction to the kubectl patch command
        2. Performing the blue/green deployment
    9. Running tests with Docker Compose
    10. Summary
    11. Questions
  27. Centralized Logging with the EFK Stack
    1. Technical requirements
    2. Configuring Fluentd
      1. Introducing 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 definition files
        2. Running the deploy commands
      3. Deploying Fluentd
        1. A walkthrough of the definition 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
  28. 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 Grafana dashboards
      4. Importing existing Grafana dashboards
      5. Developing your own Grafana dashboards
        1. Examining Prometheus metrics
        2. Creating the dashboard
          1. Creating an empty dashboard
          2. Creating a new panel for the circuit breaker metric
          3. Creating a new panel for the retry metric
          4. Arranging the panels
        3. Trying out the new dashboard
          1. Testing the circuit breaker metrics
          2. Testing the retry metrics
    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
  29. Other Books You May Enjoy
    1. Leave a review - let other readers know what you think

Product information

  • Title: Hands-On Microservices with Spring Boot and Spring Cloud
  • Author(s): Magnus Larsson
  • Release date: September 2019
  • Publisher(s): Packt Publishing
  • ISBN: 9781789613476