官术网_书友最值得收藏!

Microservices structure

We want to build a geolocalization application and we chose to create it like a game so that it is more fun and easier to understand. Feel free to adapt the example to any other idea, for example, a tourism application with geolocalization embedded.

Our game will use geolocalization to find different secrets all around the world (or in a specific geographic area if you want a smaller map). The backend system will generate new secrets and place them randomly on our map, allowing the users to explore their environment to find them. As a player of our game, you will collect the different secrets and store them in your wallet, which is where you will find more information about each of them.

To make our game more fun, we will have a battle engine. While you are discovering our secret world, you can battle against other players to steal his/her secrets. The battle engine will be a simple one--just throw a dice and the highest score wins the battle.

A project of this kind cannot be completed without other services, such as a user/player management system among others.

As a developer, you start with a specification and you try to decompose it into smaller parts. From our little description, we can start defining our microservices and their responsibilities as follows:

  • User service: The main responsibility of this service is user registration and management. To keep the example small, we will also add extra functionalities, such as user notifications and secrets wallet management.
  • Battle service: This service will be responsible for the users battle, keeping a record of each battle and moving secrets from the loser wallet to the winner.
  • Secret service: This is one of the core services for our game because it will be responsible for all the secrets stuff.
  • Location service: To add an extra layer of complexity, we decided to create a service to manage any task related to locations. The main responsibility is to know where everything is located; for example, if the user service needs to know if there are other players in the area, sending a message with the geolocalization to this service, the response will tell the User Service who is in the area.

Note that we are not only creating services for our game, but we will be using other supporting services to make everything work smoothly.

The following diagram describes the communication paths between our different services. Every service will be able to talk to other services so that we can compose bigger and more complex tasks. The following diagram depicts connections between our microservices:

Microservice patterns

A design pattern is a reusable solution to a recurrent problem in a real-world application development. These solutions have a proven track record of success and they are widely used, so adding them to our project will make our software more stable and reliable.

We are building a microservice application and because we want it to be as stable and reliable as possible, we will use some microservice patterns, such as: API gateway, service discovery and registry, and shared database or database per service.

API gateway

We will have a frontend for the users to register and interact with our application and it will be the main client of our microservices. Also, we are planning to have native mobile applications in the future. Having different clients using our application can create headaches for us because their use of our microservices can be very different.

To unify the way any client uses our microservices, we will be adding an extra layer--an API gateway. This API gateway becomes the single entry point for any client (for example, browser and native application). In this layer, our gateway can handle the request in two ways: some requests are simply proxied and others are fanned out to multiple services. We can even use this API gateway as a security layer, checking whether each request from the client is allowed to use our microservices or not:

Assets' requests

Having an API gateway has numerous benefits, among which we can highlight the following ones:

  • Our application will have a single point of access, removing the problem of clients needing to know where each microservice is.
  • We have a bigger control of how our services are used, and we can even provide custom endpoints for specific clients.
  • It reduces the number of requests/roundtrips. With one single round-trip, a client can retrieve data from multiple services.

Service discovery and registry

Our services will need to call other services. On monolithic applications, the solution is very simple--we can call methods or use procedure calls. We are building a microservices application running in containers, so there is no easy way of knowing where some service is located. Our containers infrastructure is very flexible and we need to build a service discovery system.

Each of our services will obtain the location of all the other linked services by querying our service registry (a place where we store information about all our services using Consul). Our registry will know the locations of each service instance. The following figure shows the autodiscovery pattern:

To achieve this, we will use different tools:

  • Consul: This is our service registry with loads of features, such as clustering support, among others.
  • Fabio: This is a reverse proxy built on Go and has a deep integration with Consul. What we like about this proxy is the easy connection with Consul and its ability to do blue-green deploys. Another interesting tool you can try is Tr?fik.
  • NGINX: A powerful HTTP server and reverse proxy, this is a very well-known tool for most of the web developers and was chosen due to its performance and low memory footprint. We will be using Fabio and NGINX as reverse proxies indistinctly.
  • ContainerPilot: This is a small tool written in Go. We will use this software to register our services in Consul, send stats of our containers to a centralized telemetry system, send health checks to Consul, and detect changes in other services. We will create some kind of auto-healing system with this tool.

Shared database or database per service

In one way or another, an application generates data that we need to store. In a monolithic application, there is no doubt that all the data is stored at the same place. The problem is when you are dealing with a microservice application and there is no easy response. Each application domain is unique, so there is no rule of thumb to solve the problem; you need to analyze your data and decide if you want to store all the data in a shared store, if each service has its own data store, or a mixture.

In our sample application, we will cover both the approaches but let's explain the benefits of each option.

Database per service

In this approach, we keep each microservice's persistent data private to that service, the data is only accesible via its API and has numerous benefits:

  • It makes the services loosely coupled; you can make changes to the battle service without impacting the user service, for example.
  • It increases the flexibility of our application due to the fact that the data can only be accessed by its API; we can use different storage engines. For example, we can use a relational database in our user service and a NoSQL in the Location service.

Of course, this solution has a few drawbacks, the difficulty of joining data shared between different services being the most notable problem.

Shared database

This approach works like a database in a monolithic application--all the data is stored in the same engine. The main benefit is the simplicity of having everything in one place.

This simplicity has some drawbacks; we highlight the following ones among them:

  • Any database change can break or impact other services
  • Results in a less flexible application as you are using the same engine for all the data
  • If the data store is down, all the services that use the shared database will note the problem

As a developer, your job is to find the best solution for each problem you need to solve. You need to decide how you are going to store the application data, always keeping in mind the benefits and drawbacks of each option.

主站蜘蛛池模板: 水富县| 溆浦县| 宜君县| 德钦县| 泸定县| 丹阳市| 纳雍县| 颍上县| 定日县| 南汇区| 万州区| 临夏市| 青岛市| 尼玛县| 延边| 顺昌县| 阿拉善左旗| 贡觉县| 丹东市| 资溪县| 唐海县| 龙门县| 平利县| 承德县| 敦化市| 桐城市| 理塘县| 武冈市| 临颍县| 汶川县| 宜宾市| 汾阳市| 天长市| 溧水县| 松江区| 房山区| 黄平县| 双牌县| 苏尼特左旗| SHOW| 蓝田县|