What are microservices?
Microservices are an architectural approach to building applications. What sets a microservices architecture apart from more traditional, monolithic approaches, is how it breaks down an app into its core functions. Each function is called a service, and can be built and deployed independently, meaning individual services can function (and fail) without negatively affecting the others.
Think of your last visit to an online retailer. You might have used the site’s search bar to browse products. That search represents a service. Maybe you also saw recommendations for related products—recommendations pulled from a database of shopper preferences. That’s also a service. Did you add an item to an online cart? You guessed it, another service.
So, a microservice is a core function of an application and it runs independent of other services, but a microservices architecture is about more than just the loose coupling of an app’s core functions—it’s about restructuring development teams and interservice communication in a way that prepares for inevitable failures, future scalability, and new feature integration.
How is this achieved? By adapting the basics of a service-oriented architecture (SOA) to deploy microservices.
This sounds familiar...
If breaking down apps into their core functions and avoiding the pitfalls of monoliths sounds familiar, that’s because the microservices architectural style is similar to the service-oriented architecture (SOA), an already well-established style of software design.
In the early days of app development, even minimal changes to an existing app required a wholesale version update with its own quality assurance (QA) cycle, potentially slowing down many sub-teams. This approach is often referred to as “monolithic” because the source code for the entire app was built into a single deployment unit (like .war or .ear). If updates to part of an app caused errors, the whole thing had to be taken offline, scaled back, and fixed. While this approach is still viable for small applications, growing enterprises can’t afford downtime.
Enter the service-oriented architecture, which structures apps into discrete, reusable services that communicate through an enterprise service bus (ESB). In this architecture, individual services, each organized around a specific business process, adhere to a communication protocol (like SOAP, ActiveMQ, or Apache Thrift) to share themselves through the ESB. Taken together, this suite of services, integrated through an ESB, comprises an application.
On the one hand, this allows services to be built, tested, and tweaked simultaneously—no more monolithic development cycles. On the other hand, though, the ESB represents a single point of failure for the entire system—so in a way, the effort to eliminate the monolith only created a new one: the ESB, which could potentially bottleneck the whole organization.
Then what’s the difference between SOA and microservices?
Microservices can communicate with each other, usually statelessly, so apps built in this way can be more fault tolerant, less reliant on a single ESB. This also allows dev teams to choose their own tools, since microservices can communicate through language-agnostic application programming interfaces (APIs).
Given the history of SOA, microservices are not actually all that new of an idea. However, microservices have become more viable thanks to advancements in containerization technologies. With Linux containers, you’re now able to run multiple parts of an app independently, on the same hardware, with much greater control over their individual pieces and life cycles.
The most challenging part of any new architecture is getting started. Do you want to build new apps or transform old ones? Either way, you’ll want to think about the benefits and challenges of building microservices.
And the challenges?
If your organization is thinking about shifting to a microservices architecture, expect to change the way people work, not just the apps. Organizational and cultural changes are identified as challenges in part because each team will have its own deployment cadence and will be responsible for a unique service with its own set of customers. Those may not be typical developer concerns, but they will be essential to a successful microservices architecture.
Beyond culture and process, complexity and efficiency are two major challenges of a microservice-based architecture. John Frizelle, platform architect for Red Hat Mobile, laid out these eight challenge categories in his 2017 talk at Red Hat Summit:
- Building: You have to spend time identifying dependencies between your services. Be aware that completing one build might trigger several other builds, due to those dependencies. You also need to consider the effects that microservices have on your data.
- Testing: Integration testing, as well as end-to-end testing, can become more difficult, and more important than ever. Know that a failure in one part of the architecture could cause something a few hops away to fail, depending on how you’ve architected your services to support one another.
- Versioning: When you update to new versions, keep in mind that you might break backward compatibility. You can build in conditional logic to handle this, but that gets unwieldy and nasty, fast. Alternatively, you could stand up multiple live versions for different clients, but that can be more complex in maintenance and management.
- Deployment: Yes, this is also a challenge, at least in initial set up. To make deployment easier, you must first invest in quite a lot of automation as the complexity of microservices becomes overwhelming for human deployment. Think about how you’re going to roll services out and in what order.
- Logging: With distributed systems, you need centralized logs to bring everything together. Otherwise, the scale is impossible to manage.
- Monitoring: It’s critical to have a centralized view of the system to pinpoint sources of problems.
- Debugging: Remote debugging isn’t an option and it won’t work across dozens or hundreds of services. Unfortunately there’s no single answer to how to debug at this time.
- Connectivity: Consider service discovery, whether centralized or integrated.