Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Good practices to propagate errors through micro services

We have a micro services architecture and we are having some discussions about how to expose internal errors to the client.

Here's an example:

Let's suppose we have 3 services, service A, B and C. When the client sends a request to the service A, which is public, this service sends a request to service B that sends a request to service C (which are internal and needs authentication, but the credentials are stored internally like environment variables, they are not send by the client).

And for some reason the communication between B and C receives a 401 (could be 422, 403 or any client related errors), which means that the request was not authorized.

Something like that:enter image description here

The communication between B and C is internal, the user don't know about these services. Should I expose our internal structure sending a 401 to the client? Given it's not the client's fault? Should I send a 500?

like image 734
Waldemar Neto Avatar asked Jun 17 '17 23:06

Waldemar Neto


2 Answers

It's better to avoid exposing 500 status explicitly but in some cases it's necessary. A user works with your system not with particular service and for him it doesn't matter what is inside. Internal system implementation can vary but user interaction can stay the same.

Let's A will be for instance a e-commerce service, B - billing service and C - billing gateway. User buys a product via A which send billing request to B and B communicates with C to perform transaction. 401 between B and C can be for different reasons. If it is simply internal configuration problem (not updated password, expired certificate and so on) it is an internal system bug and you need to tell user that service is unavailable now or something like that, not to pass all internal error details of course. You can use 5xx code in this case. Perhaps service B can put request to some kind of queue and tell service A that's everything is OK, your request will be processed later. But if it is because of user tries to use bad credit card or don't have enough money (not authorized request) A needs to show the proper message and 4xx response code.

In general a service exposes resources and it doesn't matter how many internal or external services, databases, data sources and so on are behind it. Perhaps 401 between B and C means for B to go to D service (C alternate) and A service shouldn't know about 401 at all. So, it depends on what you need to expose to user and how you need to handle different cases.

like image 118
Vasyl Zv Avatar answered Sep 23 '22 06:09

Vasyl Zv


Your diagram makes little sense. The incoming call is not 200 until it returns to the user successfully, after all internal services are called.

If the authentication between B and C is internal (server to server auth), then you have an internal error, and 502 is a sane choice to return to A. Of course, you might decide to retry in server A, as you got a 502 from B, but it's pointless because it's an expired token. So you may decide as policy that internal 401s should be escalated back to A. Or you may find attaching metadata in the 502 error response body assists a retrying mechanism. Anyway, server-server auth shouldn't be failing where it is a valid call.

So ... if C's authentication is working on the user's supplied token, then the user's authentication ran out during the call (rare, but happens) - in this case the token should have been extended elsewhere in the system prior to this call (probably in A's call to SSO). But it wasn't, so return 401 to where-ever in the application redirects to the login page.

like image 43
JeeBee Avatar answered Sep 21 '22 06:09

JeeBee