Microservice Approaches

I have a question for the microservice community. I will give an example from the educational field, but it is applicable to each microservice architecture.

Say I have a student service and a licensed service with the requirement that the number of students is limited by license. Therefore, each time a student is created, a licensing check must be performed. There are several types of licenses, so the type of license must be included in the operation.

My question is: which approach did you find better in practice:

  • Create a composite service that calls 2 services
  • Associating a student service with a licensing service, so that when createStudent is called, the student service makes a call to the licensing service, and only when this is completed will the student be created
  • Using Event-Based Architecture

People talk about microservice architecture, which is more like a graph than a hierarchy, and option 1 turns it into a hierarchy, where you get increasingly coarse composites. Other disadvantages - this creates confusion as to which service clients should actually use, and there is some duplication, because the composites API will have to include all the parameters necessary to call the services listed below. This is of great benefit because it gives you a natural place for failover, choreography, and descriptor consistency.

Option 2 seems to have disadvantages:

  • The licensing API will need to flow in the student API so that you can specify licensing restrictions.

  • this puts a big burden on the student service because it needs to handle consistency in all dependent services

  • as more services are needed to respond when a student is created, I could see that the dependency graph is quickly getting out of hand, and the service will have to cope with this complexity in addition to that which exists from its own logic for managing students.

Option 3 Although I unleash the sky, I really don't think it will work, because it is all called from the user interface, and people are not really used to “doing something else while this new student shows” the approach.

thanks

+6
source share
5 answers

Licensing applications and creating students are orthogonal, so option 2 doesn't make sense.

Option 1 is more reasonable, but I would try not to create another service. Instead, I would try to “filter out” student service calls through middleware licensing.

Thus, you can use this middleware for other service calls (for example, service classes), and changes to the API of both licensing and students can be performed independently, since these things are really independent. It just happens that licensing uses the number of students, but that can easily change.

I'm not sure if option 3, an event-based approach, can help here. However, it can solve other problems.

+2
source

IMHO, I would go with option 2. A few things to consider. If you buy a full set of SOA and, in addition, microservices, you cannot flinch every time a service needs to contact another service. Try it ... remember that thing. What I really like about option 2 is that a successful student service response is not sent until the license request is completed. Think of a licensed service as you would any other external service, where you can wrap a licensed service in a client object that can be published by the license service JAR.

  • The licensing API must be leaked into the student API so that you can specify licensing restrictions.

Yes, the licensed service API will be used. You can call it a leak (someone should use it) or encapsulation so that the client requesting the student service does not worry about licensing.

  • this puts a big burden on the student service because it needs to handle consistency in all dependent services

Some services must take this burden. But I would deal with it organically. We are talking about 1 service that needs another. If it grows and becomes uncomfortable, then refactoring can be done. If the number of services required for student learning is growing, I think that it can be gracefully reorganized, and perhaps the student service becomes an integral service, and groups of independently used services can be combined into new services, if necessary. But if the list of dependency services used by the student service is used only by the student service, then I don’t know whether it is worth grouping them into my service. I believe that instead of loading and leaking, you can look at it as encapsulation and ownership .... where the student-service is the owner of this burden, so he does not need to flow to other clients / services.

  • since more services need to be reacted when the student is created, I could see that the dependency graph quickly gets out of hand, and the service will have to deal with this complexity in addition to the one that is out of its own logic for managing students.

An alternative could be various composite services. Like my answer to the previous marker point, this can be solved elegantly if it looks like a real problem.

If forced, each of your options can be turned into a viable solution. I am making a stubborn case for option 2.

+2
source

Option 1 and 2 creates a tight connection that should be avoided as much as possible because you want your services to be independent. So the question becomes:

How to do this with event-based architecture?

  • Use events to track licensing information from the licensing service in the student service, virtually duplicating data. The disadvantages are: you only have final consistency, since data duplication is asynchronous.

  • Use asynchronous events to trigger a chain of events that ultimately trigger student creation. From your question, it looks like you already have an idea, but you have a problem with the user interface. You have two possible options: wait for the student to create (or crash) with a small amount of timeout or (the events are better), make your system fully responsive (use the push-client-client mechanism for the user interface).

+1
source

I know that the question was asked some time ago, but I think I have something to say that it can be useful here. First of all, your approach will depend on the overall size of your final product. I tend to adhere to the rule of thumb: if I have too many dependencies between the individual microservices, I usually use something that will simplify and possibly remove these dependencies. I do not want to end with a web of services! A good thing to look at here is message queues like RabbitMQ .
However, if I have only a few services that talk to each other, I just let them call each other directly, as any alternative solutions that simplify the architecture add some computing and infrastructure overhead.

Whatever approach you take, design your services in hexagonal architecture ! This will save you from problems when you decide to move from one solution to another. What I usually do is design my DAOs as “adapters,” so the DAO that calls service A will either call it directly or through a message queue, regardless of business logic. When I need to change it, I can simply change this DAO for another without touching any business logic (in the end, the business logic does not care how it receives the data). The hexagonal architecture is very well suited for testing microservice, TDD and black box.

0
source

I recommend option 3. You have to choose between accessibility and consistency, and accessibility is most often desired in a microservice architecture.

Your 'Student' aggregate must have the 'LicenseStatus' attribute. When a student is created, his license status is set to "Unverfied" and the "StudentCreated" event is published. Then, the LicenseService should respond to this event and try to reserve a license for this student. The Reserved or Rejected event will then be posted, respectively. The student service will renew student status by subscribing to these events.

When the user interface calls your API gateway to create a student, the gateway simply calls the Student service to create and returns a 202 Accepted or 200 OK response, without waiting for the student to be properly licensed. The user interface can notify the user when a student obtains a license through asynchronous communication (for example, through a long survey or web sockets).

If the license service is not working or running slowly, this will only affect licensing. The student service will still be available and will continue to process requests successfully. After the license service is restored to serviceability, the service bus will push any pending StudentCreated events out of the queue (possible consistency).

This approach also contributes to expansion. A new microservice added in the future can subscribe to these events without the need to make any changes to student or licensed microservices (decoupling).

With option 1 or option 2, you will not get any of these advantages, and many of your microservices will stop working due to one unhealthy microservice.

0
source

All Articles