Pregunta

I'm learning how to design a Microservice architecture. For example, here is a simple Microservice architecture:

enter image description here

I'm kind of confused by the Account Service.

As we know, for a web service, normally we need to perform a login first, and then we can get access to some services. For example, we perform a login, and then we can post a blog or buy some products. As shown from the above image, services such as "post a blog", "buy some products" should be independent of each other, because this is how a micro service works. But for these services, we must perform a login, which means that when a client sends a request to some service, the service must check the authorization of the client. To my understanding, this will cause many duplicated code.

Let's say I login a web server, and its Account Service sends back a token to me. Then I write a blog and send it to the Blog Service. When the Blog Service receives my request, it will first validate the token. After that, I buy some products, so I send a request to the relative service. Again, this service will validate the token too. Besides, to validate a token, the server has to store some data too, right?

So does Microservice architecture mean that I have to design a database in which all services has access to store the data used to validate a user-token? And does Microservice architecture mean that we have to duplicate some code on each service to validate the token?

¿Fue útil?

Solución

When developing and deploying actual micro services, you do not want your consumer to access the microservices directly for several (main) reasons:

  • it introduces heavy coupling on the client to your internal representation, to a certain degree this is similar to a case where you would expose a database directly,
  • it complicates integration on the consumer side, because they need to remember where each service lives, on which URL,
  • it is difficult to perform global checks and filters, such as API throttling,...

You have encountered one of those problems, which will certainly lead to others in the future.

Microservices should be internal in general. They may talk to each other in a synchronous (request/response) manner, although asynchronous (through events) communication is preferred, which makes it easier to deploy microservices separately, and also leads to more proper microservice design regarding their separation. With publicly accessible microservices, if you need to expose them to the outside world, put an API Gateway in front of them.

API Gateway acts yet as another system, through which flow all requests. It's usually pretty light weight and responsible for routing of requests to appropriate internal microservices. But it has one great added benefit. You can put necessary global operations in it (since it's your entry point). This includes authentication (who a user is) and optionally authorisation (is the user permitted to).

Since the API gateway authenticates your user (or otherwise rejects the request as a failed auth) and then forwards the request further to an internal microservice, the microservices themselves do not need to bother with authentication anymore. It's guaranteed to be performed before they're called, and they can trust the id of the user in the request. For most calls the id is the only thing necessary (without any additional checks), therefore in such context the operations needs not to bother with user logic at all.

With authorisation, it's a little bit different and depends on the context. If there are simple rules such as: "This endpoint may be called only by users with the role admin," then such rule can probably be placed in the API Gateway, to reject the request before even routing it into the microservice, which would reject it anyway. With more complicated authorisation closer to the business rules, it's necessary that the given microservice keeps their copy of a user and checks against its database by itself (circumventing the synchronous like communication).

API Gateway provides also another benefit for your ecosystem. You can introduce multiple backends for your internal microservices, e.g. one for e-commerce, one for some mobile application,... thanks to which the consumer worries only about the exposed endpoints and is not overwhelmed by logic which needs to be internally available in your system but is only consumed from different contexts (therefore exposed as a different backend).

Why is synchronous communication frowned upon? It's an easy mechanism how to obtain data among microservices, but it leads to direct coupling, because of which you need to introduce patterns like Circuit breakers, and starts to introduce single points of failure in your system, where a single failing microservice (on which tons of other microservices depend) may collapse your entire system. Event-driven systems are more resilient to this type of failure.

Otros consejos

Besides, to validate a token, the server has to store some data too, right?

It will likely log the attempt, but it won't store any extra data per validation.

So does micro service architecture mean that I have to design a database that all of services can access to store the data that used to validate a user-token?

Not a database. You'll likely just need the public key to assert that the token was properly signed by the Account Service.

And does micro service architecture mean that we have to duplicate some codes on each service to validate the token?

I prefer a shared library to simplify things, but yes, your Account/User service tends to be a shared dependency for most if not all of your other microservices.

Licenciado bajo: CC-BY-SA con atribución
scroll top