A SAGA microservice application - 2

In this post, we will take a look at the Spring Cloud technologies and the tools we will use to code our microservice architecture. We have decided how our services will be structured and explained our reasons in the first post. Now it is time to go grab the tools and get our hands dirty. But i have to warn you before jumping in. From now on, we will be talking a lot about Restful services. It will be a lot easier to understand the concept if you have the basic knowlegde about these HTTP method based communications.

We know that microservices can work independently by themselves. This also brings the ability to develop each service with a different technology, thus having technology independence. We normally need the libraries that are written with the same language as we debeloped the project. For example, Java applications can use ".jar" libraries. But if you have modules working separately, they can use different languages and libraries. Of course the number of different technologies used in a microservice architecture is not a measurement of success, unless used consciously. Our purpose is to absord the microservice architecture and code it the right way. Therefore we will stick to Java language and use Spring Cloud technologies. It is recommended to have an experienced team leader to help with the tehcnological desicions according to requirements, constraints and goals :) Let's put our big picture below.

What does this picture tell us?

When we talk about the microservices, naturally, web services comes into the picture. Our design mandates some level of interaction between these web services. I will follow a bottom-up approach to explain the structure. This will be easy to understand. It helped me clearify the architecture back when i was beginning.

3 services at the bottom, are the services to connect to databases and have basic functions. They are responsible for users, events and payments. You can also develop new services at this level, like basket or reminder mails or billing. You should try this later :) These services are the glorified projects for simple java classes you would have inside your monolithic app. They contain small methods that connect to database (each one can connect to a different DB perfectly fine) and return the results. I especially said "small" because these services do not contain any business logic inside them.

For example: The user login operation does not return all the user information with the response. There is another endpoint to retrieve user information. Also we don't have seats control while making the payment. That control is inside another method. Hence the requirement for a SAGA emerges. This is basically converging to single responsibilty. This makes the development and maintanance easier.

Furthermore, we have "+ failover" in all these bottom services. The failover is the service to reach out when the small services are not available. This is not a backup service. It is rather "Please wait" service. It is meant to return the response "Sorry for inconvinience, we can't reach user service". Because user service might be down while deployment or due to some crash. We will have emergency response failover services in these conditions. We will also see how to fire up a backup service in the 6th post in this series.

Eureka

The first spring cloud technology is Eureka on top of the small services. Spring is a framework or a bundle of libraries in other words. Spring boot is the project infrastructure that uses spring framework. This has nothing to do with the microservices yet. It helps us write less boiler-plate code over and over and find some well known libraries instantly. Spring boot will help your create and start a web service project. I have talked about spring boot in a previous post.

Eureka is a registry and load balancing service. It helps us to know which services are up and running and load balance among them if more than one instance of the service is alive. It starts up like a web project and it detects the 3 running services at the bottom. It can also redirect the requests to each running backup service sequentially.

Gateway

The gateway comes before Eureka is, well, the gate for our architecture. We don't directly reach out to user service in this microservice arhcitecture. We have put Eureka in front of the small services. But how can we redirect the requests to failover services if for example the user service is down. This function is called circuit breaking and Eureka doesn't have this function. This is why we use Spring Cloud Gateway for routing. This gateway transfers the requests to Eureka depending on the context. And Eureka calls the services with load balancing. We will create "Go to failover service if you can't reach user service" type of routing. If you ask "where is the failover?", it is also registered to Eureka. There used to be Zuul project for routing and Hystrix for circuit breaking developed by Netflix. But those projects are acquired by spring cloud and now we can have both functions in one project with Spring Cloud Gateway.

Web application

The application on the top is the MVC web application and the coordinator. This is the app that we login and buy tickets with an interface. It sends out the request to gateway when we click user login. Gateway knows this is a user operation and redirects it to Eureka with "send this to user service" command. Eureka knows who is the user service and where is it located and can redirect the request to the relevant service. In the end, the MVC app retrieves the result and determines the next step. Upon successful login, it sends a request to gateway again to retrieve the user information. This way, it is coordinating the flows.

The MVC app can be a whole different nature other than a web app. It could be a mobile app too. There is technically no limitation here. You just have to know how to operate SAGAs, the stories with a beginning and an ending. It will be enough to call this service and this method and after this service and this method and etc.. after establishing these flows. If you had "where am i going to put this code" questions in the previous post, i hope you are enlightened a little. I will write these codes with comments in the following posts in this series.

Config Server

Lastly, we have the configserver. Let me explain it like a constitution for a country for now. There is a Config Server project within the spring cloud technologies. You can gather all the necessary information for all the services (including Eureka and the Gateway) in a central configuration. This can help us change the DB configuration one day, without re-deploying the service.

Spoiler alert. We will have 10 different spring boot projects. 3 small service + 3 failover + eureka + gateway + config server + MVC app. We have designed this architecture knowing what we want and the tools. But What would have happened if we didn't know about these tools and what are they used for? Let's analyze this. Suppose you are tyring to divide a monolithic app into small services in your mind. This will be your basic approach since you have never worked on or designed a distributed system before. You may predict sending a request to user service and redirecting it to event service and then the payment service. Each of them working independently. Then you will have this question: 1 request can only have 1 response. Where will my reponse come from and how will i know it from outside? What if something goes wrong and redirects to failover? What if an exception changes the flow of the request, like a try catch block?

The bitter process :)

This may sound like a weird question to you but if you take a look at the courses on Udemy or blog posts about the microservices, there is no proper answer to this question. There are usualy message based microservice examples and it is fundamentally different than our system. There is usualy a message queue structure in the center, like a middle-man, and all the services are expecting a message from this source. It is a lot like Mediator pattern. In this scenario, usually, the client app calls a reactive service. And the reactive service usually returns "Ok, i'm done" message to the queue. This is like the principal of the school calling someone from a class. Everyone askes each other "have you seen ...?" and eventually that person comes up. Our system is not as much complicated. Therefore we don't need a message queue based approach here.

Also, some example applications are just writing down a message to console and considering the system working. But it is actually impossible to work with that piece of code in a real application. Some of them just say "If you write this code, this works". This is why i have started out thinking that my tiny services would call each other and made my first mistake. It would be impossible to establish that architecture without properly understanding microservices tools.

And then i decided that the small services should communicate through the gateway. But in this case, the services became too heavy with the bussiness logic. Also, my MVC app would have to wait for a response that will come from a potantially unknown service. This led me to think about putting all the business logic inside the gateway via routing logic. This would allow the small services to ask the gateway "hey, can you help me with that". It is a bit of a loop between the services and the gateway. But it would have been way too complicated for the gateway. You should only use the gateway for routing and securing the requests.

Finally, i have decided to convert the coordinator into business flows and SAGAs inside the MVC app. This allowed me to write simple services, gateway and readable business logic. Maybe this process was happened because i had started with zero experience. Maybe my desicions right now is not exactly fit for our purposes. My architecture and solutions may not be ideal or optimal. These questions are all results of the advantages and disadvantages of the microservices that can change according to person and circumstances. Let me know your thoughts down in the comments :)

Ok i promise to write code in the next post

Important note: At this point, you must have basic Java, Rest api, Spring Framework and Spring Boot, Maven, Github and a development environment like Eclipse or IntelliJ. You should also have an IDE, Java 11 and Maven installed and configured in your system. And lastly, a MySql server must be installed and up and running to connect to a database. Yes, these are as much knowledge as a 2 year junior developer, but it wouldn't be much logical to start software developing with microservices without these experiences.

The next post will have detailed information about Eureka, Gateway and the Config Server. We have decided the architectural design one way or another. We have decided the technologies. Now we can start writing the codes that you can run on your computer. You can find all the necenssary code (except the config repository) on Github but you will need some configurations to be able to run it. That is why i recommend you to follow the series and run it alongside. I have had troubles while learning but i hope you won't face the same problems. Because i will continue mentioning my errors alongside the code. See you at the next post :)


Leave a comment