Distributed .NET Core (DShop) - Episode 6 [Service discovery & Load balancing with Consul + Fabio]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey welcome to the sixth episode of distributed dog mentor course it's Peter and Derek and today we'll focus on the internal HTTP communication which as you might remember is like solve sort of a problem that we mentioned in the last episode where we actually hard-coded our internal communication between the API gateway and the discount service yes and I think that we should start with with problem that we actually yeah we kind of discussed in there in the previous episodes so basically you know in some cases it might be it might be handy and I would say that also necessary to fetch some data from one micro service to another because as you probably remember we don't want to put I would say to large objects on a on the rabbitmq in this particular case mostly due to the performance issues that manicure you need to remember that of course in most scenarios when we were playing with our application in the development environment it seems that everything's work working perfectly but we need to be prepared for more loaded traffic so we should avoid doing you know putting two large objects on a on a RabbitMQ so we try to keep them as small as possible and pass the only information that's actually necessary for the another service to identify that something will not change or was created or whatever so we'll start with the very simple example of doing this and later we will move further to the issue related to this hard-coded data in their app settings so what's the plan for today so within our discount service let's imagine that we would like to have some more sophisticated business logic it comes to creating our discounts for example we would like to maybe analyze the already created or completed orders whatever makes sense to you and you know they you know get this order details this this data and maybe based or whatever it is the customer which might be some VIP or address or whatever this we would like to perform some logic and based on the output we could decide how big the discounts should be right so some sort of like analytics based on orders in order to generate incomes so to make it clear we will not implement any specific domain logic we just want to show you the you know our approach of dealing with larger objects so maybe we should start with the order DT oh yeah or maybe with the event itself oh yeah yeah so here is the order service and as you can see within our order service and we also have these messages and we have a few events here and one of the events is for example the order completed so order completed happens once our order has been completed meaning that it was created there was enough products in stock everything was accepted and you paid for an order given that we actually implemented the payment service but we didn't at least so far so this is when the order computed event happens within this within this handler for complete order handler living inside the order service so it's being published here as you can see and now in our discount service you want to subscribe to this order computed event and based on the order data you would like to maybe store it in our database and then you know perform some analytics and then create a new discounts based on you know this order data but there is an issue as you can see right only two properties nothing else that's what I said try to keep them as small as possible but we need way more data for our advanced calculating algorithm yeah so maybe let's start with with a handler and then we'll get into DT so like the common story here this comes service and then at first I need to define the message so maybe let's do it here events messages events and then order completed and I can just copy and paste this one so let's make it like this and here it comes I need to remember about this namespace which is part of our routine key in RabbitMQ so I just say our message namespace is orders because it comes from the order service and that's pretty much it now I can take this type name and create a new handler let's make a subdirectory here called orders and new class called order completed handler which will implement our I even Handler and pretty much the same story as before order completed event implement the members make it a sink and here there will be some business logic let's make it just completed that's all for now and yeah here we like to fetch our order data store in our database and then later on when for example we invoked this great discount handler or some other some other process we want to take these orders into consideration when we are creating the discount maybe in some automated way that's this narrative our end result one more thing we need to subscribe to this message oh yeah correct so let's put it here subscribe event order completed yeah that's pretty much it now the question is how we can get this order data and again just like we did recently previous previously within our API we could define maybe rest is or HTTP client and then just call our our order service to get the data but but they don't hard-code first thing is I think that we should actually ah show the way how we actually how we can actually get this data because yeah now we get to the point when we're we have this even handler defined in the discount service we have the code we have this event order completed which gives us an idea of the newly created event so we have necessary data for fetching this and of course the whole you know writes to the application is done fully synchronously but in this case we don't want to involve RabbitMQ and use rabbitmq to fetch this additional data for this counts micro service instead we want to synchronously ask for this for this data and we'll simply use the API for this but it will be not the API gateway which is exposed and published for the end-user but simply we will do we will use the same internal API as we do for the for the queries so if we go to the orders and you see there is other controller so this is basically the internal controller of this particular micro service as and as you see we have this orders - order ID which gives you an action result with the order details DTO that this you know what would give an ID this gives you a data about the customer itself who actually completed the order or maybe who actually owns this order and a collection of the order items that are the part of this order so this is basically the way we want to fetch this data using simply internal API and now we get to this issue that Peter mentioned yeah so let's start with actually defining our order details here so within our disk on service we want to have either the same object or the project with maybe less properties because as you might remember since we are using JSON for internal communication and it's pretty flexible mechanisms for visualization a sterilization of data we can omit some fields so at first let's define our internal DTO so just like we did for our customer dt or for discount details video which is our internal video we can do the same for order and I could say let's let's create a new class and name it maybe order details here and we can choose we can pick the fields that we are interested in or sorted properties so if you get back into our order details each year in our other service which is here let's go into the base class so I could for example copy all these fields or maybe just subsets of these fields and let's put it back into our order details here so there could be ID that could be customer ID items called account total amount and so on and so on but let's say do you want to have more properties so maybe we are interested in customer or maybe you are also interested in a certain and so on in the order items so maybe let's try to do the full the like the one to one Mueller copy and or is here okay so I can take a look what is my customer do ok so this is the property and again I can take this class and I can just define the same class on my own here or I could reuse this class that I have here you know so it's really now it's really up to you or maybe we can simply get rid of this customer maybe we don't need this yeah all right we can go read this guy right yeah let's say that we let's say they'll because we have customer internally we can just maybe use only D this customer ID to get the customer which is store in general in our database and maybe let's focus on these order items ETO so let's take a look at order items here there is the DTO let's create a new class here and let's do the same so let's copy this one here okay and finally if we take a look at our details or details definition which is here here is the collection of our order items so that's pretty much that's pretty much it here is our detail that will be that will be fetched from the internal internal API of the order service and yeah now the original question how do we actually get this data here so what we could do we could use recipes and we could again hard code this configuration or reproduce httpclient and hard to the configuration again but we don't want to use it why yeah yeah the issue of course is that you know the hard coded even though that this is extracted to the to the app settings and you can override this on your on your clouds or your servers private service whatever you you're actually using this there is still this this still issue that first we since we're humans and we are we tend to do mistakes we can simply do some small typos and you will have some issues with the connection to the to the remote micro service to the other micro service and of course it's kind of annoying when you have like you know this is you need to remember that this is very small application and it already have like nine micro services in the more I would say Enterprise scenario you would end up with 50 or 60 micro services and doing this manual configuration for all of them both for the production and for the development will be kind of knowing and you would be very careful when it comes to putting these settings and of course when you will migrate from one environment to another maybe you would migrate to cloud you still need to change the settings and we want to avoid this we want to since we are at least I am very lazy developer and to me the best solution is the one that actually involves me at least then if something can be done automatically by the micro service not by me at the end this is probably the best solution so we want to basically do the following thing we want to put this responsibility of of registering the data to to the micro services themselves so once we start micro service we want to we want make it to want to make the you know the display circular micro service to register somehow to something that we'll discuss in a minute saying that okay I'm up and running and this is this is the URL that actually that actually works and you can use this to communicate with me of course we are talking about the hosts about the DNS or on the host part of the URL that we are actually using so in this case could be like localhost or something yeah so as you can see this is how we could do it pretty easily you could inject here I should be client or HTTP client factory and then you know just call make an internal call given that you know where yourself is latest weather is local host some IP or some TNS get the data up based on its internal API you know just read it onto the string and this otherwise it and yeah the data that way yes this is the level one of doing the configuration so this is the hard-coded way and this is the worst way why because in order to change the the address of the of the host part of this URL you need to actually recompile your application you are not you cannot do this I don't think we can do this in another way you simply need to change the source code then we compile and deploy to your to your cloud or you know production environment whatever and the step two is we actually did so extracting these settings to app settings dubbed a song' file so we can override this without recompiling the whole application so this is what we did and it's of course way better than hard-coded values hard-coded values are in 99% bad yeah and so yeah this is the level 1 and we want to we want to move it to the another level so level 2 which is Service registration elbow or I would say automatic automatic on service registration and for this particular case we will use console yes so maybe let's go back to the last slide so basically we'll use things called console or the tool called console and this is one of the great tools which is open source and free tools created by the Hashi curve and they have a lot of other cool tools we will use at least one original tool sorry default and yeah devote for sure and maybe something else we'll see but this is great they have very cool tools and maybe let's quickly you know you can you can talk about console since you might decide so yeah this is this is the console which is a service registration yeah centralized it is right yep so basically what we are going to do is we'll have of course this each micro services each of the micro service will actually register to the console so as you see when we will actually in a startup we'll add some some logic that says that whenever our micro service is sorry app we want to call console and register our micro service with the particular data so as I said on your on your development environment it could be like okay hello console i'm service a and this is my URL so this is the log I'm running on localhost and I'm running on the port 5,000 won and I'm using HTTP not HTTP because I'm running on the development so if and this is my name let's say in this case it will be like service a so we have this key like service a so using this key will be able to get this particular data and necessary for calling the service area and of course the same story happens to every micro service that actually registers to console so then when we will hit let's say the API and we would like to fetch some data from there from the service a we won't use the article the data saying like we will call localhost five times five thousand one and then the end end point instead we will call console saying hey we need to fetch the data from the service a this is the key so in this case this is once again service a and console will return the instances that actually register as a service a with this data are necessary for connecting so that Bay later we will use the data returned by the console to actually build the host part and then to attach the endpoint and make the HTTP request there is one we think are all right because the last step would be to actually get this data we know what our service list and then we ask the service for the data and the important thing here is that if you have one instance then maybe doesn't matter but if you have more than one instance which is all about micro service as well and you want to scale your up horizontally by adding more instances which makes it more resilient more responsive and so on then this key which is called name in a console you treat like a group so for example you will have here service a and it can have one or ten or hundred instances and your your API while calling the service a it will get the list of these services and it can pick one of the services on the list and ask is for the data and I think the important thing to mention here is that the console works in a sort of random randomized way so if you take a look at this documentation of the console you can see here as I described that whenever your application calls the console registry for the DNS it will receive this randomized run Robley response right so in a console you will have a list of the instances that are up and running they're available for example to you know to process your code and you will get the rent randomize list of these instances so you can for example just call first or FERS of the first of default using link and you know just hit the service to get a data that's by default how that console works okay so maybe let's let's write the code for console so this was another one and so level zero or first step and a second step and now we are getting into this more automated like the better step I would say where the responsibility of keeping track of living services and you know their their internal communication s or the like the their configuration their IP addresses and so on is not like a concern of our micro service is the concern of the service registry so at first let's start the console and here you can find in this dish up compost at the file that can start the console and will I we made this docker compose file to also store the vault will talk about vault which is the centralized credential storage in one of the later episodes but you can start this one and just use console without a vault so just type doctor compost and as you can see we can do - F dr. compost console vault and maybe let's start it with off without - D in a yeah so we have Reddy's and a rabbit upper running which is our infrastructure and we can just run this console volt I need to put the right and the up ok so it should start our console and volt and the console will be available under this 8500 URLs 8500 and here's our console and you can see there's only single living instance there's a console in itself I can click in the console as you can see if I were to actually create a high availability console cluster I could see there you know this different disease and you know multiple instances of console but if I take a look at this note it's only the single instance of my console which is enough for this development mode so that's where I would send my services under this under this particular name so here is the IP address the port some ID and the name itself and now let's try to register our App into the console and there is a doublet corroboree for integrating of console and as you might imagine we also made this easier and we added our own code to make this integration easier so getting back to our startup class we can do the following at first I need to register all of the interfaces within our iOS container so I could just type anywhere here something like builder and add console is it right also or maybe those services let's meet oh there was it was already here no sorry it's order service should be startup disk on service ok so here I can I can tie for example services and add console rack this and if you take a look again extension method that just registers here some classes some options that we bound from our up settings and so on and so on so here is our IOC part and now the more interesting stuff which is actually making use of console so anywhere in mind configure I can just say up use console and just keep in mind console is not a middleware really so we just tend to use this convention abuse but like with rabbitmq but it's not really the middleware so the order doesn't really matter here so I can type use console like this and basically if I start on my application then it would register to the console given that I actually set up sorry and not this one and that I defined my application settings for a console here which we'll do in a minute but there is one very important console about console because once you register to your console it need to keep you know to keep track it needs to keep track of your actual instance right so whether you are available or not so what would happen if my if my application went down right what what will happen now it would be still visible here and it will be a dead instance so we can do two things in order to you know prevent this from happening and the first thing that we can do is to actually I don't know if it's a valid word but this does the name of the method to the register ourselves to remove ourselves once our application you know becomes offline just so that it so it will be removed from this service and registry it will be no longer visible here here as an available instance so as you can see in this use console which is of course and another extension method and here we have this very simple strategy yeah it's here unique ID and we just made this simple interface called a service ID and by default it will return your application ID as a new GUI but you can provide Ana strategy here as you want maybe part name of your machine MAC address whatever it is so all create a new ID unique ID for our console so for our micro service instance that we registered in a console using this simple strategy and my use console as invocation will return this ID as you can see below it will just return this service ID which is this unique ID being good and I can type the following service ID yes just to make it clear because maybe this is kind of confusing so as as we told that the name itself is used for the grouping yeah yeah or this could be a key but assuming that you have only one instance up and running and connected to the console because then you can simply use the name as a key in this case and you would only get one instance back from there from the console registry but now assuming that we'll have and this is probably what we'll tend to do so assuming that we'll have more than one instance for one particular micro-service we need to kind of distinguish between them so since each microservice will have the same name because for instance this will be the discount service we need to distinguish between the instances so for this case we will need additional parameter and this is the service ID so basically as Phelps said in this implement using this implementation this will simply create new GUI for each instance so then you would simply receive like if you would ask for discount service and this will be the grouping key let's say this will return you all instances let's say ten instances and each of them would have a different good for this service ID yeah and absolutely sorry for the mistake is actually service name and ID but you get the idea I did unique name is the group which is common for this like the family of the particular micro service okay and now the question is how I can how can I register myself and just yeah if you don't know how to do something you can for example look into other services and you can see here we have this I console client which actually comes from this library so we are using the dublin core library for the console and here leaves this icon so client which is actually part of this library and by using this icon some client we can talk to our console console API because console has other tools created by a hash table has internalized so you could basically you know type in yours in the console Xilai and you know perform all these registrations the registrations and so on so here I could inject my eye console client clients and then just like we did before for our container dispose we can say console client dot agent and now we have this method called service the register which takes our service ID which is this one so if our application becomes offline it will it will remove itself from the console right so this is the whole magic and yeah that's that's pretty much it that's clear yeah so now let's let's try to start it but before we do it we need to you know configure our our console for the service so we need to add the proper section for the settings so let's just copy PI's we have this section called console and here let's copy it from the other service out let's copy this whole stuff we'll get into details later on so the important part for now is is this one enabled I will make it true and you are of the console which is DoCoMo's 8 8500 name of my service which is the name which will be group of the service I'll call this con service and for now let's let's keep it like this let's let's make it local so now we'll get into this later on and our port will be five thousand ten but this is also for the next next case so let's try to start our app now and see if it will work so we'll get into our service let's see we can open our disk on service and start it and decided silence all right so it's a parodic let's see if i refresh my console UI you can see that it's here right so it registers itself under this count service which is the name which is this group and here as you can see there is the address local host and five thousand ten there is and here's the unique ID right so this is the this is already discount service and this random good and I can get here and I can see that it's alive and now if I get back here and if I kill my app just control C which is a graceful shutdown let's refresh it and it's gone okay so is no longer here is the longer available which is fine but there is one issue with this right which is which will not always work which will not always work because sometimes the Grateful shut the graceful shutdown might not be an option your app might just die and it will never get into this point right into this one yeah so we can resolve this and we can do it by built-in health checks that are part of the console as well so again if you take a look into this exception method you can see here that within this registration you can also provide we have this flag here called pink enabled which is actually health check and I can register this agent service check given the integral let's say 5 seconds 10 seconds 1 second whatever makes sense to you and here I can say every for example every 10 seconds I want to pimp my API under this specific URL the pink endpoint which can be slash pink maybe or slash healthy or you can use I subpoena store health checks whatever and if it doesn't respond if my endpoint doesn't respond for for example 5 seconds it means that there is something wrong with my up and I should remove it ok so I will just remove it from from console and and I'm not quite sure but I think that for castle it's a for for the checking this this health checks this is doesn't matter whether this app will actually return successful status code I think yeah I think doesn't matter yeah so if this if you try to think something that is actually protected and we did would return the 401 for free I think that with this would still work because for council this is clearly sign that your api is up and running but I'm not quite sure it could be it could be okay and I can just say pink unable to true but there is one cut here and the catch is this address now remember that we are running our console through the docker right and for the docker fiend called localhost is actually the the console if is the local host on its own right it doesn't know what is the local host unless you unless you use for example the doctor only Docs and you bar and you started with this host host parameter that will bind this this doctor address into your localhost then it will work but if you are using Windows or Mac you can do the following I can type host doctor internal and select this and then it will be able to you know just go my make my service by resolving this this URL this DNS and calling my port five thousand ten this is the only thing but remember if if you actually deploy your app somewhere and use some service may be like kubernetes and so on then it's really not an issue because you would use some namespace maybe for your external bus or some kubernetes namespace but for this scenario if you are running in the local house and we are using docker here in the keep in mind that otherwise it will not be it will not be able to talk to your service internally okay experience with the docker then you should you should know this yeah but there's always this diskette this tricky thing if you're running it on Linux Mac or Windows they are different a different URL so you have to keep it in mind so let's run our service once again and we should be able to see now to like two checks that will be performed for our service okay so let's refresh and it should be green in a moment so let's see right now it says discount service failed but should be should be working in a moment once the pink pink is ready at least work before so let's see services okay discount service oh let me check if I actually have my pink endpoint available because it might not be available which would make sense yeah so my pink my hip my pink endpoint is not defined as I can see so this is why this is working so I think you need to I need to define it let me just quickly check what was the name because we have so many extensions that sometimes we we get lost so let's see where was our pink and points I think we need to use this service ID let's see this one no this is just the ID it's not this one or it was authentication let me just check if what's the name of this Miller let's see if I can okay yeah I don't remember what was it actually start let's see oh but it's so as you can see the council's trying to pink our our our endpoint but it's not available I think it could be the part of the app metrics actually so let's let's try to make it yeah let's make it just implement this in the you know yeah I think I think it was I think it's part of the up metric so maybe let's just look like this let us make it simpler just make a console call our API without maybe a nice place ed Boyd maybe we can change this to pink as it was and simply add the that method in the control that will do nothing and we could oh yeah okay we can also do it make sense that way we could we could put the breakpoint there and show you that this actually Pink's this something happens okay it makes sense yeah I think I'm pretty sure that it was part of the app metrics library which is okay use here so this is why I didn't work but it's good to know all right let's make it an HTTP GET so yeah it was finally the failure that we are you waiting for okay let me kill the service let's see if it's actually removed okay cool it was removed so let's run it once again and here is the pink should work now I hope it's running to discounts okay just yeah the first time you run the app it always takes some time ok so it should be back here and now as you can see yeah here is the pink and let's see our console it should be green in a moment so it's hitting the pink again and again and again and let's get back here and it's yeah finally it's green so if I go into this service details you can see that there will be two checks one is this this first check when you register the app and here is the dealing help the pink below so it's pinging every few seconds and if the pink doesn't if the pink Bull would fail then it will the register remove the instance of the service and this is how you deal with it okay yeah we just remember to remove it when we start using the matrix title because otherwise there'll be another failure okay so this is how we can how the console works in under the hood now the question is how we can use console in order to talk to our our service so each hour each of the app settings has this console defined so we could simply make this you know just say it's available for the other services as well and then the services will be visible here right off in our console so right now whenever I want to make a call I will not be calling local cause whatever it is and I will just call this come service order service slash API and you know get the data that I'm interested in so for starters I think we can use our console HTTP client so I could inject it here so I just inject my console HTTP client and this is not the part of the console library so yeah so this is something that lives in the reaping the common package yeah so it's very simple to be like under hood it's a it is HTTP client so it's try to it will try to get the data from the request URI and but there is one why one important thing here if you take a look here at extensions it registers HTP client using this interface and it also defines this message handler so this is where all of the magic happens within this message header which is been more complicated so in this message handler I had this interface called icons for service registry which is very very actually simple so in this service I'm just calling get a sink and I'm just calling here scan as you can see I'm using this eye console client and I'm invoking these services so it will return all of these services that are available and then I can you know either just do first or default because it's randomized at least or I can do my very naive all own implementation of this random random here so whatever actually makes sense to me but this is where maybe we can just create this make the use of this a console client and we'll simply make a call and and discuss each step will be much easier okay yeah so yeah this is where but this is where this magic happens in this message render this is where we talk to console and you know just grab the instances so maybe what put a brakeman here as well yeah okay and let's get back into our but before we do it we'll need to start all the services right because we have to go through this order completed scenario which will which can be or you can simply if you you have some order already created you could no I I don't have yeah I have empty database unfortunately so yeah but okay let's give the try it so I will inject it here and then I can say just this DTO equals my console h-2b client and get a sink I want to get the order details ETL and I will call the order service and its internal API which is this one like this and yeah and there will be my order detail below so it's do it maybe so let's put a breakpoint here and here yeah but before we started we need to we need to go for this scenario so and you also yep need to enable regeneration on the oh that's correct so yeah let's add this registration for the other service no we don't need the other services yeah exactly and yeah we can also enable the pin here 5005 okay but we need to start quite a few services so let's go I must say I really enjoyed this this episode because this is the first time that actually something more advanced happens so yeah we'll see if you feed buddies and you already good sign yeah so at first we'll get into will start the API and we have to start off pretty much all the services I think I think also including the operation service so identity because for the order completed we have some break yeah because we also have some distributed logic for the error completed event so all right so API identity customers discounts and orders ok customers and products as well because we have no products yeah and then the operations and then the orders and then the discounts so I think that from the next episode we actually need to start using this dotnet run all this will be yeah but I just agree mile radius yeah that there is quite a few things to to start and finally bigger and bigger so let's see API customers identity products operations orders and there will be the discounts finally so let's see okay let's open it operations yeah we need for completed for the completed order event because there is some logic alright so here is our order service operations here actually it seems that it had the clones live but this is what matters other service for now and finally we can start our our disken service so let's just put a bit okay we have break point here so let's run it I hope it will it will succeed okay so we need to go for this for this flow so if I open my dish abreast and since I have no data at all as you can see in my database is empty there's nothing here we need to start from the very beginning at first I will create an admin ok I think it should make a request see ya field I'm not sure let's see I think it did oh yeah first oh it didn't start it okay so here's the here is the user and there is the sign-in so here is the token for our admin and now let's create a new product so I'll paste a token here and let's create a new product ok so it should have the product and we can actually call almost a thousand such products and there sorry there should be a products with one product in a moment at least now you type the wrong URL no that's ok ok alright so we haven't seen the product now I can get back here and let's create a new customer so then I will sign up as a customer yeah sign in there is an e missing so e and this one and now create a customer all right so let's let's take a look it will have the customer data in our Diskin service okay so for so far everything seems to be okay and we should also have the products within our not we don't need we don't need to have it here so I think it looks good so far let's try to create a new new order so at first I need to add an products and a product to my item so I can call this discounts product service grab the ID and I can put it either here into my variable or just paste it here it will be faster this way so let's send a request to my cart let's see what happens so I can grab my card by tolling the get card see okay here is my card with a single single product and now I can finally call post orders create a new order alright so there should be a new order let's see refresh there is any order and the final step I will get this order ID which is this one and I will try to complete an order which should produce our event so let's just paste it here and make a call to orders complete and now let's see let's wait it should produce the event at least after a while let's see if if it works at all it's completed somehow somehow we didn't get this event the question is did actually I think that we didn't start it or no I saw I started so the question is why we didn't get this data right let's see I think I know where the issues I think the issue is yeah I'm pretty sure what the issue is so let's get into our extensions for the console yeah and I think the issue is here because here I just heard the console client has interface but I adjusted is as yeah but right but I remember one thing about this one I remember that when I tried to inject my console players interface I got some somehow it couldn't couldn't be resolved by D by D container I don't know why so let's just do this quick fix for now let's just try to do it like like this as a class because yeah like I said I'm pretty sure that I had some issue with this registration here and I couldn't in I couldn't inject this interface so let's just do it like this and it should work I'm pretty sure that there was a reason because it it works just fine if you do it at least behind interface class but for some weird reason I couldn't get this to work so we should start with the you should solve the SUBSCRIBE event extension yeah yeah but hopefully this will no I'm certain this this will this work okay so I can hit my complete order now and it should work just fine so here is my order ID and that's it this is how you make longer videos in the YouTube aren't you yeah simply make it back in the struggle with this for did I change it but did I change it back to the class or didn't I oh here here we are now sorry we are here yeah we hit it okay cool we are in the handler I think so yeah it is and we should actually hit our endpoint where is it order completed which leaves this and this goes which is here okay five we are yes we are here so we have Annalee typical dependency injection issues with the registration yeah so ordered is here and yeah let's get into our work on so she be client so we can get into this class and let's put a breakpoint maybe somewhere here and so before we did it it actually called our message handler so those here before then it's called this cell residue ticket the get the leads of instances and finally f5 it should get the data itself so let's wait I see the fact let's take a look at our phobia order service should be here it's here how's the colonel 505 I think I know what the issue might be isn't it that we are actually trying to call because it registered itself under these and under this docker URL and right now our service got this docker docker URL and is trying to call this one instead of the localhost oh yeah so there's there's this there is this mismatch I guess okay okay yeah so basically right now the services yeah I mean the micro service is not the council itself are running simply using Dublin CLI does not put inside the docker containers and we had this whole Joker internal for DNS for actually yeah yeah so yeah and this is something that you need to keep in mind when you're trying to develop everything locally while using the docker so right now we set to our console that we are able then it can reach us under this URL which is valid for docker but if we try to get this from our you know from our discount service it will not work right because this is void for doctor but I think could we use this docker for Mac localhost here I'm not sure if it's going to work or not mmm so maybe let's let's try to do it like this with all the pink just to make sure it works but I think maybe this magic URL could also work here doctor for Mac local I think that this should work okay yeah we can we can just leave it as yeah let's just try to just I will co-host without I without the pink yeah so as you can see quite a few obstacles yeah so to make it clear for pink enabled we kind of had to do this because council is running in the darker container and for for Castle itself the local host is lives within this container and our micro services run as as a simple dotnet dozen instances in without the docker are beyond its its scope so we use this magic docker host internal for for the council to be to allow him to actually pink our service but if we will disable this we can simply get back to the local host to actually make it work without the darker so services will be available under local host and then some support instead of this weird docker host internal exactly so let's see if in this final third try yeah but I think this this magic URL for the for this doctor for Mac localhost should also work so we can try it later on all right so final final one create a new order and I thought I would say that this is what happens when you actually make you have some mix so some services are running on the docker some are not this is typical thing yeah okay so here are getting into our message Handler and let's see I will click f5 right so it takes our it's a registry and now let's put a breakpoint here into the send I think I see will happen here f5 now we are getting here again and let's it will try to get our UI so as you can see there is this order service so what will happen let's get into this get URI and let's put it to the back one here it will try to resolve this based on a service name so it'll get the service name and let's see our service name is the order service as you can see yeah and next step son I think so if you get here you can see that we are using poly here or the retry so we'll try for example to send it three times so Polly endure yeah but yeah but this is just to salute not scared about this and this method and finally get request URI async okay so let's put a breakpoint here and here and here so here we will try to call ourselves registry so again let's let's dive deeper and put a breakpoint here and here so it will call our agent to get all the services and we'll look for the services let's see we got the one service for this type so as you can see is lives on the local house it's order service ID and this is under the service group told order service okay let's put the five and finally we have a new URI which is translated into our localhost and now we can finally get our data all right so here is the response JSON convert and there is our DT oh wow that was yeah okay again so I think that we should sum up what actually happened once again just to be clear so basically we completed an order and and an event quarter completed was published and was then caught by discount service inside and then of course processed by the event handler that we that we created in this episode so then we use this console HTTP client for forgetting the auto DT off from the order service so we use this order service as a as a host part which was used as a key for the console using this order service key we got the list of the instances for this particular case we got just one instance and within this within this instance we gods necessary metadata so we got we got the local host and part with the port so we got the local host and the 5005 for something yeah I believe yeah so we use this data to actually construct the host part of the URL and the rest was of course the same so there was the orders and - ID so council provided this expected this key received and returned the list of the of the services and of course that was if you want to see how this is actually implemented because this might look scary the whole mechanism is pretty simple but just we encourage you to visit the our github and go to the to the common part and there is there is a whole section inside this common package dedicated to the to the console itself yeah I can go and see how this is actually implemented so it might look scary about this it's it's not yeah and let me destroy one last thing and so as I mentioned at least for the local development of docker if you are using Windows you can put here win if you are using a Mac you can use your Mac and there's this magic URL docker for Mac or local for winoker house and if I type into my browser I can access my local host sort of through dr. right so I can just do doctor from Agra host 5000 and here's my API so let's try to put it here that's our address part and let's do it for this con service and let's do it for older service and I'll just see if it will actually work with pinks and it will work with our service registry okay this last thing that we because we need pinks for the for the next next feature anyways so just quick restart the order service and restarted these conservatives and see if it works so there's this magic URL that you can use if you are using docker on your Mac or Windows and if you're running on the linux you can simply type localhost here just localhost but then you just need to start with Sarah doctor of this attribute which means which is - - net equals host which will bind your doctor into your localhost okay so let's start it once again here's the order service so discount service and as you can see there was some message in the hue that wasn't it was in process before so let's go again already you know and let's try to get our URI and it should now use this docker for Mac localhost internal address so let's do f5 f5 again and service name and let's see it should get the services again okay here is the services this is our doctor for my local host yeah yeah one instance and let's see if it will work it should work just fine five oh my god I think it was another another and another event it wasn't processed before there were a few events so as you can see even if our app is down for some time once you start it once again there will be messages waiting for it in the in a queue where was it think it was should be it was processed somehow not sure if I have a breakpoint here the last one okay geez I finna remove this why it's still there yeah just do it like this which would be much faster sorry not an empty cart chart get post and finally oh so many five and finally my complete order which is here so last order Aaron let's send a request okay and device there is some issue huh okay so as you can see it's trying to get the data let's see if it's there now it works is here which looks fine so it it was able to fetch data sending request but somehow it seems like somehow our endpoint didn't hit it I didn't hit this this breakpoint sorry we didn't hit this endpoint somehow but as you can see it actually sent the request to this URL which is about because I cannot put it in my browser which is here right so yeah somehow we didn't hit the breakpoint and well yeah there is some somehow we didn't hit it I'm not sure why device it'll figure circle exception yeah but again it's sending the sending of the messages but somehow it it couldn't get the data we'll probably have to debug it but anyways this is how we can how can use this magic URL to get it okay so the last thing that we can use right like a level free I think yeah so basically because this looks like like a kind of complete solution for us because if you think about this we have this we have this registry that we can simply query for the particular instances of the of the certain you know certain key and actually the console itself is something that we call the server service discovery right so basically the server itself so in this case the castle is responsible for giving this for giving as the instances of the particular service and this randomized using this I mean it load balances this traffic using this randomized round-robin but we can go one step further and actually involved another tool for load balancing so yeah as you see this is also suggested in the in the Hashi curve documentation so we can use the fabula and the fabula itself is it's a I think that was created for the EBA and yes it's good yeah it's got open source open source so basically this is a very simple load balancer that actually creates the routing table and it integrates very easily with with the council so maybe we can get back to the slides to actually all right you have to see how this is how it's working because this is quite simple quite simple mechanism itself yeah so one yeah let maybe let's get to the actual side this is like the wool fiber is right yeah and here's how it works yeah so basically the fabula is this is the one with this blue yeah this is the fabula so basically what it's what it does it's as you see we start with the typical console registration so in this case we have this service a that actually registers as a service I of course with this additional service ID and we say that we want to register ourselves as the localhost 5002 but also we have we can provide to the console some custom headers and this headers will be used as further for the integration so we will say that our service a supports this two paths so if we will send a request under API slash values or API slash users or whatever actually you have in your particular micro service then you can that this is these two paths are the one that we actually can handle somehow so then console sends this to the fabula maybe fabula is this from there from the console so it creates this routing table saying that whenever we have some request that goes to API values we can forward this to the localhost 5002 so to the service a because it's claimed that this actually it can handle this somehow and the same goes to the api - users so this can also be forwarded to localhost 5002 so then if we will do an API call we will always do API call to the fabula so as as our load balancer so Fabio is available under nine nine nine nine yes I think correct so fear I would say that technically we could we could hard code this because this will never never change so will actually do something like localhost then 9999 - API does users and then fab using this routing table would say okay so you want to fetch some data from the API - users I have some service that actually subscribed with with this endpoint and this is the localhost 5,000 - so then fabio would simply forward this to 5,000 to - api those users - to make this HTTP request and then get the response and forward this to the to the color so basically this is how fabio integrates with the console it's a very simple mechanism and you will see in just a minutes how this actually loops and one more thing I think that we should say about these strategies in the fabula so by default this the Fabia you have this yeah it's it's open here yeah so basically by default fabio uses this random distribution and as you see in in the docs as far as we understand this this simply creates a seat for the random using this millisecond microsecond fraction of the request time and by doing this we can actually resolve the the next instance that will actually that will actually hit within the same and within the same key but of course we can change this providing the proper environment variable and we can change this to the round robin distribution yeah which is also pretty simple yeah yeah so but it's still better alright we can I'm not sure if it's better or not I think yeah we all have to take a look which one is better just keep in mind that it's not very sophisticated and both are very simple load balancing mechanism if you want something more yeah maybe more subscale it you can look for another tools like one of the newer tools it's called traffic and for example with traffic what you can achieve is this way they'd run rabbit or dynamic round-robin and there are also other you know little balancers that you know take her take a difficult consideration things like latency so they measure the you know the latency of the request and based on this latency they they will return to you the list of instances this has the best latency and so and so on so there are different load branching strategies and for the fab you have these two strategies which are quite quite simple but sometimes it might be enough really depends what you want to do okay so let's get started and and again we can start the fabula for our daughter so if you take a look at this compose here is the single compose fire for for the fabula and here is this awesome engine so by using this phablet proxy strategy and environment variable I can either say error or Rd by the Folies Rd as far as I know and the other important thing is to not notice that we need to be in the same network if you are using the docker we need to be in the same network where our and where our console lives because it's using the console right to to work to create its routing table and to get this into instances okay so as you can see do expose to ports so let's let's run let's start the failure and one is for the load balancer and the nine-eight is for the UI so here we'll actually see this routing table yeah in action and maybe let's just kill everything and okay so here is our console and now I can do the same for Fabio Fabio and here is the docker compose therapy Fabio and let's make it up it will start quickly and our can access the localhost nine nine nine eight where you can see the routing table and for now there is no register there is no services research yeah okay so let's try let's take a look for example we take a look at our order service which is here here is this registration for the console and here is the registration for the Fabio so I can type enabled true right and let's try to actually start start a Fabio service so I start the order service and see if it works with Fabio so let me just restart it yep okay so I should be able to refresh this now and I should see there is a routing table for my older service hopefully let's see okay here is my routing table for order service so what I can do now I can do something like localhost and remember nine nine nine eight is for this to simply Y and I can do localhost nine nine nine nine and then based on my service name which is the tag so as you can see here there is my service name the detox is that using the prefix I can do slash order service and let's see I will get the response from my order service it's crazy and I can do something like slash orders and it will return to me the list of orders which would also require to pass the customer ID in order to get the orders for the particular customer so you can see I can I could pretty much use the HTTP client and just make it make a base URL to hit the fabula at all times and just use this URL because fabio will will be aware of our instances and based on this service name which is which is this part it will just redirect traffic to this particular instance based on this simple a load branching strategy can you go to also to the console because I think that the console actually shows that's correct custom header let's see so yeah there is Thursday head alluded to use this you are this URL prefix and then Dennis trip so if you were wondering where does it came from again extensions for our fabula floor for our console because it's also here and down below we have this we have this Fabio track which is here get Fabio tags and I'm just i just use my my service name and that's it and I just create this prefix here so I have these Fabio talks and alright as you can see I use it here so if I said that my fabulous and able in my app settings I can just oh it will just have these tags and register it into my console and then the fabulo create a routing table and I can hit my Fabian order to get the data so right now I could just do this and in my for example order computer handler if you get back into our discount service which is there which is here I could pretty much do this one and and then just change it to localhost 9999 and make it like orders - service slash orders and it's all I don't need to use this aged consulship client I can do a very simple interface for Mary let's say fabulous TP client and that has you know hard-coded page where of the fabula or the URL that is taken from app settings and that's it that's how we can make our life even simpler yes that's the whole magic and last step the rest is right yes yes because of course we can as you see we kinda have three ways of configuring this HTTP client for us because we can either use the the thing that we did in the last episode so we can use just the rest is for doing the simple HTTP calls or we can use we can involve the council as hours service service discovery and the last option is using the fabula wave the council to to have this council and allowed busing provided by the by the fabio so of course this is yeah this is the stuff that that we you actually need to program some house so we put this into one extension so changing just one flag and of course assuming the new actually enabled the fabula and the console on each particular microservice is yeah so basically to the strategy is dependent on just one flag so if you go to the API I believe yeah let's let's make it into our API gateway right so here right they pack gateway yeah and remember yeah something we don't we don't need to enable the fabula Fores or we don't to enable the constant 4k api gateway because api great we only need to know maybe about Fabio right yeah so it can be it can be disabled here and that that is simply because none of the services actually calls the API gateway yeah is that simply called the directly the micro services itself so but if you go to these recipes as you see this is the we have this load balancer parameter and if you will leave this as it is so the just empty string we will use the first strategy so we'll simply use the data hard-coded into app settings so this is what we actually did in the previous episode if you will you will change this to console this will actually use this HTTP console client for fetching the services from the registry and then we will use the data from the registry to actually build this host part and you just need the name right you just need a name because this will be skipped because it wouldn't make sense otherwise it will just take a look into the name of the service yes yes the whole scheme and the port is not necessary because we will get this data from the console itself so this is the second option and the first strategy also involves the fabio in this process and will simply forward the all requests to Fabio and Fabio Bay based on the routing table will decide using the round robin or the random of course this depends on the configuration but this will forward this request to the particular instance of the particular type of the service so yeah I think this key so if you take a look into the extensions for recipes you can see that you have this simple switch for like nolan bastard and Fabio and if I take a look at Fabio you can see that it just creates a new HTTP client for Fabio and it just add this as this message handler for 45 awright so it only cares about two things whether about it cares about the viewer of the fabric itself and about the the the service name so and then it can invoke this send async and this and async method ok yeah so maybe maybe we could create this yeah let's let's try to make it let's try to run it so I set this to be Fabio I can remove this one just to prove that it's not a net let's make it this con service right and what else in my Fabio I have this URL I will also define the service name for my API because I think we added this parameter to be actually we set it to be required so I just let's just put it here besides there is nothing else that we need ok so we'll try to use our we'll try to get our discounts using the fabula I'd so if I get into my distance control you can see here that we are calling the recipes and we are calling this get maybe fight and fight async method for the customer ID so we'll get all the discounts and this is our service and now the race is should get our data for the Fabio right ok so upsetting set and now let's let's only start our disk on service so everything this should be yes provided the configuration for the discount yeah yeah that's the this last step so let's just copy this and into our discount service up settings let's put it maybe here and okay okay let's make let's enable this one URL name will be discount service and you can see we also set this retries but it's topic for the for the one of the next episodes and let's start our discount service on this one because we'll try to get a data for our gateway alright so where was my discount service it's here so let's run this one come on yeah okay let's take a look at our console so she'll be in console and it should be also available in Fabio as you can see there is a there's different service there is this there are these tags and it's open the console sword if I be routing table oh and one more thing when it comes to fabula I'm not quite sure but I think oh and as you see the weight is 100% because we have just one instance of the particular micro service so there is pretty much no to balance yeah if we yeah if you run the two instances there would be there would be two instances available should we give it a try okay let's see so I can easily change my my port so it's going to my properties and maybe let's make it five thousand eleven like this and also make this one but what I want to say is that I think that the fabula itself requires your console to integrate with the health checks yes yes yes if you want to if you want to use the fab you need to have this console configured with the yeah yeah because the Fabio builds this routing table dynamically so all the health checks are really required so let's see if it I started mine disk on service once again on the other port ah one more thing I need to I need to fix the fix the end point for the health text to make it available on this on this one right yeah because it will also ok let's run it once again and we should see there should be two instances of our discoveries okay so the council started being our second instance so let's see here yeah there is four because we have two instances yeah and two objects and let's take a look at Fabio and nice two two instances with two weights and remember you also have the CLI for Fabio and you could you could do some sort of sophisticated load balancing based on weight yes you can define different ways for different services and so on alright so let's just try to get our discount service for the fabulous record just called discounts service and local host nine nine and a nine as basic well did I made a type of here oh I made a discount instead of discounts I think I'm okay yeah okay it works so let's get into our API and just make sure that we have discounts so this cannot discount say so let's just make a quick fix because it's a discount not discounts and let's start our API and it should work so I think I have a PR somewhere here here is compose okay here is the API don't not run right and yeah let's look for a customer ID in the meantime let's see let's refresh my discounts ah we don't have any discounts really but at least we should get a we should get an empty empty response right yeah so let's copy this ID let me just take this go it part okay and what we can do now we can do a local 5,000 sledge discounts all right and I think we need to provide this the customer ID as this parameter yep see if it's running it's my ap alive API alive or not okay this gown customer ID discount yeah right discounts rights discounts discount discounts customer ID it calls this one it should talk to our let's see let's take a look at the logs HTTP discounts customer ID so you can see it's calling this this URL oh I know was there was a mistake register our service the console of this with this typo yeah this like that so let's say we have this we have disciple for the for the discount not discounts so just make it make it proper discounts and also here discounts yeah magic strings so discounts yeah here should be discounts and now everything should be should be fine let me just restart my API and we start my disconcert whatever the instance I just changed the ports to default once and it should work yeah and lemur locks are the source of truth you can see that it actually try to get the valid a valid end point because it got translated for this simple rest is fiber integration but it just hit discount instead of discount okay this counts it seems by the previous service where is its API oh this one yeah so I just killed the previous disc on service we started and it will finally work okay so let's go caucus 5,000 should be a permalink did I actually am too much yep and finally our discounts once again there is my URL okay my service is up and finally it works we've got the empty data because we have no discounts so as you can see this is our discount service and this is our API it hits this endpoint sorry this end point for the Fabio Fabio takes care of this routing table it looks for the available instances and returns the data for you so this is how you can how you can make use of council how can we make it so Fabio and how we can use rest is in order and finally we would like to create a service rest service to communicate with our order service just like we did in a previous episodes for API gateway and communication between API and discount service so here is my here's my discount service and in the mean time I also started all of the services that use console and fabulous so if you open a console now you can see that they are they have been registered here and they are also available as a part of fabulous routing table so simply applied fabula and constantly to true and modify the app settings for each of the of these particular service so the last step new directory let's make it Services okay and now let's create a new interface I order service and we can basically take a look at our order service that is part of the API gateway yeah exactly and we can just take take this definition and just change it to be a details DTO as references and we are good to go so the remaining think we have to finish it we need to do configure the rest is and register the for water so here I can type as again add service service for water resource service order for this order service type and this section will be called order service and finally let's take a look at our app settings for AP gateway here is the section for the rest is here is our fabulous buzzer and now let's just copy and paste this one for example here and pretty much we only need this discount service so we don't need all the services because we'll be using only this 30 order service so we need to do the following and we don't need this whole scheme part because it will be resolved for the for the console or for the fabula depending on the load blast and this is just this is only required when we when you don't have any parameter in the load balancer because this then we use the default HTTP client and we need this yeah and the last step is to update our handler so within our order computed handler we can get rid of this console H to client and let's just inject here our our our I order service and this is going to be our final step we can call it level 3 point 1 or level 4 simply ordered 0 equals await order service get a sink and we'll provide here our order ID from the events now let's let's start our discount service in a debug mode hopefully for the last time and see what happens also remember that the discount service we need to enable console here and we also need to enable failure yeah and once it starts it should be part of this routing table as well so let's wait yeah and while it's a while starting let's see if my card is empty okay so the card should be empty oh it's not empty okay I have some remaining items here so it doesn't really matter and let's see if I have already completed all of my orders or under some orders debts are not completed yet so okay of them are completed I have two items on my cart and I should be able to create a new order computing order and this order cell service should be resolved and we should hit this pay phone here so let's see okay it's part of our fabula it's part of our console as well so everything seems to be up and running and now the final final step let's post to the orders endpoints which is always here we should get a new order I'll get this ID and let's just try to compute an order okay send a request and let's wait fingers crossed yeah it works cross yeah it's getting here so our other services resolved now f5 and let's see what happens are we going to get the data yes yes there is there's the data so we have the data here and everything is valid so maybe there's some up because it was quite quite some time this episode yeah what we did during the way yeah so basically we started with with the would have issue we we got so we kinda had to figure it out how to avoid first of all of course we want to avoid hard-coded variables in our source code because if you want some change you need to recompile and redeploy your application and that's that's a bad thing so we started actually in the previous episode from the level one when where we stored our settings in the app settings JSON but this is still not enough for us because we wanted to we wanted the services to be responsible for their registration somewhere so we introduced the console as a server service discovery and the council provided as this ability for services to self registering and using console we were able to get the registry of the particular services depending on the given key or maybe the grouping key whatever we call this but since the console provides very simple load balancing we also introduced the fabula and I was the level 3 and the Fabio creates this dynamic routing table and provides the load balancing using either episode random or round-robin so that was the final I would say the final step for for the infrastructure but we got this additional step so the level 4 or yeah that was level 4 so basically if you'll go to the to the common package you will see in the source code that basically you can create simple interface just for the rest ease and depending on the depending on the parameter that we provide in the load balance parameter in the upsetting JSON beneath the different strategy and different infrastructure will be involved to make this HTTP call so yeah that's pretty much what we did and I think that before we before we finish this episode two things that I wanted to mention first if you'll go to the our forum then there is a topic related to this council and the fabula and that's where you can see that was the some issue but that was also another topic where if you'll go to maybe wasn't glitter or this one I think yeah so you have this free free ways of configuring this this synchronous connection depending on this parameter called load bounds so that's the that's the one thing and the other I I wanted to say is that can you go to my github okay if this if this seems kind you know too much for you I think that I have this repository very simple so this is the default asp.net core app and to my repositories yeah this is console Fabio demo so you'll have three branches on on this repository and as you see step one is hard-coded endpoints step two is the console and then you have the console plus the fab year itself so this is simple asp.net square up with no extension method with just the infrastructure necessary for connecting to fabian console so you can start with this and then move to then move to a common package in a tea shop because maybe this will confuse us because this is quite a lot of code that you need to that you need to analyze and understand actually yeah and also remember about all these fingers ready to talker so for example if you type here just a local house then the pink probably wouldn't work because your doctor doesn't for the for himself I mean for the doctor also local host is its own container so unless you're running on Linux with a special parameter you will not be able to pin your service so you need to either use this hose docker internal or then you need to use this docker for Mac or the confirm window Cal house because otherwise you might get some troubles but again it's mostly for the local local development what once you publish your up somewhere to the cloud maybe or on some VMs then you probably start using here some you know some static IPS or static DNS so it's no longer than issue or you just put your micro services into the docker and then you just start using these these these aliases these services names and then it all works but for surgical deployment when some of your services are local or local some of the services are part of a docker you need to be aware of this these issues yeah and I think that's that's pretty much it yeah right yep I think that the that's the longest episode so far oh it's yeah it's for sure the longest episode so far we're getting yeah we're getting better of course you can expect that in the next ten episodes yeah we'll just sit here for I don't know four hours and so we're gonna be Lord of the Rings yeah except directors get okay so this is and I will see you next time
Info
Channel: DevMentors
Views: 13,767
Rating: undefined out of 5
Keywords: devmentors, dshop, microservices, restease, consul, fabio, load balancer, service discovery, .net core
Id: UWfn8Iml2Kc
Channel Id: undefined
Length: 104min 11sec (6251 seconds)
Published: Sun Jan 13 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.