7

My company has been converting to a service oriented architecture, but we have an odd setup. We have a number of web apps. Each one of these web apps currently has their own RESTful microservice. These microservices are essentially an intermediary to our backend REST services. Although they are generally a pass through, the microservices were created to authenticate/authorize a user, format data, enrich data and aggregate data between multiple services. I have a couple of questions:

  1. I always see that microservices are supposed to communicate with one another. Currently 2 separate microservices might call the same backend service. Is this correct design, or should I make one microservice A that calls a backend service, and 2 other microservices, B and C, that call A?

  2. We want to push some formatting from the UI to the microservice. For instance, we always want to format a phone number from backend service A to have dashes. 5552223333 to 555-222-3333. Should I have a formatting microservice I pass through, or is it best to do it on each microservice that calls backend service A?

  3. Each web app only communicates with it's specific microservice. Should web apps communicate to multiple services rather than just the one? This would get rid of the duplication I see throughout the microservices.

If anyone has any good resources that deal with a similar design, I'd love to read about them.

3

The ideas behind microservices:

  • You publish a service to all eligible clients; if you add a client, you don't have to rewrite the backend, you reuse it.
  • You can replace an implementation without disrupting other microservices, as long as you expose the same interface.
  • You can run more of some kind of microservice nodes if they need more resources, or run them on different hardware, etc, so that you have easy time scaling / adapting your system to the load without rewriting it, or without major redeployments.
  • If some of the microservices become unavailable, your whole service has an option to function partially, when it makes sense.

Whatever helps this is good. But remember about the overhead and complexity added.

Various services hitting the same backend, and otherwise hitting each other in a DAG pattern is not just OK, it's sort of the idea behind it. It's how you share functionality of a backend with whatever other services that might need it. This is how you get rid of duplication of code and inconsistencies in functioning.

I'd not run a whole RESTful microservice that only formats a phone number. How often do you change this format, and do you want to change it without restarting the whole system? A bigger data-normalization service looks more reasonable. A non-RESTful RPC (something low-overhead, protocol buffers / cap'n-proto /thrift) may be an option for a very lightweigt function.

  • Is it best to have a UI to Microservice DTO/interface, which then maps to a business layer object where any manipulation happens, which then maps to the outgoing service calls (another DTO)? And vice versa: when my microservice gets a response from an service (DTO), it should map to a business layer object where any formatting or business logic happens, which then maps to the outgoing DTO? – Mike H Mar 9 '17 at 23:35
1
  1. I always see that microservices are supposed to communicate with one another. Currently 2 separate microservices might call the same backend service. Is this correct design, or should I make one microservice A that calls a backend service, and 2 other microservices, B and C, that call A?

Answer 1: Deciding to split or merge microservices, or alter their communication structure is really dependent upon what you want to accomplish in regard to performance, security, network and code overhead, and your operational limitations.

You can answer your question "should I make one microservice A that calls a backend service, and 2 other microservices, B and C, that call A?" by answering a few questions such as:

  • How is performance impacted for all services when you make either decision?
  • How is security impacted for all services when you make either decision?
  • Which decision is easier for developers to reason about, or helps to simplify the code structure?
  • Are there any restrictions that would limit either decision (cost overrun with new servers/containers, external api rate-limits from third-party services, etc.)?

Once you answer the questions that matter you can find reasons why you would or wouldn't split a specific service.

Side Note: You are very clear that your organization designates the difference between a microservice and a backend service. Sometimes organizations use the wrong domain-specific language and group things in a way that is incompatible with the mental flexibility you need as a developer to do your job. To be clear: everything is a microservice. You shouldn't be afraid to open a REST interface on a "backend" service if the performance, security, overhead, and limitations matrix are in favor of this decision... because "it's just another service".

IF your definition of backend services are shared databases or queue services, then you're not doing microservices the right way. Split all of those tables off into database instances attached to their respective services. Services should not share the same database schema, but should share data with their defined (REST / websocket / network) interfaces. The answer in this scenario would be "make one microservice A that calls a backend service, and 2 other microservices, B and C, that call A".

  1. We want to push some formatting from the UI to the microservice. For instance, we always want to format a phone number from backend service A to have dashes. 5552223333 to 555-222-3333. Should I have a formatting microservice I pass through, or is it best to do it on each microservice that calls backend service A?

Answer 2 Shared formatting (or algorithms) should be placed in a shared module and installed in the code closest to the transformation. I would suggest the code necessary for parsing, formatting, and validating phone numbers be moved to a shared module that can be installed on each microservice that must handle phone numbers.

Side Note: If you disagree with the shared module idea and opt for a "phone number formatting service", then let's explore how that scales. What happens when you need an "address formatting service"? Is this a separate service with all of the code, network, and maintenance overhead? Do we open up new REST endpoints on the "phone number formatting service" and blur the lines of single responsibility? The easier solution would be to create a new shared module (which has a low code, network, and maintenance overhead), isolate all of the address logic in that module, then include it in any service that must handle that logic.

  1. Each web app only communicates with it's specific microservice. Should web apps communicate to multiple services rather than just the one? This would get rid of the duplication I see throughout the microservices.

Answer 3: This is a tricky question. In an absolute and ideal world; using one microservice as the facade for each web app is the right decision. This buffers erratic user behavior and performance issues from your core services. It also ensures clean separation of the client-specific logic from the core logic.

However, the real world answer is more organic. Start developing the web app and make requests directly to the services. If the capability of the web app grows beyond what is manageable with point-to-point communication to each service then build a facade.

Most likely the first people to speak up will be the mobile devs asking for a single aggregate endpoint/service they can call instead of many endpoints/services.

Side Note: You should get rid of the code duplication in your services independent of the answer you choose here. If there is code duplication across your services then move that into a shared module with a simplified interface, then include that module in your services and remove the duplicate code. You will still have some code duplication, but it will be code that uses the public interface you designed (stable), instead of specific business logic on how to handle a problem (less stable).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.