Vaughn Vernon - Implementing Microservices with Scala and Akka

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so I'm the author of this book maybe you've seen it before if not it is about implementing domain-driven design it's goes beyond theory but helps you to put into practice domain driven design I'm also the author of this book reactive messaging patterns with the actor model it's a Scala Anaka book that basically takes the integration or the enterprise integration patterns and implements those in akka and Scala and my latest book which will be out in a few weeks is domain driven design distilled so a lot of people have had trouble grasping domain driven design you know in a six to eight hundred page book so this book is meant to give you a very practical approach to using domain driven design to start off with I just wanted to say that I think oftentimes we are in an industry of extremes what do I mean by that it seems like we kind of latch on to an idea and we take things to an extreme where we should really use things in a more moderate way here's an example acid everybody has come to respect that acid transactions are something that are very useful on the other hand should everything be acid in fact should we use XA or two-phase commit and try to make our systems be in harmony with one another in what appears to be an acid transaction when you think about it what was life like what was business like before acid transactions how do businesses work people had a wooden or metal inbox on their desk we're folders or papers were dropped into and whenever that person got around to approving something or finishing some work and a workflow it could take not only minutes but hours or even days sometimes for transactions to be completed so ask yourself do we really need acid transactions or transactional integrity around everything actually everything used to be eventually consistent and today many things can actually be eventually consistent who do you think is or are the correct individuals to determine whether something can be eventually consistent or must be acid transactionally consistent who do we ask any ideas who humans but do we ask the programmers domain experts good so it's really the business that knows whether something must be transactionally consistent or if it can be eventually consistent so we ask the business and oftentimes we can reason with the business around eventual consistency and especially if we can show them that if we try to make something transactionally consistent it could be a bad thing we could actually cause failure on other transactions or our own transaction if we try to make everything in the system consistent and in harmony all at once here's another extreme that I see monolith or micro service often times companies will live and die by the monolith actually there may not be anything wrong with the monolith in some cases but should we be using micro-services and if we do what is your definition of a micro service how big is a micro service how big is a monolith is there some way to find a practical balance between monolith and micro service so oftentimes a monolith will turn into what's called a big ball of mud and a big ball of mud does not have to be formed over years and years of time it can actually happen within weeks or months this is where you have multiple domain models that should be separated but instead are all tangled together in one place to the point where you can't even distinguish where your domain models are separate within this one monolith application and to the point where you can't actually make logical sense of the code when considering it in the mindset or the mental model of the business business experts so a big ball of mud is not only a monolith but it's worse than a monolith because you actually can model a monolith in a respectable way but what about micro services what is the size of a micro Service how many micro services should there be do you know what these numbers have in common one hundred four hundred and a thousand these are actually all line counts of microservices that I've seen or heard defined some people will say there should be no more than one hundred lines of code and a micro-service there should be no more than four hundred lines of code in a micro service there should be no more than one thousand lines of code in a micro service whose correct so it's an interesting proposal now someone named Fred you are two hears heard of Fred George he's actually many of you haven't heard of them he's actually credited or credits himself with coming up with the idea of the modern-day micro service so he was working in monolith land for quite a long time in fact he says that he was working on one of the largest je applications on the earth on the planet but after that he got into what he termed were micro services and you can watch Fred George's presentation here on on Vimeo at this URI and what Fred George says there is that one page of code makes a good micro service now if we think about pages in old terms like what I remember what was that sixty two lines of code sixty-five okay what was it 25 25 page 25 line page okay maybe anyway it's hard to even define how big a micro service should be by this definition because even within this room we have different definitions of what is a page of code so how many micro services should we have how big should a microservice be what I'm going to do today is give you a prescriptive approach to doing this and one approach that you may want to consider or even use if you look again at Fred George's definition of microservice he says that in some of the enterprises where he has worked and created micro services that they actually have many even an untold number or unidentified set of services that no one even knows are running they actually just leave them out there whether they still have any purpose or not and Fred George says that it only costs the company about 40 dollars a month to leave those services running so why bother why bother looking now to me that's a problem I don't like not knowing what's running I don't like even the thought of not caring what's running because it could have consequences also when we think about infrastructure infrastructure can have a really big impact on how many micro services we want to run think about having a cluster of servers to run a single entity and that is what those such as Fred George recommend if I have 100 lines of code for a micro service those micro services are going to need to be resilient we're going to have to be able to recover under failure if a service fails or various other things how many clusters could you actually have running in an enterprise if you define your micro services like this so what do you think is a practical way to measure the size of a micro service what I am going to do is talk to you about what domain-driven design offers regarding the size of micro-services and in specific or specifically I'm going to talk about bounded context how many of you here are at least somewhat familiar with what a DDD bounded context is hey excellent good probably about half now even within the micro services community there is the use of this term bounded context but I want to make clear that it is not always used in the way that domain driven design means that pattern to or defines that pattern to me and what I'm saying by that is again some will say that a single entity a single concept such as product let's just take the concept concept of a product that that product is actually in its own bounded context okay it could be but it shares no other linguistic conceptual ideas with any other thing in your enterprise I would say that that's questionable so when I talk about building micro services using bounded context I'm roughly referring to what Sam Newman describes in his book building micro services he does in his book talk about using true domain driven design bounded context and so what is the size of a bounded context any ideas is it just one entity do you know how we know what the bounded context holds we have to ask are ubiquitous language we can't we can't say specifically that a bounded context has just one entity or five entities or ten entities it really depends it depends on the ubiquitous language and so that's the other idea that I'm promoting today is model micro-services in a bounded context that is determined in size by how big the ubiquitous languages linguistic components are cohesive and therefore I think that many times within a bounded context while you can think of the components within that bounded context as being in themselves micro-services and actors for that matter we probably would not want to separate those because they have a natural cohesiveness where they collaborate together in some way so let's take an example this is what I would call a fairly reasonably sized bounded context because it addresses the ubiquitous language of scrum and if you've looked at my implementing domain-driven design book you're somewhat familiar with the concepts of this specific domain model product backlog item release sprint team team member and product owner these are the concepts within the ubiquitous language of scrum we have a set of abstractions that represent the concepts of a scrum based application or a project management tool and so if you think about a micro service as being this size it can really be practical but we aren't talking about creating a monolith in any way because actually in this case we see that we have four micro services or for bounded contexts that are interacting in some way and each of them are addressing a specific part of the business that needs to be addressed so we have the agile project management context that's the scrum based system that I spoke about we have a different ubiquitous language for collaboration we have an issue tracker context and an identity and access context for different micro services for different bounded contexts now think about this for a moment let's add a fifth micro service into this mix and count how many entities are in each of those bounded context or micro services actually it's 35 different entities if you were to count them now how many here would like to have 35 deployed cluster units to represent your micro services or how many of you would rather deal with five can I see the vote for five versus 35 okay fair enough I think that's a good conclusion to reach so what I am proposing is that at least to get yourself started with micro services use bounded context you'll probably find that bounded context works very well in general for the long term for micro services but if you find you know that that you're becoming more and more comfortable with micro services over time and you want to make all our deployment units that's not out of the question but I think it's wise to start with this granularity to begin with it's larger than one entity but it's much much much smaller than a monolith so the ubiquitous language that I am talking about is greater than entity names a ubiquitous language is really the language that the business comes up with and that developers help the business refine in a close-knit team and so a ubiquitous language grows it expands it contracts over time but it's greater than just the entity names it includes from a reactive development perspective not only the entities but also command messages and event messages so that's what we're gonna talk about next is the commands and events that are part of the ubiquitous language of scrub so we have our product entity we have our backlog item entity and we have a command message and if you're thinking in terms of akka this would literally be a message that gets sent to the product actor so backlog or a planned backlog item would be a case class for example in Scala we create an instance of that case class we pass the message to the product plan backlog item product then emits if that is a valid command it emits a backlog item planned domain event this is part of your ubiquitous language when we think about the backlog item entity again an actor and we have a case class defined tasks an instance of that case class is sent to backlog item define a task and what that backlog item emits is tasks defined domain event so this is all part of your ubiquitous language this is all within a single micro service note to that your micro service ie bounded context owns databases it owns an event journal so those two events that you saw being emitted by those two different entities those events are being saved into an event journal which is a sequential journal of all events that have ever occurred within that micro service are bounded context this makes up the event streams and the entire event journal for that bounded context over time so this is what I'm talking about you put events in in the order in which they occurred and events can also be published out to other micro services so that they can function properly we also have what's called a query model so this view is event sourcing which corresponds to akka persistence and then we can take the events from our micro service or bounded context and create a model that is query optimized for the kinds of queries that our users and integrating services need so again we're talking about actors as asynchronous services and if you will you can actually architect your system in such a way that the actors within a single bound that context are like many micro-services with it ok what I want to emphasize next is to never ever ever do this don't ever take a request into one might perform some transaction with an entity and then send a request to another micro service because this is trying to mimic XA right except it doesn't so if you have a failure right here it means that your system is out of harmony and that's a bad situation to be in so what do we want to do well this is where I agree with Fred George Fred George talks about Rapids rivers and ponds Rapids we're gonna talk about Rapids first what are they Rapids is where every single micro service in your enterprise publishes domain events and all of those domain events go into one big bus topic let's say think of it as the all topic everything goes in there and then so it kind of looks like this we have a micro service publishing events into a topic and each of the micro services gets every single one of those domain events so every other micro service knows about the domain events that happen in every other micro service however well first of all this requires a high performance bus to make it really simple actually arrests for Adam publish Adam pub kind of approach works really well you can also use Kafka RabbitMQ or something like that for the rapids alright and we can linger on that a little bit later but the rivers are where the individual micro-services are bounded context subscribe to the all topic events and then they filter out the events that they're not interested in and the events that they are interested in are dispatched to actors within that micro service like this so the topics service it's a micro service in its own sense but it's not really a bounded context this is a technical service where domain events are flowing in and then being published out to an interested micro service and an event is turned into a command because an event is a matter of fact you cannot dispute that the event occurred but the command can be rejected so in this case we're saying that this event translates to this command and our micro service are bounded context and possibly this entity will accept that command if it does what will it do well it's going to save its entity State as a series of it domain events part of your ubiquitous language into the event store event journal and then the actors will omit those events back to the Rapids so you see the circle and now again other micro services can take advantage of the fact that those events have occurred channel services may have a very very small ubiquitous language and here's what I'm talking about in this case you may have an enterprise that looks for or is interested in an offers that users would like to see some kind of offer maybe its plane fares trips vacation rentals something like that so you have an offers detector but how do you actually make the reservation is the reservation part of this ubiquitous language or would you conclude that it's in a separate micro service a separate ubiquitous language well it really depends on your conversations with the business experts but it could be that your ubiquitous language 4-channel services are much smaller even just a very few entities so what about reactive with micro services we're interested in micro services being responsive resilient elastic and message driven responsive in my experience using scala akka and play i often times see rest endpoints take a request and provide a response within 12 to 20 milliseconds timeframe so this is a very very highly responsive environment that I'm describing what about resilient the interesting thing about akka and the actor model is that when you have an exception thrown by some actor component it's not the client that has to deal with that exception it's the parent of the actor that throws the exception that deals with it and the parent is the component that best understands what to do under those circumstances so we aren't leaving it to every client for example of the domain model to understand what needs to happen under every situation where an exception might get thrown instead the parent of that component is what deals with it can help the system to recover quickly even to self-heal and then all that the client needs to understand is was my request honored or was it not honored if it was honored we're good if it wasn't honored I can retry or offer a failure condition to the user that's all that the client needs to understand and the client can build a circuit breaker for retries it can use back off exponential caps back off can use a lot of different approaches for retries or it can simply offer a failure condition to the user elastic well if you haven't seen the other talks about akka cluster and how akka cluster is elastic then I I would say that you should watch those videos after the conference I'm not gonna linger on this but you can actually shrink and grow a micro service on demand message driven to be clear actors are message driven and the rapids approach to publishing all events and subscribing to all events in a given system is message driven and I also want to talk about the nature of the throughput of the high-performance bus you know we're talking about being able to with rest publish and subscribe to tens of thousands of events per second and with Kafka even hundreds of thousands if not higher numbers of events per second and there there's actually a RabbitMQ service that you can get from Google where you can publish as in send and receive two million messages per second and I'm talking about 1 million in and 1 million out so probably for a lot of us that kind of throughput in the rapids will will probably work pretty well for us ok so let's talk about how to implement micro-services using Scala and akka and this is the distributed computing use case that I'm going to show you in this demo what we have is as step one you see at the top step one we have an incoming command message the command message is create a product this is in the scrum agile project management context so we're going to create a new scrum product a scrum product in the ubiquitous language is defined as the software that we're building that is what a scrum product is to an agile team using scrum the command comes in we emit two domain events from our product or the potential for two domain events we definitely MIT product created which says that this product has been created but if the command message also stipulated that a discussion a collaborative forum based discussion should be created in addition to the product we will also emit a discussion request a domain event that domain event will end up in the river or in the rapids I should say and then eventually into the river of the collaboration micro service discussion requested and a forum and discussion entity will be created in the collaboration micro service and then a discussion started domain event will end up back in the rapids and then it will go back to the agile project management context micro service as discussion started and the product will now have an identity that says I have a discussion available through another microservice so whenever our users want to have a chat about this scrum product in particular they can use this threaded discussion to to carry that out so let's look at the code and what I want to show you is first of all in each microservice you're going to need some sort of startup so in your when you have a micro service such as the agile project management context or the collaboration context or any other kind of service you're going to need to get in touch with the rest of the micro services and the way that you do that is you have what's called a service registry and so as you start up can everybody see this code okay not so good a little bigger okay all right so what we have is and this is using dependency injection within play within the play framework so we have we're going to bind what's called a start up runner that's really just this singleton class right here and this start up runner is going to bind in eagerly which means whenever the service starts up this is going to be the first thing that happens all right and we register this start up module in our application comp file of play you can look at the details of how to do that I won't show you right now but it's very simple all right so this is the first thing that's going to happen when your service comes alive now your startup Runner is going to do a few things it's going to create a topic speeder which is going to be responsible for taking all domain events that occur in your micro service and putting those into the rapids or that topics service and then we're also going to start a topics reader which will read all new domain events from the rapids and bring them in to our micro service so that we can filter and get the events that we're interested in in our particular micro service then we create a heartbeat actor that registers this particular micro service with the service registry it says under this name I provide these URIs okay just to put it simply as you can see at the very top of this code here i have a home uri i have a new product uri so this is how another service would would send a request to my service to create a new agile product or it could be a UI that uses this and then we can also get so do a query on a product through the product name alright so that's the kind of thing that happens and then and then every few mike milliseconds this actor will re register itself with the service which allows the service to actually move around or and and it also allows the service registry to check health the next component that I want to show you is the products controller so this is in the agile project management micro service it is the controller that will take rest requests so if you can make out here I have a comment which is a curl command and this curl command can be used to create a new product I'll demonstrate that in a moment and this curl command can be used to get the state of a product by its ID ok so what we're going to do is for example when we create a product we're going to get the product description as JSON data from the rest request and then we're going to get the identity for the product the identity is going to be sent in with this command create product remember our our command message is being sent in create product to the new product which is an actor we get a future back we map to we map the future to create product result message and then we map that to a result and we're going to assume that the product was created you would have potential failure recovery and in this situation but if we have created we're going to send a 201 created message with the location URI of where that product can be found so if you wanted to immediately query back and ask where is this product or what what does this product look like you could do that okay so we've actually looked at service startup we've looked at a service endpoint now let's look at the potential need for a process manager a process manager is described in enterprise integration patterns and shown how to you how to create a process manager in my book reactive messaging patterns with the actor model I'm going to show you an example of this in code so this is as you can see here the start forum discussion process or the start forum or the I'm sorry the forum discussion starter which is a process manager this process manager is interested in just three messages one message is start forum discussion so as its default receive block it's going to take a start forum discussion and it will then create a new entity called forum and this entity will be sent a start forum message and internally this forum discussion starter will become a start forum discussion info listener which is the next block down and notice that I I give this block an info a start form discussion info object so that when it receives a forum started message domain event message it knows that it can then properly create the discussion within the forum and then this block tells the listener to become a discussion started listener and finally we reply back to the original sender that we started a forum discussion all right now an example of a an entity or a persistent actor this is the product entity in the agile project management context and it's going to receive a create product command and what will that he met it will emit at least a product created event and if a discussion was requested right here it will also emit a discussion requested domain event this domain event will flow over through the rapids into the river of the collaboration context and that is where this forum discussion starter process manager is going to see that domain event or a command based on the that domain event and it's going to run so what I want to do is show you each of these services running so I'm going to start the service register on port 9001 and I'm since this is in development mode I'm just gonna ping this service registry and make it start running then I'm going to start the Rapids this is the topics service running on port 9000 - and I'm gonna ping that service as well so these are two technical services they're not really taking care of any business function they're just taking care of service registration and pub/sub essentially now I'm going to go to my collaboration bounded context this is actually a business micro service and it's going to run on port 9000 3 and I'm going to ping this service so that it starts running and now I'm going to go over to the agile project management context micro service and let me ping this service with something actually meaningful so now the curl command that I'm running here is actually going to post to create a new product in the agile project management context and what you should look for is in the topics you're going to see so in the upper right corner you're going to see a message come across that is the domain event that fires from the agile project management context so here we go you see the agile p.m. is starting to run we're going to get a request look up at the topics you see the topics that message was just delivered over here to the collaboration context and we finally got back in the agile project management context indication that got the mess the domain event that we were looking for that the discussion was started and if you want to look in the collaboration context to go back a ways here you can see that the topic for all message was received we got a collaboration discussion requested event that caused a forum and discussion entity to be created in the collaboration context through that process manager and then the topics reader consumer said that completed successfully and if we look back in our agile project management context we see that this discussion was started we got to discuss discussions start a domain event and that allowed us to marry up the discussion ID with the agile project management product ok all right so you got to see an actor aggregate let me just show you I we're actually a little bit over time if anybody absolutely needs to leave feel free to do so but I did want to show you also the CQRS part of this CQRS stands for command query responsibility segregation and this is where we're going to take the domain events from our own bounded context our own micro service and we're going to create optimal query views for how the user would want to consume the information within this micro service for example on a UI so we get a tick event every so many milliseconds and this tick event is used to read a persistence query or to use a persistence query from akka persistence query and to read any new domain events that have been received into our persistence into our event journal and each of those is projected each event is projected into the proper view so now whenever we receive a query product view we can return a product view result object that has the view of a given a gelada sizz tuned for how the user wants to view which is different from the product aggregate or product entity which is tuned for commands all right so any questions yep yeah okay so I think I think what you're asking is in thinking about this component should we have more specific topics top okay but but everything that's going in here is just a JSON representation yeah well you have to yes you have to take into consideration versioning of domain events or replacing domain events so yeah that's that's a thing for sure but maybe we could take that one offline any other questions about this yeah so regarding the bounded context yep say for example you have only two services in a particular bounded context that are overloaded do you have the flexibility of scaling only those two services or do you have to scale the entire bounded context I see what you're saying so yeah that so essentially what your argument is that if I have one micro service per entity one entity per micro service I can scale those independently right so that yeah that could be one reason to break one entity out and and deploy it separately but logically it's still part of that ubiquitous language so I'm not I'm not necessarily saying that you should never deploy individual entities separately you can do that I but I argue that there's still part of the same ubiquitous language or just you just have a different deployment strategy okay right right right yeah scaling is definitely a reason to break them out I can't hear I'm sorry in this diagram the persistence journaling is happening in the product right yes the and even the view projection is also happening in the product right yeah right I know the view projection is happening out-of-band from the product okay so I actually have this products views is a separate actor okay yeah and you can you can send a query message to that actor and in the background or you know every so many milliseconds that actor is looking for any new interesting domain events such as product created discussion requested discussion attached right and it's building the view from that okay any other questions go ahead go ahead where are you sometime - why am i using time yeah every five seconds like that what there's just subscribe to the vents and get the events that they are where do you see fights oh yeah my like good I yeah oh two seconds yeah so actually that for practical purposes this is for teaching okay but this would obviously be maybe like 10 milliseconds or 100 milliseconds or something like that we don't want to just pound the this this pub/sub interface is running over rest and and we don't want to just constantly pound the the reader but you know certainly you have to find the right threshold for for reading events did you have another same service yes they are yeah interesting yeah so when that when scalability is the thing right you definitely have to approach this differently but what I'm saying is to start out with with this sort of conceptual architecture of micro-services is going to greatly simplify your ability to to succeed with micro-services to start with then as you see that individual entities or some kind of component needs to scale greater than you can pull that one out from the micro from the one micro service and deploy it separately but it would still logically be part of the same valid context same ubiquitous language yes so where does that go and what is the purpose of it so that that is a technical service it's running here and it is it's in your infrastructure it's it's a service that that needs to run and what it's doing is that just think of it as a as a global map so to speak where I have a key value pair and the key is the name of my service and the value is another map that that says these are the endpoints that I support or it at a minimum it would be a key with a single value that says here is my home location and from there you can navigate to all my other endpoints right is it a real time what no no it's actually that that is how that is how anything knows that that it can use the agile project management context or it knows that it can use the collaboration context it's basically like a service lookup it's where you do your service lookup some people call it service locator I swear off that word because it gets me in trouble every time I use it but it is a service registry it's where it's a it's sort of a central location that in itself can scale and provides the means for all other services to know where it can find a certain service right all right makes sense okay I can meet outside if anybody has any other questions thank you for attending [Applause] [Music]
Info
Channel: Vaughn Vernon
Views: 494
Rating: 5 out of 5
Keywords:
Id: ceXzpVvp9AU
Channel Id: undefined
Length: 58min 39sec (3519 seconds)
Published: Thu Sep 13 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.