39,59 €
The open source Micronaut® framework is a JVM-based toolkit designed to create microservices quickly and easily. This book will help full-stack and Java developers build modular, high-performing, and reactive microservice-based apps using the Micronaut framework.
You'll start by building microservices and learning about the core components, such as ahead-of-time compilation, reflection-less dependency injection, and reactive baked-in HTTP clients and servers. Next, you will work on a real-time microservice application and learn how to integrate Micronaut projects with different kinds of relational and non-relational databases. You'll also learn how to employ different security mechanisms to safeguard your microservices and integrate microservices using event-driven architecture in the Apache Kafka ecosystem. As you advance, you'll get to grips with automated testing and popular testing tools. The book will help you understand how you can easily handle microservice concerns in Micronaut projects, such as service discovery, API documentation, distributed configuration management, fallbacks, and circuit breakers. Finally, you'll explore the deployment and maintenance aspects of microservices and get up to speed with the Internet of Things (IoT) using the Framework.
By the end of this book, you'll be able to build, test, deploy, and maintain your own microservice apps using the framework.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 275
Veröffentlichungsjahr: 2021
A quick-start guide to building high-performance reactive microservices for Java developers
Nirmal Singh
Zack Dawood
BIRMINGHAM—MUMBAI
Copyright © 2021 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the authors, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Group Product Manager: Aaron Lazar
Publishing Product Manager: Denim Pinto
Senior Editor: Storm Mann
Content Development Editor: Tiksha Lad
Technical Editor: Pradeep Sahu
Copy Editor: Safis Editing
Project Coordinator: Deeksha Thakkar
Proofreader: Safis Editing
Indexer: Tejal Daruwale Soni
Production Designer: Vijay Kamble
First published: September 2021
Production reference: 1240821
Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham
B3 2PB, UK.
ISBN 978-1-80056-423-7
www.packt.com
To my dearest loving wife, Rajveer, for walking the journey of writing this book with me. You are the wind beneath my wings.Nirmal Singh
To my wife, Waheetha, and son, Aaryan, for persuading me to complete the book. Behind every author there is a supporting and loving family.Zack Dawood
In March of 2018, Micronaut® co-founder, Graeme Rocher, delivered a keynote address at Madrid's Greach conference in which he introduced a brand-new, open-source, full-stack, JVM software development framework. Although Graeme and the rest of the core development team at the Framework's home, Object Computing, knew they had built a groundbreaking toolset that was poised to revolutionize the way microservices and serverless applications performed, they could not have predicted the incredible amount of enthusiasm and support the Framework and the team would quickly receive following the product's launch.
By shifting framework infrastructure into a compiler feature, the Micronaut framework has significantly transformed the way developers view startup time and memory consumption when building microservices and serverless applications. It has upended the way developers approach framework design in server-side Java and rewritten the book on how frameworks should be built in the post-Java EE world.
The Framework is being used at SmartThings, StainlessAI, Minecraft, and many other organizations around the globe. It has been featured at tech conferences around the world, reached a Trial status in the 'Languages and Frameworks' section of ThoughtWorks' Technology Radar, received its own hipster in honor of JHipster's Micronaut Blueprint, and had more than 60,000 apps created on Micronaut Launch, an online tool for quickly and easily creating Micronaut applications.
It is not at all an exaggeration to say that the Micronaut framework is a hit!
In 2020, we launched the Micronaut Foundation, a not-for-profit company that oversees the software's roadmap and development, best practices and processes, repository control, documentation and support, and fundraising. Our goals? To ensure technical innovation and advancement of the Framework, to evangelize and promote the Framework as a leading technology in the JVM space, and to build and support an ecosystem of complementary documentation, functionality, and services.
The Foundation is led by a Technology Advisory Board made up of thought leaders and representatives from different sectors of the technology industry. Bringing together a group of folks with diverse experiences, priorities, and areas of expertise is a huge win for the technology and the community.
Object Computing and the Micronaut Foundation highly value the equal opportunity represented by open-source technologies; working together with members of the Micronaut community to share information, knowledge, and expertise can only further promote success for everyone. Thus, when Zack Dawood and Nirmal Singh approached us and told us they were writing a book about the Framework, we were delighted and happy to help in any way. Building Microservices with Micronaut is a great example of community members channeling their enthusiasm for the Micronaut framework into a resource that we know will lead to innovative and exciting solutions with the power to change the world.
Whether you've been a fan of the Micronaut framework since its inception or you're just getting started by picking up this book, you're part of a community full of people and organizations that are passionate about creating the very best technical solutions possible – developers and tech enthusiasts who embrace the idea that all of us is better than any one of us.
We are certain that you will find the Micronaut framework to be a game-changer, and with Zack and Nirmal's guidance, you will soon find yourself enjoying all the benefits the Framework offers. And where your journey takes you from there? Well, whatever you do, you can take pride in the fact that you're a pioneer in a future that runs on intelligent compilers, lightning-fast runtimes, and technical solutions limited only by your imagination.
Foreword by The Micronaut Foundation
Nirmal Singh is an entrepreneurial-spirited renaissance mind technology leader, with 10+ years of broad and unique cross-domain experience in handling complex inter-disciplinary requirements, leading high-performing software development teams, and delivering robust software solutions. He has worked in various techno-functional roles, serving health-tech, fin-tech, retail, and social commerce verticals in both product and consulting engagements. He currently leads a product engineering group at CGI to re-engineer a classic mission-critical wealth application.
I would like to extend my gratitude to my loving wife for her patience and encouragement throughout the journey of writing this book. Without her, this would not have been possible.
Zack Dawood is a Canada-based technologist, leader, author, and speaker. Zack has 16+ years of experience in IT software product development, big data, machine learning, mobile app development, blockchain, payments, Agile, enterprise architecture, and DevOps. Zack is highly certified; his key certifications include Certified Agile Leader, Certified Scrum Professional, SAFe, ITIL, Microsoft Certified Professional, and TOGAF. He has also been a Distinguished Toastmaster (DTM) since 2018. Zack also serves on the board of directors and has assumed the role of president since November 2018 for a non-profit organization. Zack writes technical blogs and contributes to Stack Overflow.
I would like to first and foremost thank my loving and patient wife, Waheetha, and son, Aaryan, for their continued support, patience, and encouragement throughout the long process of writing this book. Thanks also to the Packt team for their support and encouragement in completing this book.
Patrick Pu is a senior full-stack developer at CGI, where he focuses on building microservice architecture-based fund accounting platforms.
Patrick has worked as a senior consultant and helped many clients to build digital solutions for personal and business banking, B2B relationship management, child behavioral research, sports streaming, and digital currency exchange.
Patrick is a cat lover and blockchain enthusiast.
Micronaut is a JVM-based framework for building lightweight, modular applications. It is a fast-growing framework designed to make creating microservices quick and easy. This book will help full stack/Java developers to build modular, high-performing, and reactive microservices-based applications using Micronaut.
This book is for developers who have been building microservices on traditional frameworks such as Spring Boot and are looking for a faster alternative. Intermediate knowledge of Java programming is required, along with a intermediate knowledge of implementing web services development in Java.
Chapter 1, Getting Started with Microservices Using the Micronaut Framework, kicks off with some conceptual fundamentals on microservices and microservices design patterns. You are then introduced to the Micronaut framework and why this is the ideal framework for developing microservices. Later, you will get hands-on with the Micronaut framework by working on hello-world projects using Maven and Gradle.
Chapter 2, Working on Data Access, covers aspects of working with various kinds of database and persistence frameworks. You will begin with an object-relational mapping framework while doing a hands-on Hibernate framework and then dive into using a persistence framework (MyBatis). Finally, you will also integrate with a non-relational database (MongoDB).
Chapter 3, Working on RESTful Web Services, starts with a discussion on data transfer objects and mappers. You then dive into working with RESTful interfaces in the Micronaut framework. Later, you will learn about Micronaut's HTTP server and client APIs.
Chapter 4, Securing Web Services, covers various approaches in securing web endpoints in the Micronaut framework, such as session authentication, JWT, and OAuth.
Chapter 5, Integrating Microservices Using Event-Driven Architecture, starts with event-driven architecture and two different models for event publishing: a pull model and a push model. You then dive into event streaming and using Apache Kafka for integrating two microservices in the pet-clinic application (sample project).
Chapter 6, Testing the Microservices, sheds some light on various kinds of automated testing – unit testing, service testing, and integration testing, and how to employ these testing techniques in adopting a prudent automated testing policy to reduce cost and increase the robustness of microservices.
Chapter 7, Handling the Microservices Concerns, covers some core concerns while working on the microservices, such as distributed configuration management, documenting service APIs, service discovery, and the API gateway. Later, you also explore the mechanisms for fault tolerance in the Micronaut framework.
Chapter 8, Deploying the Microservices, covers the build and deployment aspects of microservices. You will kick things off by building the container artifacts using an automated tool and then leverage Docker Compose to deploy the microservices.
Chapter 9, Distributed Logging, Tracing, and Monitoring, throws light on implementing the observability patterns in microservices with distributed logging, distributed tracing, and distributed monitoring.
Chapter 10, IoT with Micronaut, jumpstarts with an introduction to IoT with Alexa, covering Alexa fundamentals and a hello-world example. Later, you will be able to integrate Micronaut with Alexa while working on the pet-clinic application.
Chapter 11, Building Enterprise-Grade Microservices, covers the best practices for working on the microservices and how to build and scale enterprise-grade microservices.
If you are using the digital version of this book, we advise you to type the code yourself or access the code via the GitHub repository (link available in the next section). Doing so will help you avoid any potential errors related to the copying and pasting of code.
You can download the example code files for this book from GitHub at https://github.com/PacktPublishing/Building-Microservices-with-Micronaut. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://static.packt-cdn.com/downloads/9781800564237_ColorImages.pdf
There are a number of text conventions used throughout this book.
Code in text: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "By following these instructions, we added a foo-stream topic and added a message to this topic."
A block of code is set as follows:
@KafkaClient
public interface VetReviewClient {
@Topic("vet-reviews")
void send(@Body VetReviewDTO vetReview);
}
Bold: Indicates a new term, an important word, or words that you see on screen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "As viewed on the Kafdrop, we can verify that our event from the pet-clinic-reviews microservice is streamed out and added to the vet-reviews topic."
Tips or important notes
Appear like this.
Feedback from our readers is always welcome.
General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/support/errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in, and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Once you've read Building Microservices with Micronaut, we'd love to hear your thoughts! Please click here to go straight to the Amazon review page for this book and share your feedback.
Your review is important to us and the tech community and will help us make sure we're delivering excellent quality content.
This section kickstarts the microservices journey in the Micronaut framework while covering some fundamentals of microservices, microservices design patterns, and why Micronaut is the ideal framework for microservices development.
This section has the following chapter:
Chapter 1, Getting Started with Microservices Using the Micronaut FrameworkIn recent times, there's been a good buzz about microservices and how the microservices architecture has been transformational in developing rapid, agile, and enterprise-grade web services to address the unique challenges and requirements of today's world. The microservices architecture has turned the page toward disciplining the standards on developing these web services. In this chapter, we will walk through the evolution of web services to microservices. We will quickly dive into some useful microservices design patterns. We will zero in on the key pitfalls in most of the traditional Java development frameworks and how their surface-level adoption to the microservices architecture has elevated performance and optimization issues. We will then explore how the Micronaut framework has addressed these performance and optimization issues in the microservices with an overhauled and ground-up approach to microservices development. Lastly, to get started with the Micronaut framework, we will set up the Micronaut CLI and work on a small hello world project.
In this chapter, we will focus on these topics in particular:
Introducing microservices and their evolutionUnderstanding microservices design patternsWhy Micronaut is the best choice for developing microservicesGetting started with the Micronaut frameworkWorking on the hello world project in the Micronaut frameworkBy the end of this chapter, you will have an understanding of how web services evolved in to microservices and why traditional Java frameworks are ineffective for developing microservices as compared to the Micronaut framework. Furthermore, we will also gain the practical knowledge to start using the Micronaut framework by working on a small project in the Micronaut framework.
All the commands and technical instructions in this chapter are run on Windows 10 and mac OS X. Code examples covered in this chapter are available in the book's GitHub repository at https://github.com/PacktPublishing/Building-Microservices-with-Micronaut/tree/master/Chapter01.
The following tools need to be installed and set up in the development environment:
Java SDK: Version 13 or above (we used Java 14).Maven: This is optional and only required if you would like to use Maven as the build system. However, we recommend having Maven set up on any development machine. Instructions to download and install Maven can be found at https://maven.apache.org/download.cgi.Development IDE: Based on your preferences, any Java-based IDE can be used, but for the purpose of writing this chapter, IntelliJ was used. Git: Instructions to download and install Git can be found at https://git-scm.com/downloads.Before we thoroughly jump into introducing and defining microservices, it will be helpful to know how microservices have evolved. In the late 1960s, Alan Kay coined the term object-oriented programming. Though it was a definitive idea, later it birthed the four pillars for building software solutions using object-oriented programming:
EncapsulationInheritancePolymorphismAbstractionIn a short mnemonic, it's known as EIPA. Since the inception of these four pillars, the software industry has seen the rise and fall of many programming languages, frameworks, design patterns, and so on. With each such adaption and idea, thinkers and tinkerers have tried to come closer to EIPA by keeping a modular design and loosely coupled yet tightly encapsulated application components. Over the last few decades, software teams have moved away from the art of object-oriented programming toward the science of object-oriented programming by systematically adopting these key pillars. This iterative journey is the evolution of microservices.
In the late 1980s and early 1990s, almost every enterprise application was exposed as either a command line or native desktop software. Applications were tightly connected to databases and it was almost as if the end user was directly interacting with the database with the application as a thin façade in between. It was the era of monolithic applications or client/server architecture.
In the proceeding diagram, we can see how users interacted with a monolith application:
Figure 1.1 – Monolithic client/server architecture
As depicted in Figure 1.1, in monolithic client/server architecture, the application is tightly coupled to the database and the user interacts through a terminal façade or desktop application. In this architecture, it was painful to maintain good service-level agreements (SLAs). Almost all the key non-functional factors such as scalability, high availability, fault tolerance, and flexibility underperformed or failed.
To address some of these aspects service-oriented architecture (SOA) came into existence. In the 2000s, SOA was formalized in the industry with the definition of some standard protocols such as Simple Object Access Protocol (SOAP). Web Services Description Language (WSDL) was also created during this period. Web 2.0 applications were popular with Asynchronous JavaScript And XML (AJAX). Enterprise service bus and messaging systems were highly used in enterprise applications. Advancements in SOA catalyzed a new paradigm of delivering software solutions to end users: Software as a Service (SaaS). Instead of desktop applications and terminal clients, software solutions were delivered to end users over HTTP as hosted online services. In the proceeding diagram, we can see how users interacted with an SOA-based application:
Figure 1.2 – SOA
As shown, SOA brought in some decoupling by separating the concerns between the web application, web server, and app server. App servers or enterprise service buses (ESBs) usually interact with the database and the user interacts with the application by accessing it on web browsers (SaaS solutions). Though SOA brought some relief, the adoption of SaaS left scalability and flexibility as key unhashed puzzles.
Post-2010, the technology world started to move much faster than it did in the previous two decades. With the introduction of containers, the cloud, big data, and machine learning, everything started moving rapidly in architecture design. It is the era of Uber, Airbnb, Netflix, and freemium/premium applications. Applications are designed for distributed computing and scalability. With the microservices architecture, the application is decomposed to loosely coupled microservices where each microservice owns its database. In the proceeding diagram, we can see how users interact with a microservices-based application:
Figure 1.3 – Microservices architecture
In the previous diagram, we can see a fully realized microservices application where each microservice interacts with and owns its database. The user interacts with a single-page application through a modern browser. Any incoming requests from the web server are routed to the respective microservice. The full realization of microservices architecture is to address key factors of scalability, fault tolerance, high availability, and flexibility.
To put it simply, microservices or microservices architecture componentize an application into a collection of interacting services. Each service could be developed, tested, deployed, and maintained independently. Thus, each smaller (micro) service has its own unique life cycle. Furthermore, since each service is loosely coupled (interacting with other services using HTTP/HTTPS), we can do the following:
Scale up or scale down (based on the service traffic).Address any runtime faults (boot up the service backup).Make new changes (change impact is limited to the service).Therefore, through the complete realization of decoupled architecture in the microservices, we address key issues of scalability, fault tolerance, high availability, and flexibility.
So far, we have learned about microservices and their evolution and how they have been transformational in addressing the unique, rapid, and agile needs of today's world. This understanding is a good preface to realizing the potential of microservices. In the next section, we will dive into the microservices design patterns.
To fully realize the benefits of any architecture (including the microservices architecture), an architectural approach is often backed with design patterns. Understanding these design patterns is crucial for an ideal adoption of the architecture. In the following sections, we will cover some practical and commonly used design patterns in microservices. Each pattern addresses a different aspect of the application development life cycle and our focus would be to see these design patterns from a practical usage standpoint. We will begin with decomposition design patterns.
Decomposition design patterns dictate how we can componentize or decompose a big/monolithic application into smaller (micro) services. These patterns come in handy in designing a transformational architecture for any legacy monolithic application. The following are the most commonly used design patterns in decompositions.
Any business capability is an instrument to make a profit. If we can enlist and categorize an application into a set of business capabilities such as inventory management, customer orders, or operations, then the application can be decomposed into microservices that are based on these business capabilities. This process to decompose is effective and recommended for small- to medium-sized applications.
If the application is an enterprise-grade and heavy application, then the previous approach may end up decomposing the application into smaller monoliths. These monoliths are smaller but monoliths nonetheless. In such cases, business modeling can help to categorize and map application functionalities into domains and sub-domains. Functionalities inside a domain/sub-domain are similar but very different from the functionalities of other domains/sub-domains. Microservices then can be designed and built around domains or sub-domains (if there are many functionalities mapped to a domain).
Once the application is broken down into smaller (micro) services, we will need to establish cohesion among these services. Integration design patterns address such collaboration requirements. The following are the most commonly used design patterns in integrations.
Often upstream frontend consumers need to access microservices through a façade. This façade is called an API gateway. The API gateway design pattern serves an important purpose to keep things simple for frontend clients:
The frontend client is not sending too many requests to microservices.The frontend client is not processing/aggregating too many responses (from microservices).At the server end, the gateway routes a request to multiple microservices, and these microservices can run in parallel.Before sending the final response, we can aggregate individual responses from different microservices.This pattern is very similar to the aforementioned API gateway pattern. However, composite microservice is the key differential. The mandate of a composite microservice is to offload an incoming request to multiple microservices and then collaborate to create a unified response. This pattern is used when a user request is atomic from business logic standpoints, but it is processed by multiple microservices.
In some scenarios, an incoming request is executed in a series of steps wherein each step could be spinning off a call to a microservice. For example, ordering an item in an online marketplace would require the following:
Searching for an item (inventory management service)Adding an item to the cart (cart service)Checking out the added item (payment service, mail service, inventory management service)All these service calls would be synchronous. Fulfilling a user request would be an amalgamation of all these chained microservice calls.
Integrating with the persistence layer is an important aspect of any microservice-based application. Greenfield (net new) and brownfield (legacy transformation) applications may dictate their requirements in how to choose a data management pattern. The following are the most often used design patterns in data management in microservices.
In greenfield (net new) applications, it is ideal to have a database per service. Each service is the owner of an isolated database (relational or non-relational) and any data operation must be executed through the microservice only. Furthermore, even if any other microservice needs to perform a database operation, then it should be routed through the owner microservice.
In brownfield (transformational) applications, it may not be practical to decompose the database into one database per service. In such scenarios, the microservices architecture realization can be kickstarted with services sharing a common monolith database.
In greenfield or fully transformed applications where each microservice is an independent database owner, there might be a requirement to query data from multiple databases. The CQRS pattern stipulates to decompose an application into a command and query:
Command: This part will manage any create, update, and delete requests.Query: This part will manage query requests using database views where database views can unify data from multiple schemas or data sources.Some concerns cut across all the different aspects/layers of microservices. In the following sub-sections, we will discuss some of these concerns and patterns.
In a microservices-based application, each microservice may have more than one instance at runtime. Furthermore, these service instances can be added or removed at runtime based on traffic. This runtime agility can be an issue for upstream consumers in how they connect with services.
The service discovery pattern addresses this by implementing a service registry database. The service registry is a metadata store containing information such as the service name, where the service is running, and the current status of the service. Any change to the service runtime information will be updated in the service registry, for example, when a service adds a new instance or a service is down. This eases the pain for upstream consumers to connect with different microservices in the application.
In a microservices-based application, often services interact with each other by invoking endpoints. There could be a scenario where a service is calling a downstream service but the downstream service is down. Without a circuit breaker, the upstream service will keep calling the downstream service while it's down and this will keep impacting the user interaction with the application.
In the circuit breaker pattern, a downstream service call will be routed through a proxy. This proxy will timeout for a fixed interval if the downstream service is down. After the timeout expiry, the proxy will try to connect again. If successful, it will connect with the downstream service; otherwise, it will renew the timeout period. Therefore, the circuit breaker will not bombard the downstream service with unnecessary calls and it will not impact user interaction with the application.
In the microservices landscape, often an incoming request will be processed by multiple services. Each service may create and log its entries. To trace any issues, it will be counter-intuitive to access these sporadic logs. By implementing a log aggregation pattern, logs could be indexed in a central place, thereby enabling easy access to all application logs. Elasticsearch, Logstash, Kibana (ELK) can be used to implement log aggregation.
