Moving from Monoliths to Microservices πŸŽ‚ β†’ 🍰🍰🍰

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hi everyone, this is GKCS! Today we are talking about how to move from monolith to microservices. Now we know what monoliths are. They are rather large code bases, which contain all of the logic required for you to run your application anywhere you like. All of the relevant code in this project is kept in a single repository. While in the micro-service architecture, you have cell phones, which connect to different services based on what the requirement is. So let's say you're logging into Google. Does the payment service in Google need to know about what you're doing? No, not really. You just need to go to the authentication service and when it gives you a response, your authentication is done. So you are seeing that the code has been broken into pieces and converted into services themselves. As you can see, there are quite a few advantages that microservices have over monoliths, the first one, being that if you need to make any feature change, let's say your payments now need to also accept PayPal payments. All you need to do is just go to this payment service and make the change. So there's a good separation of concerns. The second one is coding in microservices is sometimes easier because all you need to worry about when you're making a feature change is just the code, which exists here. So your expectations are well-defined in the payment service. Your responses are well-defined and that's all you need to care about. Your assumption is that the rest of the services, the engineers in those services will respect the contracts that you are making with them. So to some extent, coding is easier, but so is designing these services and the interactions that they'll have. So I would say instead of coding, maybe 'engineering', these services is actually easier. The third critical advantage here is that you can make deployments much easier with microservices, the authentication service, when there's a change in that, you can just deploy the authentication service separately. There might be a service, which is not critical. For example, you have some ranking service, some machine learning service, which ranks your restaurants. Now, if it stops for one second, the world won't come to a collapse. So the deployments are easier. These are the core advantages of microservices. Monoliths also have certain advantages. The time when you move to a microservice architecture is not when you have a lot of scale, not when all of your users are coming in, you move to a microservice architecture when your team has scaled. When you have a large team and all of them want to move about individually, you have different product teams working on different products. You want deployments to be smooth. That's when you move from monoliths to microservices. So for a small team monoliths are good. For a large team, microservices are probably the way to go. The second one is that because there is more clear communication happening in the monolith... Module A to module B, you're doing a single function call. The parameters. That you're passing into that function are explicit. They are clear. So when you're making that function call, if you make a wrong function, call, the compiler is going to say no. While in a microservice, what could happen is that ID was earlier an int. Now you ran out of integers. So you made it a string. So all the other services who connect to this service are going to be using the profile with the ID as an int, because they are not aware that the ID has turned into a string, which means that all communication to this service will break. Okay, this is called a breaking change earlier. You had something. Now you have something else which is not compatible. That's a breaking change. So in microservices. It's much easier to have breaking changes, which is bad. While in monoliths because the code and therefore the expectations are in one place, it's much harder to have these kinds of problems. Contracts are in one place. These are the service contracts. Now let's find out how we can actually move from monolith to microservices. One strategy would be that you make this microservice architecture, where you have this cloud of things running, and then some parts of the user, maybe 10% of the users are redirected here. If they have no issues, if these services are working perfectly along with their databases, then you can make the switch. But the problem with this. Is that the engineering challenge is huge because you need to write down all of these microservices. Also make sure that the databases are correctly configured. Then you have to redirect these users. So the effort for doing. This is massive. A much better approach is not to invest so much in the start. What you can do is when you have a new feature in this monolith architecture, you can try to separate that out into a single service. For example, you might have a new analytics feature that you need. So whenever any of these modules are producing an event, you need the analytics module to process that event and then give you dashboards or graphs or reports instead of actually putting it in the moonlit architecture, we separate it out. We make this a separate service. And how do we do that? Well earlier, when you were communicating through cord, you used to just make a function called. Now you're going to be making this call over a network. So you'll have either HTTP or GRPC or whatever the network called doesn't really matter. But the treatment of this piece of code, this service is as if it's an external thing, you cannot access any of its functionalities through a function called, uh, and the analytics service will also have its own database, which may be the same as this database. Let's say, this is my SQL that you might end up using my SQL here also, but you might use an SQL database also like Amazon dynamo, DB, Cassandra, anything. There is an isolation of concerns when it comes to the analytics service. And through this small change, what we have done is we are open the possibility for all future services, all future functionalities being sent to their relevant services. So analytics is having its own code repository. This might be hosted on GitHub or wherever, and this has its own code repository, which is separate from the analytics code repository tomorrow. You might find that there's a functionality of sending emails, which is being used by payments. Being used by profile is being used by analytics. There's different emails that you need to send. So you separate that out into separate service. By doing this, what. Happens is we need to now bring in some infrastructure changes to make addition of these services easy. And what are those changes? Well, firstly, you need to be able to define how are you going to communicate to these services? So the email service is going to be taking your network calls, but it needs to give you a contract. That for the profiles that I have, I have the ID as an integer or as a string or whatever. But this contract has to be maintained by the email service. And whenever an external service wants to call a function over here, it has to read this contract, construct an object as per requirement, and then send the request or the network. That's the important thing. So the first change that we need is that we need to define contracts for each microservice. Okay? These are also called clients. Whenever a service in session service wants to call it email service. It doesn't really read the contract. Technically what happens is you have something called a client, okay? Each service has their own client. So if I'm an engineer for the analytics service, I say, well, you're going to be reading my contract, constructing the object in my way. That's pretty bad. So instead I will write some piece of code, make a library out of it. And anybody who wants to talk to analytics, you use this library to make these function calls. Okay? So if sessions wants to talk to analytics, all it needs to do is download the library. And if you want to say, get report, my library has that function and you can pass in an ID. Here. My library will figure out how to talk to my. External service. So analytics is here. This is my library, which is running in your box. And you are over here. Maybe you are the session service, which is interacting with. This library. Okay? What. Happens if my library's not up to date too bad? I mean, the code will break most likely, or when it reaches here, there's going to be a break. So you need to be continuously updated in terms of libraries. If you're looking for more details on how this library is updated across services, you can look at the description below there's interviewready.io, which is a system design video course. It talks about this in more detail. The second thing we need to do is also have a mechanism for routing requests from any service to another service. So that's point number two, we need some sort of a router. Most likely it's going to be the load balancer, the services, the street, which routes requests based on service capabilities, all this happened because you took a new feature of analytics and made it a separate service, right? Because of that, you can actually pick on each of these functionalities separately. Point number three is simplifying deployments. The simplest way to deploy any service is to do a CP, which is copy of the code that you have in your GitHub repo on to an AWS box or GCP box, then going on to that box and running the service. Okay? So literally what you're doing is you're copying your code from one place, keeping it in the cloud server and then running that service by firing a command. But as the number of services in your organization increase, that's not what you want to be doing. You want to more seamless way of things happening, maybe on every gate push to master. You want the deployment to be dead, okay? Because your tests have run through and you're sure that everything is fine. So you want to simplify deployments by using tools like Jenkins. You want to simplify deployments by actually using containers instead of deploying it on the box that makes your DevOps team happier. The fourth one is that communication between services can be varied. Let's say the session service talks to the analytics service by using a message queue. Because if the message doesn't reach the analytics team, if this event doesn't reach the analytics service, what's the big deal. You know, the reports will be wrong, but it's not like the user's going to drop off while in payments, you might need a much more immediate response. So when the profile service is talking to the payment service, you might want to request response architecture so that you know exactly what happened immediately after a request has been sent to payments. So that's the communication bit point number five, which is the thing that most people forget is logging. Uh, this is super important. If a request is sent from the user to the session service, then it goes to analytics which triggered something in profiles. And then it went to payments. There's no way that you can track all this by logging into each service and then checking the logs and saying, oh, the ID will be over here all the time. Then you go here and it's. Not going to happen. Instead. You want to take. All the logs in all the services and push it into a single repository, okay. A single database. So to speak, you can use the elastic stack, which is good at this stuff. And for pushing logs, you can do it through a message queue like Kafka. Kafka can take all of the logs from all of these services, and then you can store them in something like leucine, which is a part of this stack to summarize, moving from monolith to microservices, require us to look out for new features, which are being added to our existing application. We need to then think about how we can take those new set of features and condense them into a single service, which instead of being added as a module to the monolith, it will be made a separate microservice. Once this is done, you can start focusing on these five parameters. Do these services have sensible contracts which are being updated. Do they have some sort of routing to the right service? Do they have any sort of deployment help so that the engineers are not too uncomfortable adding new services or maintaining. The services is communication between. The services well-defined. The communication may be in different ways. You might have a request response architecture, which is standard. You might have a messaging queue, which takes the quest and then sends it. And you might also have some sort of a batch processing thing where you take 10 requests and send them together to the next service. And finally, you need to take care of logging. This is more like. Making sure that the infrastructure on microservices is fine. If you have all of the logs of these services being condensed and put in a single place, what happens is if a user has an issue, okay, let's say the user ID is 123, then all relevant logs for that user request. Let's say the request ID it's 256. All of them can be pulled out from this single repository in one shot, which makes debugging much easier and also root cause analysis of any bug, much, much easier. So go ahead with this. If, and when your team is convinced that you need to move to microservices, here's a few things to keep in mind. The first one is that every microservice needs to encapsulate the data that it is responsible for. So if you have profiles as your microservice, all profile related, information should be with you. So if a person says, get a profile, it's not like they can get the profile from the payment service. Also that's impossible. The payment service has to ask you for profile related information. Now it might store it locally in a cache. That is okay. It's not taking real responsibility for the cash. The expectation is that whenever you need to update the cash, you need to make a network call to the profile service. Okay? So you are the source of truth. You are a single source of truth. Every component in your architecture has to have a single source of truth when it comes to microservices, which only happens if you have a dedicated data store for each service. The second thing to keep in mind is that it's very tempting to take services and break them down into simpler and simpler components. But the important thing to remember is that what is the responsibility of this service? And when we are breaking it down, are we also separating our responsibilities? For example, let's say the profile service needs to take information from various external services like. Google, Facebook, and LinkedIn. These external services, they are giving you information in the profile service. You might feel like, Hey, it's not the profile service job to take this information. I will create a separate service here, which is going to be condensing all this info from the three external services and giving me a single response. So the profile service talks to this service, which is an intermediary, uh, which talks to external services. And then the response is sent back. Okay. This might seem like a good idea. But the question to ask is that, is this data being used by any service except the provide service? No. When there is a change in profile service requirements, is there a change in the service requirement? Most likely. Yes. And is this business functionality is the, is the business requirement of this separate from the profile service business requirement? No. So what should ideally happen then is that this should be a component of the profile service. You can make a library out of this. You can put it in the uterus package. That's a separate thing. It shouldn't be separate from this service though. Okay. The code base should not be separate. So that's the reason why this should just be a part of profiles. So that's the second point, condensed business responsibilities to a single place. Okay. Don't break it down just because your engineering will get much simpler, uh, really do consider whether you need to separate it further and further. The third important point is that can we afford the infrastructure requirements for building a microservice architecture? The initial infra structure cost is high. The cost of logging, the cost of building a deployment infrastructure of documentation. All of this is really not worth it for a small team because you're essentially sacrificing some features that you could have added during the time you started fixing all the infrastructure issues. Okay? So ideally this is my own hocus-pocus formula, but for a startup really going for a microservice architecture is fine. If the total number of services that you are handling per person is less than or equal to two. So this is for startups. One person is handling less than equal to two, you know, microservices, basically it depends also on the user scale, but for startups, this number is very flexible. As for medium organizations, I would say one person should be handling less than or equal to one service. So ideally you would have two people handling the session, service, two people handling the payment service. And that way you avoid a single point of failure. If someone is absent or, or something happens, you know, they leave the organization, you still have one person who is taking care of that service. So you're not entirely dependent, even as a business on them. And for the large organization, basically two people to four people per service. And the reason I say this is because two people is good. There's no single point of failure, but if it's a large service, you might need multiple people working on different things. One person might be doing a proof of concept. Two people might be on doing the current features, which are required by the product team. And one person might be fixing bugs or making sure that support is being taken care of. So four people for one service is good. More than that, what happens is there's confusion. Like who's doing what this service is too big. Maybe you need to break it down into simpler pieces. I know I gave a lot of talk about the business should be running, whether this is a microservice or not. But the fact is that this is also engineering thing. So if this is getting too big, it's probably because the business requirements are getting too big. And therefore you need to kind of break that service down to separate pieces. So this has been a rather detailed approach of how to move from one. Let's do microservices. If you're having doubts on this, do let me know in the comments below, I have a discord server in which you can come and, you know, post any of your doubts or even your generic doubts that you have. There's different channels for that. I also have a website with a system design video course, which is on interviewready.io. It speaks about these concepts in detail. You can check it out if you are looking to improve at system design. And of course, if you liked this content, then subscribe to the channel, hit the like button and I'll see you the next day. What is system design? System...what? Can get to the next question? Can I get a hint? System design is the design of websites using systems. System design? System Design Is the process of defining components and interfaces with their interactions based on specified requirements. Next question?
Info
Channel: Gaurav Sen
Views: 124,116
Rating: undefined out of 5
Keywords: system design, interview preparation, interviews, software interview, programming, gaurav sen, system design interview, monoliths to microservices, microservices, monolith, microservice, refactoring, refactor
Id: rckfN7xFig0
Channel Id: undefined
Length: 19min 24sec (1164 seconds)
Published: Wed May 26 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.