3

I'm currently looking at microservice architecture example and am struggling to make my services truly autonomous.

I have the following services...

  • CustomerAPI
  • CustomerService

  • OrderAPI

  • OrderService

  • ProductAPI

  • ProductService

As part of the OrderAPI I'm looking to create an order by sending back a Customer ID and Product ID.

In order to successfully create the order, I need the OrderService to use those IDs to retrieve the customer from the CustomerService and the product from the ProductService. I need to do this to ensure the IDs that are supplied are correct. By retrieving the customer and product I can also perform business checks I.e. a customer under the age of 18 cannot order alcohol.

This means my OrderService directly relies on other services which stops it from being autonomous. It also means my services are blocking (I need both calls to come back before I can continue). I've also been told that microservices should not GET data but instead ask services to DO something. This also violates this rule.

I noticed a code example on github which has the same issue as I'm describing... https://github.com/microservices-demo/orders.NET/blob/master/Controllers/OrdersController.cs

How can I redesign these services so that they are autonomous?

  • 1
    How do you define "autonomous?" What would the microservice have to look like in order for you to call it "autonomous?" How would you reconcile the fact that your OrderService does, in fact, require the CustomerService and ProductService to function properly? – Robert Harvey Dec 12 '17 at 17:36
  • Ideally, I don't want the OrderService to be dependent upon the other services so directly. Is there a way of doing this using an async protocol that would make this better? To be honest I feel like the OrderService is requesting data and it should be telling services to do stuff. – fml Dec 12 '17 at 18:00
  • Can the OrderService accomplish what it is supposed to do without data? Why did you mention async? – Robert Harvey Dec 12 '17 at 18:08
  • 1
    You might want to try reading this: microservices.io/patterns/microservices.html – Robert Harvey Dec 12 '17 at 18:10
  • No, it cannot. The product might have an age restriction and the customer's DOB would be required. I mentioned async in case there was a way to push this dependency back through messaging. – fml Dec 12 '17 at 18:11
5

Request-based microservices cannot be autonomous. They depend on other services by definition and have the standard coupling problems. E.g. cannot be deployed in isolation.

Event-based microservices can be autonomous. Here is how it works. Each microservice posts important business-level events (e.g. OrderPlaced, PaymentRejected, etc.) into a shared streaming database. Each microservice subscribes to events it cares about and turns them into its own local copy of the data it needs. Example: Order receives the CustomerAdded event and updates its own local copy of the customer table, separate from the one that Customer keeps. Later when Customer adds a new event which might correspond with new data in one of its tables, Order doesn't have to know/care about it to keep doing its job. There is a duplication of data, but a separation of concerns.

To make that happen you need a streaming database. A common streaming database I see mentioned for this is Kafka, which is distributed, scalable, and fault-tolerant. (And a lot of work to operate.) On a smaller (normal?) scale, you could use something like EventStore or Postgres with your own logic around LISTEN/NOTIFY.

You also need contracts defined (i.e. the structure that every listener can expect) for each type of event. I've seen Avro mentioned for this, and probably any schema standard would work as long as every team could access it. Or better yet grab a library and just use it. This is an API in and of itself, so versioning needs to be considered.

Event-driven Microservices can allow multiple teams to deploy continuously and without depending on other teams for the most part. But if its a single team, the value proposition of microservices is far less, especially because of ops cost. Following good design, a monolith can often be a better solution in the small and be refactored to microservices as it grows.

2

If your services are chatty and need each other's data, more probably than not it means that their boundaries are wrong.

To reach Business-IT alignment, you should think about your business architecture before defining technical services. It can be defined with capability-mapping or value-chain analysis techniques. Shortly, you should consider the major steps that your business carries out to obtain its business-value. In other words, these are the higher-level capabilities of your business. Customer makes order, customer pays it, and the order is delivered -- those are the major steps in e-commerce. These steps are fully autonomous, they don't require anyone else to know about their specifics. They communicate only with events. These are the boundaries you should align your technical services with.

So instead of Product, Customer and Order services you should have a Sales services that has all the necessary data to accept order.

And be aware of data duplication that Kasey Speakman proposed. Usually functionality duplication follows. Than some common libraries are extracted, turning you distributed system into a distributed monolith. Basically, events should be used to notify that something happened, carrying no more than some entity's id.

Here is an example that addresses this domain in greater detail.

  • Removed previous comment. Basically too many aspects of the working solution to convey in this format. Suffice it to say, I disagree with you. If your product is distributed across multiple teams, you have to give up on the idea that all data is centrally stored as normalized or else the teams are dependent on each other. It's often not a great track to follow in a single team, because normalization can conflict with Separation of Concerns, and the latter is more important to maintainability. – Kasey Speakman Dec 13 '17 at 17:19
  • I didn't mean all my data is centrally stored. I'm with data decentralization. But I do mean that data required by some business-process or use case must reside in a single place -- to avoid chatty services. Thus, separation of concerns is satisfied. – Zapadlo Dec 20 '17 at 18:26
  • 1
    This is the right answer, but unfortunately it's very hard to get the concept. I was also in denial until it finally clicked in my head. Having "entity based" services (OrderService, ProductService, CustomerService) is so obvious to most developers that it's hard to show that it's actually there where the problem resides. – Francesc Castells Sep 2 '18 at 21:42

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.