In this video, explore leveraging a Gateway for microservices architectures so you can understand how to leverage this pattern to improve efficiencies in the system.
- [Instructor] We will now move from decomposition patterns into integration patterns. These patterns allow you to solve orchestration and Ingress needs across your system as a whole. The first pattern that we're going to talk about is the gateway pattern. The API gateway pattern or gateway pattern is an Ingress pattern for clients communicating with your system services. The problem statement we're trying to solve is that of chaos. If we allow any client of any system to access any service however they wish, operational and maintenance needs will skyrocket across the system as a whole. This grows even more chaotic as your clients set increases, especially if third party vendors start consuming your APIs. The gateway pattern is designed to provide a buffer between the underlying services and the client needs. That can be accomplished via a facade or a simple proxy, each having risks and rewards. This single layer becomes the interface for the outside world into your system as a whole. And this includes client systems that you own. It can simply proxy the calls to your underlying services. It can mutate the calls, or it can limit the calls based on what the gateway itself exposes. This also, however, can become a single point of failure for a system as a whole. So care needs to be taken to ensure that it scales and responds well when the need arises. One of the most powerful aspects of a gateway is its ability to mutate the payloads from your system in a specific way to the specific consuming client. In its most simple form, it can proxy the backend calls. Using a gateway in this way allows you to put your security and authorization logic in a single Ingress point. You can restrict or allow access based on the client and its credentials. You can have a simple buffer so your internal system doesn't have to be exposed publicly. Only the gateway itself needs public Ingress. The gateway can also decorate payloads, oftentimes, we need to have common headers or other data points in the payload that are not necessarily relevant to the underlying service. By using the gateway we can apply that decoration in one place in a consistent way. Another powerful aspect is we can do aggregation. We have many use cases like high bandwidth desktop clients that can and should consume more data at one time. So we can use the gateway to aggregate the payloads under these approved situations, the gateway makes the underlying calls and assembles the data into a single payload for the client. Be very careful here of not applying business logic when doing this. It can and will lead to an unmanageable gateway. If you're going to need business logic in your aggregation routine, please stay tuned for the process aggregator pattern. In a similar vein, you can limit access. Say for instance, you have a lower bandwidth mobile client that doesn't have the screen real estate, let alone the bandwidth to handle a full call to your underlying API. The gateway allows you to limit the data you send to these clients, while not modifying the underlying services or the calls for other clients. One of my most favorite benefits of this pattern is it gives me the ability to provide a movement buffer. Consider having a web, desktop and mobile clients for your system, as well as public API clients you publish to npm or Maven. The gateway pattern gives you a contract driven API point, they can be static while the underlying services can change, migrate and move as needed. The gateway implementation may change, but your clients don't need to feel the pain of that change, because it adheres to your public contract. The strategy for building a gateway is actually very straightforward. First, you need to define your contracts. You can start small here. Remember, however, that this is your public touch point. Now, you expose those APIs in your gateway component. These APIs are static, or at least passive contracts and can be tailored for specific clients. You want to keep the contract solid so you may build out sets of APIs for each client independently of the rest, or just focus on the most dynamic APIs and expose them as being client specific along with a core set of global APIs. If you haven't heard, I've mentioned passive a few times on purpose. These APIs are your public touch point. Nothing and I mean nothing makes a developer more upset than having to fix code that worked yesterday, because someone in a third party system broke the passivity of a contract. In order to keep these contracts static, you strict version control like semantic versioning to keep your APIs growing, but to help ensure passing behavior. Of course, the versioning isn't enough. You have to make your your changes passive as well, based on that versioning strategy. Now, you simply implement your gateway. It is recommended that you build your internal client code in distinct modules and consume those modules within your implementation. By doing this, you could isolate the changes that are needed on the backend to support the growth of your internal APIs as a whole while keeping that public contract solid.