Netflix has taken three steps to build an anti-fragile organization1 . The first step is to treat every developer as an operator of the corresponding service. The second is to treat each failure as an opportunity to learn and the third is to foster a blameless culture. These three little steps have helped Netflix become the top-leading organization in the microservices world. Many look to Netflix to learn how things are being done and for best practices. Netflix in fact optimized everything for the speed of delivery. As we already discussed in the book, at its core of any microservices design, time to production, scalability, complexity localization, and resiliency are key elements. Developer experience is one of the most important factors to reach these goals. The experience of a developer in a microservices environment is quite different from engineering a monolithic application. As rightly identified by Netflix, the developer’s task does not end after pushing the code into a source repository and expecting a DevOps engineer to build and push the changes to production, or a support engineer to take on any issues that happen in the production environment. A microservices development environment demands a broader skillset from the developer.
Note
All Netflix developers are given SSH keys to access their production servers, where in most of the traditional application deployments, developers have no access from staging onward.
Over the past few years there have been many tools and frameworks developed to assist and speed up microservices development. Most of the popular tools and frameworks are open source. In this chapter, we discuss different options available for a microservices developer and see how to build a microservice from the ground up.
Developer Tooling and Frameworks
There are multiple tools and frameworks available for microservice developers under different categories. There are a few key elements we believe one should take into consideration before picking the right microservices framework. One of the very basic requirements is to have good support for RESTful services. In the Java world, most developers look for the level of support for JAX-RS2. Most of the Java-based frameworks do support JAX-RS based annotations, but to extend that functionality, they have introduced their own.
The seventh factor of the 12-factor app (which we discussed in Chapter 2, “Designing Microservices”) says that your application has to do the port binding and expose itself as a service, without relying upon a third-party application server. This is another common requirement for any microservices framework. Without relying on any heavyweight application servers, which eat resources and take seconds (or minutes) to boot up, one should be able to spin up a microservice in a self-contained manner in just a few milliseconds.
Most of the microservice deployments follow the service per host model. In other words, only one microservice is deployed in one host, wherein most cases, the host is a container. It’s a key aspect that everyone looks for in a microservice framework to be container friendly. What container friendly (or container native) means is discussed in detail in Chapter 8, “Deploying and Running Microservices”. The level of security support that the language provides is another key differentiator in picking a microservice framework. There are multiple ways to secure a microservice and provide the service-to-service communication between microservices. We discuss microservices security in Chapter 11, “Microservices Security Fundamentals”.
The first class language support for telemetry and observability is another important aspect in a microservice framework. It’s extremely useful to track the health of the production servers and to identify any issues. We discuss observability in Chapter 13, “Observability”. Another two important aspects of a microservice framework is its support for transactions and asynchronous messaging. Asynchronous messaging was discussed in Chapter 3, “Inter-Service Communication,” and in Chapter 5, “Data Management,” we discuss how transactions are handled in a microservices environment.
The following sections explain the most popular microservice frameworks and tools. Later in the chapter, we go through a set of examples developed with Spring Boot, which is the most popular microservice development framework for Java developers.
Netflix OSS
As we already discussed in this chapter, Netflix is playing a leading role in the microservices domain, and its influence on making microservices mainstream and widely adopted is significant. The beauty of Netflix is its commitment toward open source. The Netflix Open Source Software3 (OSS) initiative has around 40 open source projects under different categories (see Figure 4-1). The following sections explain some of the common tools under Netflix OSS that are related to microservices development.
Nebula
Nebula4 is a collection of Gradle plugins built for Netflix engineers to eliminate boilerplate build logic and provide sane conventions. The goal of Nebula is to simplify common build, release, testing, and packaging tasks needed for projects at Netflix. They picked Gradle over Maven as the build tool, as they believe it’s the best out there for Java applications.
Spinnaker
Spinnaker5 is a multi-cloud continuous delivery platform for releasing software changes with high velocity and confidence. It combines a powerful and flexible pipeline management system with integration with the major cloud providers, which include AWS EC2, Kubernetes, Google Compute Engine, Google Kubernetes Engine, Google App Engine, Microsoft Azure, and OpenStack.
Eureka
Eureka6 is a RESTful service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers. In a microservices deployment, Eureka can be used as a service registry to discover endpoints.
Archaius
Ribbon
Ribbon8 is an Inter-Process Communication (remote procedure calls) library with a built-in software load balancer (which is mostly used for client-side load balancing). Primarily it is used for REST calls with various serialization scheme support.
Hystrix
Hystrix9 is a latency and fault-tolerance library designed to isolate points of access to remote systems, services, and third-party libraries, stop cascading failure, and enable resilience in complex distributed systems where failure is inevitable. Hystrix implements many resiliency patterns discussed in Chapter 2. It uses the bulkhead pattern to isolate dependencies from each other and to limit concurrent access to any one of them, and the circuit breaker pattern to proactively avoid talking to faulty endpoints. Hystrix reports successes, failures, rejections, and timeouts to the circuit breaker, which maintains a rolling set of counters that calculate statistics. It uses these stats to determine when the circuit should “trip,” at which point it short-circuits any subsequent requests until a recovery period elapses, upon which it closes the circuit again after doing certain health checks10.
Zuul
Zuul11 is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more. It acts as the front door to Netflix’s server infrastructure, handling traffic from all Netflix users around the world. It also routes requests, supports developer testing and debugging, provides deep insight into Netflix’s overall service health, protects it from attacks, and channels traffic to other cloud regions when an AWS region is in trouble.
Spring Boot
Spring Boot12 is the most popular microservices development framework for Java developers. To be precise, Spring Boot offers an opinionated13 runtime for Spring, which takes out a lot of the complexities. Even though Spring Boot is opinionated, it also allows developers to override many of its defaults picks. Due to the fact that many Java developers are familiar with Spring, and the ease of development is a key success factor in the microservices world, and many adopted Spring Boot. Even for Java developers who are not using Spring, it is a household name. If you have worked on Spring, surely would have worried about how painful it was to deal with large, chunky XML configuration files. Unlike Spring, Spring Boot thoroughly believes in convention over configuration—no more XML hell!
Note
Convention over configuration (also known as coding by convention) is a software design paradigm used by software frameworks that attempts to decrease the number of decisions that a developer using the framework is required to make without necessarily losing flexibility.14
Spring Cloud15 came after Spring Boot in March 2015. It provides tools for developers to quickly build some of the common patterns in distributed systems. Spring Cloud, along with Spring Boot, provides a great development environment for microservices developers. Another feature of Spring Cloud is that it provides Netflix OSS integrations for Spring Boot apps through auto-configuration and binding to the Spring environment and other Spring programming model idioms. With a few simple annotations, you can enable and configure the common patterns inside your application and build large distributed systems with Netflix OSS components. The patterns provided include service discovery with Eureka, circuit breaker with Hystrix, intelligent routing with Zuul, and client-side load balancing with Ribbon. We’ll use Spring Boot and Spring Cloud for the code examples we discuss later in this chapter.
Note
Convention over configuration was first introduced by David Heinemeier Hansson to describe the philosophy of the Ruby on Rails web framework. Apache Maven, the popular build automation tool, follows the same philosophy.
Istio
Istio is an open platform that provides a uniform way to connect, manage, and secure microservices. It supports managing traffic flows between microservices, enforcing access policies, and aggregating telemetry data, all without requiring changes to the microservice code. With a strong backing from Google, IBM, Lyft, and many others, Istio is one of the leading service mesh products in the microservices domain. We’ll be discussing service mesh in detail in Chapter 9, “Service Mesh”. For the time being, service mesh is a component in microservice architecture, which facilitates service-to-service communication along with routing rules, adhering to the resiliency patterns we discussed in Chapter 2, such as retries, timeouts, circuit breaker, and bulkheads. It also does performance monitoring and tracing . In most cases, the service mesh acts as a sidecar (Chapter 2), which will take the responsibility of handling the crosscutting features from the core microservice implementation. More details about Istio are covered in Chapter 9.
Dropwizard
Dropwizard is a widely used framework for developing microservices in Java. It’s well known as a little bit of opinionated glue code, which bangs together a set of libraries. Dropwizard includes Jetty to serve HTTP requests. Jetty16 provides a web server and javax.servlet container, plus support for HTTP/2, WebSockets, OSGi, JMX, JNDI, JAAS,17 and many other integrations. Support for REST and JAX-RS (JSR 311 and JSR 339) in Dropwizard is brought in with Jersey. Jersey18 is the JAX-RS reference implementation. It also integrates Jackson19 for JSON parsing and building, and Logback20 for logging. Logback is a successor to the popular log4j project.
Support for metrics is a key feature in any microservice framework, and Dropwizard embeds Metrics21 Java library to gather telemetric data related to a running application. Dropwizard also embeds Liquibase22, which is an open source database-independent library for tracking, managing, and applying database schema changes. It allows easier tracking of database changes, especially in an Agile software development environment. The database integration with Dropwizard is done with Jdbi and Hibernate. Jdbi23 is built on top of JDBC to improve JDBC’s rough interface, providing a more natural Java database interface that is easy to bind to your domain data types. Unlike an ORM (Object Relational Mapping), it does not aim to provide a complete object relational mapping framework—instead of that hidden complexity, it provides building blocks to construct the mapping between relations and objects as appropriate for your application. Hibernate24 is the most popular ORM framework used by Java developers.
Dropwizard has a longer history than Spring Boot. In fact, Spring Boot was motivated by the success of Dropwizard. It was first released by Coda Hale25 in late 2011 while he was at Yammer. However, with better developer experience, strong community support, and the backing from Pivotal, Spring Boot is now a better option than Dropwizard.
Vert.x
Vert.x26 is toolkit for building reactive27 applications on the JVM (Java Virtual Machine), which supports multiple languages, including Java, JavaScript, Groovy, Ruby, Ceylon, Scala, and Kotlin. It started as an open source project under the Eclipse Foundation in 2012 by Tim Fox. Even before microservices became mainstream, Vert.x had a powerful stack to build microservices. Unlike Dropwizard, Vert.x is an unopinionated toolkit. In other words, it is not a restrictive framework or container, which preaches developers a specific way to write applications. Instead, Vert.x provides a lot of useful bricks and lets developers create their own apps the way they want to.
Like in Dropwizard, Vert.x also supports integrating Metrics, to gather telemetric data related to a running application. Further, it also supports integrating with Hawkular28, which is a set of open source projects designed to be a generic solution for common monitoring problems. For service discovery, Vert.x integrates HashiCorp Consul29. Consul makes it simple for services to register themselves and to discover other services via a DNS or HTTP interface. Vert.x supports integrating with multiple message brokers—for example with Apache Kafka and RabbitMQ—and multiple messaging protocols—for example AMQP, MQTT, JMS, and STOMP.
Overall Vert.x is has a powerful ecosystem to build microservices, but yet Spring Boot, with the strong support from the Spring community, has the edge.
Lagom
Akka Actors—providing isolation through a shared nothing architecture based on the Actor Model
Akka Cluster—providing resilience, sharding, replication, scalability, and load-balancing of the groups of individual isolated service instances making up a microservice
ConductR—providing isolation down to the metal and runtime management of the microservice instances34.
Lagom is based on three design principles: message driven and asynchronous communication, distributed persistence, and developer productivity. It makes asynchronous communication the default, and the default persistence model is using event sourcing and CQRS (discussed in Chapter 10, “APIs, Events, and Streams”)—using Akka Persistence and Cassandra, which is very scalable and easy to replicate and to make fully resilient.
Lagom is a promising, but relatively new, framework for microservices.
Getting Started with Spring Boot
For anyone who loves Maven, the best way to get started with a Spring Boot project would be with a Maven archetype. Unfortunately, it is no longer supported. One option we have is to create a template project via https://start.spring.io/ , which is known as the Spring Initializer . There you can pick which type of project you want to create, choose project dependencies, give it a name, and download a Maven project as a ZIP file. The other option is to use the Spring Tool Suite (STS)37 . It’s an IDE (integrated development environment) built on top of the Eclipse platform, with many useful plugins to create Spring projects. However, in this book, we are going to provide you with all the fully coded samples in the Git38 repository.
Note
If you find any issues in building or running the samples given in this book, please refer to the README file under the corresponding chapter in the Git repository: https://github.com/microservices-for-enterprise/samples.git . We will update the samples and the corresponding README files in the Git repository to reflect any changes or updates related to the tools, libraries, and frameworks used in this book.
Hello World!
Before we delve deep into the code, let’s look at some of the notable Maven dependencies and plugins added to ch04/sample01/pom.xml
Spring Boot Actuator
Gathering telemetric data about a running microservice is extremely important. This is discussed in detail in Chapter 13. In this section, we explore some of the monitoring capabilities provided in Spring Boot out-of-the-box via the actuator endpoint40. There are multiple services running behind the actuator endpoint, and most of them are enabled by default. As discussed in the previous section, we only need to add a dependency to spring-boot-starter-actuator to enable it. Let’s keep the Spring Boot application from the previous example up and running and execute a set of cURL commands.
Configuration Server
In Chapter 2, under the 12-factor app, we discussed that the configuration factor emphasizes the need to decouple environment-specific settings from the code to configuration. For example, the connection URL of the LDAP or the database server are environment-specific parameters and certificates. Spring Boot provides a way to share the configuration between microservices via a configuration server. Multiple instances of microservices can connect to this server and, over HTTP, load the configuration. The configuration server can either maintain the configuration in its own local filesystem or load from Git. Loading from Git would be the ideal approach. The configuration server itself is another Spring Boot application. You can find the code for the configuration server inside ch04/sample02.
Consuming Configurations
Service-to-Service Communication
You will also notice that the item codes are printed on the console where the sample04 microservice is running.
Getting Started with gRPC
Building the gRPC Service
Building the gRPC Client
Now let’s see how to build a gRPC client application. In fact, in our case, the gRPC client we are building is another microservice. Just like in the gRPC service, first we need to create an IDL (Interface Definition Language). This is the same IDL we used for the gRPC service. You can find it under sample06/src/main/proto/InventoryService.proto. Later we will use a Maven plugin to build the Java classes from this IDL file, and it will by default look for the location sample06/src/main/proto/.
You will also notice that the item codes are printed on the console where the sample05 microservice is running.
Event-Driven Microservices with Kafka
Setting Up a Kafka Message Broker
In this section we discuss how to set up a Kafka message broker. For the recommendations on a production deployment, always refer to the Kafka official documentation41.
Building Publisher (Event Source)
Building Consumer (Event Sink)
Now if you look at the console running the Inventory microservice (sample08), you find that the order ID is printed there.
Building GraphQL Services
In Chapter 3, we discussed how GraphQL is used in some synchronous messaging scenarios in which the RESTful service architecture won’t fit. Let’s try to build a GraphQL-based service using Spring Boot. You can find the complete code for this available under ch04/sample09.
Spring Boot will pick up the corresponding dependencies and set up the appropriate handlers to work automatically. This will expose the GraphQL service at the /graphql endpoint by default (configured in the /src/main/resources/application.properties file under sample09) and will accept POST requests containing GraphQL payloads. The GraphQL Tools library works by processing GraphQL schema files to build the correct structure and then wires special beans to this structure. The Spring Boot GraphQL Starter (graphql-spring-boot-starter) automatically finds these schema files. Those files need to be saved with the extension .graphqls and can be present anywhere in the classpath.
The method signature must have arguments corresponding to each parameter in the GraphQL schema. It should also return the correct return type for the type in the GraphQL schema. Any simple types—String, Int, List, etc.—can be used with the equivalent Java types, and the system just maps them automatically.
A Java bean represents every complex type in the GraphQL server. GraphQL also has a companion tool called GraphiQL44. This is a user interface (UI) that can communicate with any GraphQL server and execute queries and mutations against it. Fields inside the Java bean will directly map to the fields in the GraphQL response based on the name of the field. The instructions on how to run sample09 is available in the README file under ch04/sample09 directory, in the samples Git repository.
Summary
In this chapter, we discussed how to build microservices with Spring Boot. The chapter started with a discussion of the different tools and developer frameworks available for microservice developers. Then we delved deep into building microservices, with four different communication protocols—REST, gRPC, Kafka, and GraphQL. In the next chapter, we focus on the data management aspect of microservices.