Microservices Using Spring Boot and Spring Cloud #1

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on guys assalamu alaikum welcome to amigos code and today because you guys have been asking it for so long i decided to record a series on microservices yes microservices if you're into my channel go ahead and literally subscribe and also you'll see that like button just take two seconds and smash it literally just take two seconds and give me a thumbs up and comment down below and let me know what other videos that you want to see but in this video we're going to learn about so hopefully i will get the chance to teach you all of this that you see in here and to be honest this is quite interesting and um yeah so this is what professionals do and hopefully i will try my best to teach you everything in the best manner now what i want to do first is show you how you're going to use for example eureka server and config server but then i will show you as we transition to kubernetes that we literally don't have to have some extra services and we can just focus on what is our own domain which is our own microservices that perform our own business logic in this video i don't want to go too much in depth what a microservice is um if you want to know just let me know i can i can do an in-depth video on it but just imagine where you kind of start with the monolithic application and as the application grows then it's more difficult for you to deploy your application also if you have a lot of people working on the same code base then if my team wants to take something to production it means that it means that i will also be taking the other team's changes to production right now the microservices world pretty much just decouples things and we can just focus on a subset of the entire application and we can deploy things independently we can iterate quicker things are not coupled if you want to use a different database you can use a different database different technology so on and so forth right so what i want to teach you is so right here this is the public internet and as the clients send requests we'll have a load balancer in here so this will serve as the main entry point so we usually when you build applications you don't have the client talking directly to these services right here right because these services or everything in here this should be within your private network and then the load balancer is responsible to perform the routing to the corresponding microservice based on the path so you'll learn all of this later in this series but in a nutshell so you have the load balancer it sends requests added to these two services and i've called it customer and fraud and we also have notification right here so the idea is that um if a a client wants to register a customer for example we check whether that customer is fraudulent and this blue arrow indicates that this is an internal communication between these two services so if the customer is not fraudulent so if the customer is not fraudulent then we save the customer and then we push a notification into the message queue right here which this notification microservice can use and then perhaps it might use twilio or firebase to send sms's or push notifications now all of this in here is powered by a eureka server so as you'll see usually you don't want to be dealing with ports right so calling a service on a specific port because if you have multiple instances of it then how do you keep track of all those ports and basically you just want to have a centralized place where all the clients register to the server so in this case the erica server and then if you want to communicate with them you just need the service name and i'm going to show you how to set all of this you also have the config server right here so config server this is mainly for storing your configuration so whether it's development testing environment production uh pre-prod so on and so forth right so you'll see uh that interior we don't need even the config server uh but i'll show you what it is so on and so forth then we also have sleuth and distributed tracing so uh with zipkin so this is so that if a request comes so let's say that request gets to customer then it flows through fraud and then it goes to notification then with you should be retracing we we know exactly the entire flow and where perhaps is our bottle neck so this is pretty much the overall view now i'm going to be honest with you here so there is a lot to learn literally there is a lot to learn and usually you should just take what you need instead of implementing for example let's say config server or eureka server right because there are better ways of doing this these days usually if you want to take your application to production these days kubernetes all the way right so then you kind of don't need eureka server nor config server and also you'll see that you know the spring framework they have their own load balancer and also i would say like i'm going to show you exactly how to set it up but usually you would never never want to manage a load balance yourself and instead you pay someone else to manage the load balancer and make sure that it's you know always available it can also work multi-region and ssl search are done for you so on and so forth so that you just focus on your domain right so your own business logic the same with databases right so databases usually never host or you never um provision a database yourself right so you never have a server which you look after usually just have a database as a service and then you use it so the same will be for the load balancer um eureka server config server this is taken by kubernetes zipkin there's other things that you can use but i'm going to show you how to implement all of this so that you learn and then i'll show you better ways of doing things so that's all for now catch me on the next one by the end you should have a complete understanding on how to pull all of this together now how exactly are we going to achieve this if you've been following my courses on springboot then you should know by now that springbook makes it super easy for you to build java applications so in here in the official page of spring.io you can see that basically uh what you can do with spring you can write microservices reactive programming with asynchronous cloud web apps serverless event driven batch so on and so forth so you can go and basically see how to get an application up and running super easy with springbook but in this course you'll learn all of this and what i want to show you is so right here because we are learning about microservices let's just see what they have to offer so in here microservice architecture are the new normal building small self-contained ready to run applications that can bring great flexibility and added resilience to your code so basically you can read more about this um just to have a an overview but in a nhl in here the way that we build microservices in the spring world is using spring cloud so this diagram right here is the representation of this diagram right here and basically i've put everything together because i want to build a fully fledged system that communicates to each other with their own databases so on and so forth and this diagram here is much easier for you to understand what is happening but basically at the end of this course you'll have an understanding of all of this but what i want to show you is if you click on spring cloud in here so they give you again definition so developing distributed systems can be challenging and this is what the spring cloud project does gives you so here you can see that we have projects we have spring boot the framework cloud data so and so forth as well as security which i have a course on it but right here so again the exact same architecture you can see that we have service discovery api gateway cloud configuration circuit breakers tracing testing so on and so forth and what i want to show you actually if i click on projects uh let's go to spring cloud and right here have a look so this is all the sub projects within spring cloud now obviously we're not going to use everything in here because as i said you should only really take what is necessary for you to write your own microservices and then as we move towards kubernetes you'll see that some of these things are not needed but go ahead and basically have some reading on how to get all of this up and running but later you'll see that how we're going to install um spring cloud so on and so forth i'll make it super easy for you to understand with maven multi modules so hopefully now you know about spring cloud and within projects you can see that we have spring boot so this is what allows us to write the microservices and then spring cloud allows us to bring all these microservices together and also you've got spring data for databases spring security for securing your microservices so on and so forth if you have any questions drop me a message otherwise let's start developing microservices for this project we're going to use maven as our build tool and in this page right here which you can find the link in the description of this video you can see that they give you the installation guide for the operating system that you have and then how to create a simple project so because i'm on a mac i'm going to use brew so within my terminal i'm going to say brew install and then maven so this should take a while now and there you go so now we have maven now if you want to make sure that maven was successfully installed just click the screen and then type mvn and then version and there we go so this is the version which was installed in my machine so now that we have maven installed in here in this guide you can see that we have this command that we can use to create a project so we say mvn arc type generate and then we pass a couple of flags in here so here the group id so this is basically our organization and the artifact id is the application name and then we pass some other arguments so copy this command and then change this according to your organization or your name and this as well and i already have done that so i'm just going to paste it there we go and you can see that the group id is com.egoscode and then the artifact id is amigo services and in fact before i run this let me cd into desktop and then paste the command again there we go and just give a second and there we go so now in our desktop you can see that uses amigos code desktop we have this folder right here and what i'm going to do is cd2 amigos code services and then in here i'm going to say ls and this is the maven file structure so let me see if i've got a tree in here no so i'm going to say brew install and then tree there we go and now i can type tree and check this out so this gives me now the fold structure in a very nice way so you can see that in here we've got the root we have the palm.xml src main java.com amigos code app.java and then the same for the test and we are good to go next let's open up this folder with intellij so in here i do have the intellij ultimate edition and if you want to grab it i would recommend you to install jetbrains toolbox and if you want to grab it i recommend you getting it through jetbrains toolbox because this is the easiest way that you can manage all of your ides and perform all the upgrades on and so forth so here i've got the ultimate and this is what you see in here now let me open up this folder with intellij there we go and inside of my desktop i do have amigo services which is this folder in here so just pretty much just click on the xml or the folder either one should work open as project and just give it a second while it's downloading whatever it has to download there we go that's done and what i want to show you is so let me just put this full screen so in here if i go to file and then project structure i just want to show you that i'm using java 17 and in here if you want to use java 17 as well so that everything works with no issues just click on edit and then click on plus and you can download the jdk just like 17 but in here you can see that i can download all the other versions in here so 16 15 13 11 and 1.8 so 17 is basically the one which has the long term support as i speak so just u17 and then that's it next let's bring in the dependencies that we need in order to start building our micro services with springboot all right so let me go ahead and open up this folder right here and this is basically our parent project so we're going to use maven multi-module so that we can have dependencies and then let all the all the sub modules choose which dependencies that they need to import and we can also enforce dependencies to all microservices so in here what i want to do is this folder src we not going to need it at this point because this is the parent module and open up the pom.xml and in here so we have a couple things so just go through it but basically change this according to your url if it's not so let me just delete that and leave the properties as is and for dependencies so instead of dependencies let's just get rid of this dependency inside so we're going to have our own dependencies in a second and then for the build and then plug-in management so you can see that we have a bunch of plugins inside so let's also just get rid of everything and there we go so let me just have the empty plugins and there we go now inside let me just have the empty plugins tag and we're going to fill this in in a second now the dependency that we need in here is the following so here i'm going to say dependency management and then within have dependencies and the dependency that i want in here is so dependency so the artifact id so this comes from springboard dependencies and this comes from org.springframework.boot just like so and then choose a version so in my case i'm going to pick the two five seven so this version right here i'm gonna show you in a second but this i think is the latest version as i speak so make sure that you choose the exact same version so that you have no issues then what i also need is to say scope and then import so this is using the bom where inside of this artifact there's a bunch of dependencies that we can use and this is because we're not using springboard as the parent project so this is our own parent module and then we have some modules that can use basically these dependencies inside so if they need for example the spring pool starts a web they can just include it right here so this is the beauty of having the dependency management whereas if we have dependencies in here so dependencies so in here let's say that we want every single sub module to have the lombok dependency so here just say lombok and this comes from org.project lombok and let's also make sure that all some modules they have the testing artifact from springboo so here i'm going to say springboot dash starter and then test and this comes from org springframework.boot and there we go so let me just put this full screen now finally because we are using spring boot let's have the plugin for building the artifacts so here let's have a plugin and the group id will be com.spring boot dot spring framework and then dot boot and then the artifact id will be springboard maven just like that and also let's specify the version in here so version and this will come from the property so this will be spring dot boot dot maven dot plugin dot version and if you grab all of this and then scroll up and inside where we have the properties let's just paste that and then close that and then basically what i want is to say 2.7 in here but i just realized that this version right here is the exact same thing so let's just take this from here and then say springboot dependencies dot and then version and we can take this from here and then put it here close that and then inside we can say 2.5.7 and if you want you can basically control these independently so the springbook maven plugin as well has the exact same version and you can see that this now is taking shape so this should be https and also this should be java 17. there we go and yeah so this is now taking shape so let's just basically reload the changes and it looks like that we have an error oh no that went away uh but basically if i open up maven so this is still red so if i clean you can see that the process terminated so let's have a look so it looks like that i'm missing the type inside of the dependency management so that's fine so inside in here i'm missing the type that's for sure and i want this to be palm so this is so that we can use all these dependencies for our sub projects now let's reload there we go so all good and you can see that we have the dependencies right here everything has been resolved if i open up dependencies we have lombok and starter test so this is what we have included right for our sub projects we also have plugins and in here let's now clean so i just want to make sure that this runs and there we go so let's validate as well and also work so we haven't got anything to compile but you can see that this is working so obviously if you want to grab this file you can grab it under the description of this video so that you can follow along and all you have to do is just change the url the name the group id and the artifact and off you go now just to recap so we have some properties but really dependency management so this is so that our subprojects can pick whatever dependency that they want and you'll see this in a second and then dependencies this is so that all sub modules by default have these two dependencies without them explicitly imported in their pom.xml and then we have the exact same thing for the build so build management right here and basically not everything will be and basically not everything will need this springboard maven plugin and that's why it's inside of this plugin management if you have any questions drop me a message otherwise let's move on all right now let's focus on how we're going to build this microservice right here so we're going to start with customer and then we're going to have the restful api that allows us to post a customer we also will configure the database right here and then once we have this then we can move into the other microservices how they will communicate to each other so on and so forth but for now let's just focus on building this space right here and then we can start assembling the puzzle now that we have this palm.xml right here and this is the parent palm let's go ahead and create our very first micro service as a sub module so in here what i'm going to do is right click in this folder right here and this is the root so amigos services or whatever you have named it right click new and then module now at this point so this will be a maven project the project sdk will be driver 17 and don't tick anything just say next and right here you pretty much name the microservice so in my case i'm going to name it as customer so this will be a microservice that will deal with customers and if i expand the artifact coordinates in here so the group id will be com.ego's code and then the artifact id is customer and then leave the version as is finish and there we go so now have a look so we have this new folder right here this is customer and inside so let's just open up the parent palm and what i want you to notice is that we have now by default this new section in here so modules and this is a list of modules so we can only have one module right here and this is customer now if i open up customer so this will again have the exact same folder structure so for any maven project so you have the palm.xml so inside of this pom.xml we have some properties and basically have look the parent you can see that we have this icon so this goes to artifact amigos code services right here and i usually like to flip this around just like that and then the model version and then this is the artifact for this project right here which is customer and if i open up src main so this is uh basically everything is empty and we're going to add a few things in a second but for now what we're going to do is let's just open up the palm.xml for our customer microservice and let me close this for a second and what i want to do is inside in here let's have so we're going to say basically we want to have the dependencies right here and now we can bring any dependency that we want so for now all i want to bring is so i'm going to say dependency and this has the artifact id as spring boot dash starter dash and then web or starter dash and then web just like that and this comes from org dot spring framework dot boot there we go so now so in here have a look so you can see that this dependency right here right here it comes from so if i click on this button in here it comes from springboot dependencies dot palm so 257. so this is what we have defined in here have a look so right here so dependency management right here we brought all of these dependencies and now we are letting each of these microservices choose whatever dependency that they want to use so for this microservice we want to be able to write a restful api so hence we are bringing in this dependency at this point this is all we need so what we're going to do now is let me just close this bomb and also this main palm oh actually i closed the wrong one so let me just open the pump for customer now inside of src so instead of customer src main java let's create a new [Music] package name it as com dot amigos code dot and then customer just like that and what i want to do is i want to basically create a new java class and then i'm going to say customer application and this will have a main method and this class we're going to annotate it with add and then spring boot application and here i'm going to say spring and then application dot run and the primary source will be customerapplication.class there we go and also we need to pause the arguments from the command line and this is pretty much what we need so we also need to have the application.yaml inside of resources so here file and then say application.yaml or if you prefer properties it's completely up to you enter and inside i'm going to have server and then i want to have the port so i want to have control of the port just like that so the default is 8080 so let's say that we want this to be 8080 and we also want to name this application so spring application name and this will be customer there we go now what i want to do is i want to basically create a new file in here and i'm going to name this as banner.txt and open up google and search for create spring boot banner and click on this very first link and in here let's just say customer and you can change the font if you want but i'm just going to leave the default copy everything go back paste that in and last but not least what i want you to do is open up the palm.xml and you should see this maven button right here or you can press shift command o to load the maven changes so we've added this dependency so let's just make sure this is reflected in this microservice so if i open up so right here we've got customer and the only dependencies that customer has is lombok and starter test and this is because so if you recall correctly inside of dependencies we said that we want all the microservices or all these submodules to have these two dependencies right but we included this one right here for this module but it's not showing up in here because i need to reload in here so you can reload from here or from here either one and you can see that you now have the dependency and it's just taking a while to index and there we go now let's open up the customer application so this is our main method and right click run and there we go so you can see that so let me show you the logs have a look so we've got our custom banner in here which is customer and you can see that everything started correctly and you can see that tomcat started on por 8080 so there we have it we have our first microservice currently it doesn't do anything it doesn't talk to any database on so forth but we'll add that in a second but you see how easy it was first to bootstrap a microservice with springbook so within this package right here com.amigoscode.customer let's go ahead and create the model for this microservice so this will be customer so this is a class and in here i'm going to use lombok so every submodule has lombok in it so here i'm going to say add and then data so this is lombok and then at and then i also need the builder in here and there we go so we're going to come back to this class in a second but for now this is all we need now here let's have a couple of fields so let's have the id as an integer let's also have the first name and last name as a string and finally let's have the email in here there we go now what we're going to do is so we've got the model so basically we're just following the entire architecture and i've got a bunch of videos covering all of this stuff how to properly organize your applications on and so forth so here let's start from the controller so i'm going to say customer and then controller so this will be at and then rest controller this will also need the at request mapping and we're going to map this to api forward slash v1 slash and then customers and i also want to have the at sla 4j just like that so i can just log a couple of things and i've just realized uh instead of a class let's just use a record and because inside we're going to pass a couple things in a second so just leave it like that and now let's have a public method that will basically take a customer from the request body and then register a customer so public void register customer this will take a customer request and we're going to create this in a second there we go and this customer request will come from the request body so at request and then body let's log the customer request so log dot and then info so new customer registration and inside we're going to pass the customer registration just like so and we also need to annotate this with ads and then post and then mapping so that we can fire post requests against this endpoint in here now let's create this class quickly so here new and then java class this will be a record and let's just say customer registration and then request there we go and what we want to pass in here is the first name we also need the last name and finally the email there we go so this is our record and the reason why i'm using a record and not a class is because i get immutability to strings equals and all that stuff for free whereas in here i'm actually going to use jpa in a second now inside of my customer controller so this should be actually customer registration request just like that delete this and then let's just log that instead in here and job done so there we go and now let's create this service that will basically handle this request so let's just say customer and then service customer service and this customer service so let's just create this class so create class there we go and let's also change this to a record and pass nothing inside for now and if i go back in here so what i want to do is just say customer service dot and then register customer and then pause the customer registration request just like that and i need to create this method in here so there we go and voila so i've got the request in here now let's turn this request into the customer so here i'm going to say customer customer equals to and then customer.builder we're going to pass the first name from the request we also need a last name and finally email and all we need to do is just say build so this is the builder pattern and there we go now let me just say to do here and we're going to do this in a second so there you have it so basically right here you can see that how the application is taking shape and what we have to do next is just get the database up and running and then configure our application so that we can store the customer to our database and finally we need to annotate this class with ad service so that spring initializes this as a bin for us so that we can inject it in our controller let's go ahead and get our database up and running so that we can connect our microservice to it so in here what i want you to do is under the root folder of microservices right here so amigos services actually go ahead and say new and then file name this as docker dash compose dot and then yammo and then press enter now inside i'm going to paste some yaml configuration which you can find under the description of this video and if you want to learn more about docker go ahead and check my website i've got a course teaching you everything you need to know about talker but in a nutshell so let's just start from the top we've got services this is postgres and then this is my container right here the image is postgres i'm exposing the ports and then this is the network and right here i've got pg admin so this is the graphical user interface client so i'm giving the name and then passing some environment variables to connect to it and exposing the port 5050 to 80 inside of the container and right here i've got the networks so that they can talk to each other and then some volumes to store some data so once you have this file and make sure it's named as docker dash composer yamo so you can actually run this from here if you have the ultimate edition and if not i'm going to show you how to run it through the terminal so in here open up your terminal or command line and make sure that you are within the project so i'm going to type ls and you can see that i do have this docker compose.yaml now to get things up and running just type docker space and then compose and then up and then dash d for detach press enter and you can see that it's creating the network and now it's creating the containers so the pg admin as well as the database and there we go so you can see that this was super quick you can type docker compose nnps and you can see that we do have pg admin which is listing on port 5050 and the postgres which is listening on port 5432 so now that we have this database let's connect to it so open up your web browser and in here type localhost and then 50 50. press enter just give it a second and there we go so you can see that oops the front is too big so now we need to set a master password so i'm just going to say password right so now let's basically add a new server and in here i'm going to basically name this as amigos code and the connection so in here the host this will be post grass and this is because we are connecting from a container to another container right here so if i show you inside of services have a look networks postgres in here so this guy right here uses the exact same postgres or the the exact same network which is postgres so pg admin uses postgres and right here this is how we define the network so that these two containers can talk to each other and if pg admin wasn't running with docker you would need to say local and then host so this is postgres the port is 5432 leave the database maintenance the username so this is amigos code and the password is password there we go i can save the password and to be honest this is it so click on save and you can see that we managed to connect to our database so i can click on it and data you can see that there is not much information in here but basically if i expand in here you can see that we have databases and by default we have amigos code and postgres so now we have a database that we can work with next let's configure our microservice to connect to it so within intellij what i want to do is let me just close all of these tabs so close all tabs and let's start fresh so inside of our customer microservice open up application.yaml in here what i'm going to do is paste this configuration and you can find this under the description of this video and also if you want to learn more about spring data jpa you can check my website where i've got a course on this teaching you everything you need to know about connecting to databases joins how to model your table queries so on and so forth so it's a very in-depth course which you should take so in here what i have is the data source key right here and within it i do have the username so this is amigos code and the url this is postgresql localhost right here and the reason why is localhost is because our application right here when we start it's not a container if it was a container then we would need to connect via the network but in here you can see we also have the port and customer so i'm going to come back to this in a second we've got the password which is password and then here we have some configuration to set the dialet format sql update when we update our entities and then show some sql now this customer right here so this is the name of the database that we have to connect to so if i go back to pg admin inside of databases create database and then the owner is amigos code and here let's just say customer i'm going to say save and there we go so now we have this database that we can connect to it now the last thing that we have to do is to open up the palm.xml and in here we brought this dependency so start a web so this is for restful apis but we also want the dependency that allows us to perform queries and interact with our database so in here let me just put this full screen and this is spring and then boot and then starter and then j pa or data jpa there we go and what we also need to bring in is the postgres driver so dependency and this will be post and this is from org.postgresql and you can see that this is coming from the power and palm and in here i'm going to say that the scope for this is runtime there we go now go ahead and basically reload so the changes are picked up if i open up maven in a second you should see that we now have data jpa in here as well as the postgresql driver so all good now let's open up the customer class and in here we need couple things so one we need the at and then entity annotation and also we need at all rx constructor and also no our constructor in here we're not done yet so we need to annotate this with add and then id and the id will be based of a sequence so let's just have the sequence generator and then import sequence generator and finally we need to have the generated value just like so and let's import the generated value as well as the type so i think at this point is trying to basically have a star so here let me just say type so generation type and we are good to go so with this in place let's now create a new interface so this will be customer repository this will extend and then jpa repository where the entity is customer and the data type for the id is an integer now what we need to do is open up the customer service and inside of this record we're going to inject it so customer repository so that we can basically save our customer and for this to do right here store customer in db let's just say the repository so repository dot and then save and then our customer job done and delete this to do obviously there are more checks that we have to do but for now this should basically save customers in our database now let's start the application and hopefully this works and there we go you can see that we have some logging and here create table so id email first name last name and then the key is the primary key is the id and we also have the sequence so this is good stuff so now what i'm going to do is to open up pg admin and within amigos code databases customer and then open up schemas so we have one schema and this is the public schema open that up and then we should have one table inside and in fact let me just refresh there we go and now if i open up tables have a look we have the customer table in here and also the sequence which is right here so customer id sequence so this is really cool so if you want you can basically uh count the number of rows so this will give you zero so there is nothing inside and you can even basically run queries against this so you could say for example select star from and then customer and then run this and you can see that this gives us back but you can see that we actually are connected to our database to our database and we have a table called customer based of our entity now what i want to do is send a post request into my api and see whether we can save a customer so i'm going to use postman as my rest client and you can use any other so in here within postman new request two so this will be a post and the url will be a localhost and then 8080 v1 customers select body raw from text to json and in the body let's have this json blob so first name last name email jamila ahmed j ahmed and this json object right here corresponds to so if i go back in here so corresponds to this guy here so if i open up the customer registration request so it maps to this record first name last name and email so if i go back and then let's try and send the request and see whether it works so send there we go 200 status code which means that we most likely have saved this customer to our database so here i'm just going to rerun the exact same query and have a look so now we have jamila ahmed in here so this is beautiful and you can see that how we now have our microservice connected to its own database okie dokie i hope that you had fun learning about all of these different things and you saw that how we are structuring things nicely with maven multi-module using dependency management so on and so forth now what we have to do is so we have customer right here and in the next video what i want to show you is how we're going to set up fraud microservice as well as the notification microservice and we'll also stick in the distributed tracing so you see how the request flows from these different microservices right and also you'll see how we're going to build the client so that we can interact with these microservices as well as set up the eureka server and setting each of these microservices to register as a client if you enjoy what you saw comment down below literally comment down below let me know uh what you liked uh any suggestions that you might have and also don't forget to smash that like button so i can keep on recording these videos if you're not part of the amigo squad community go ahead and join the communities growing on discord as well as private facebook group i would love to see you there this is all for now i'll catch you on the next one you
Info
Channel: Amigoscode
Views: 34,737
Rating: undefined out of 5
Keywords: amigoscode, microservices tutorial for beginners, microservices architecture, microservices tutorial, microservices spring boot, microservices spring boot example, spring boot tutorial, spring boot tutorial for beginners, api gateway microservices, postgresql, docker tutorial, kubernetes, java spring boot, maven tutorial
Id: p485kUNpPvE
Channel Id: undefined
Length: 51min 16sec (3076 seconds)
Published: Tue Nov 30 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.