We just saw some scenarios in which this whole event based communication architecture seems to totally
fall apart.
In this video I'm going to answer a couple of questions that you might have about all this stuff right
from the get go.
Well then take a pause and then we'll go through some possible ways of solving these problems in the
video after this one.
It's going to try to keep this video a little bit shorter.
OK.
So first big question you might have.
Remember we're making use of async communication between our different services.
That's why we're dealing with these event things.
We had said earlier on INSIDE the course that when we are working micro services we can have them communicate
asynchronously at events or synchronous sleep with direct requests.
So at this point it might sound like this async communication style is just awful.
Based upon all the problems I just mentioned and you might think that it would be a lot easier if we
just stuck to some kind of synchronous communication approach.
Well turns out all the same stuff happens with synchronous communications.
So at that point you might say well the heck with this micros services stuff.
Let's just go back to building monolith style apps.
Well it turns out all this stuff actually does happen with monolithic style applications too.
So let me show you diagram just to expand on this first point.
All right.
So we're going to imagine that we are building the same kind of money depositing application but now
we have a more monolith style approach where we are not exchanging events or anything like that.
Now in this scenario we would imagine that maybe a user makes three requests in a row.
One request you deposit 70.
Deposit 40 and then withdraw 100 now even if we are using some kind of monolith style application it
is still incredibly likely that we are running multiple instances or copies of that application.
So never a user makes these three requests right here.
They will probably go to a load balancer of sorts and then these requests will essentially be randomly
assigned to all of these different instances.
So we can imagine that their first request goes there.
The second to right here and the third one down here so then each of these instances are going to raise
essentially and try to process that incoming request.
So we might be in that same kind of scenario where maybe instance a an instance B have a lot of traffic
incoming right now for whatever crazy reason maybe they are a provision to some virtual machine that
has lower specs than instance see down here or whatever reason we can very easily imagine that monoliths
C down here or instant C might process this withdraw one hundred dollars request first.
So it would reach into the database.
Take a look at the user's balance Oh it's zero right now.
Well once again we're in some huge error.
So by just going back to some model modeling style approach we still deal with these concurrency issues.
It just turns out that when we start using this micros services event based approach these same concurrency
issues just become a little bit more prominent because we're now talking about adding in this extra
latency step of the Nats server.
And we're also talking about the possibility of having automatic retrials or read deliveries of these
different events.
So because the system becomes more complex because there are additional communication jumps inside of
here this whole concurrency issue just becomes a little bit more prominent.
Well to be honest a lot more prominent.
But it's still an issue even if we went back to an old style approach again.
So next up you might come up with an immediate solution.
If I asked you Hey solve this problem here's one possible solution you might decide to come up with
this a very common solution or a solution people come up with and then they very quickly realize oh
wait that won't quite work out.
So when we were going through all these different scenarios that everything would fail it seemed like
a lot of the issues kind of stemmed from the fact that we had two separate services processing events
because now there was a scenario where maybe one service was slower than the other or had communication
issues with file storage or whatever else.
So very convolution people come up with is let's just run one copy of the service one instance think
about what would happen if we did that.
So we would say let's throw that service out now we're just running one copy of the account service
now as we start to publish events deposit deposit withdrawal.
They'll go to hear what process that process that process that now even then there's still a possibility
of failure here.
For example this first event we could have some issue opening up that file because of some temporary
issue with the hard drive so we might end up having some issue processing this first event.
We might fail to process it entirely and it gets thrown back over essentially more or less.
It doesn't actually get thrown back over but we never acknowledge it.
And so Nats figures that has to deliver it again if we might then successfully process 40 dollars and
then withdraw one hundred and boom we're still back to the same issue as before.
But this is not foolproof but at least it kind of solves in the issues we ran into.
And we are running multiple instances but that's not the real big issue here where we still have the
possibility of failure.
The big issue is that if we are only going to run one copy of the service now all of a sudden we've
got a processing bottleneck inside of our application.
If we can only run one copy of the service well we are very severely constrained at how quickly our
application can process data and how we can scale it up.
Remember generally two ways to scale up an application.
We can scale it vertically where we are going to increase the specs that are dedicated or the amount
of you and processing power that the service gets or horizontally.
That's where we create more copies of this service.
So we're going to say right from the outset they're only going to run one copy of the account service
all the sudden.
We cannot scale horizontally and I can end up being a huge catastrophic issue down the line as our app
starts to get more popular and more traffic going to say solution one it's not going to work.
It's not an option.
We always have to assume that we're going to be running multiple copies of any given service.
Option number two or possible solution number two.
That is also not going to work.
Now I don't really have a distinct plan here.
This is more just a note that I want to throw out right now.
Very quickly so possible solution number two you might try to figure out every possible concurrency
issue inside of your app and you might decide that Hey we're gonna find all these possible issues and
we're going to write code to solve every single last one.
Well I just want you to get it in your head right now.
I really want you to internalize this inside of any application.
There is an possibly infinite number of concurrency issues.
There can be a lot of different things that could possibly go wrong and you really feasibly can not
sit down and write code to handle every last issue.
Now of course there are exceptions to this.
If you are building some kind of spaceship or something like that something that is absolutely critical
in nature that it always works no matter what.
Of course there are exceptions.
But if you are building some kind of like Twitter clone or something like that does it really matter
if say two tweets are out of order.
Does it matter.
Two tweets are duplicated or forum posts or blog posts.
Does that kind of stuff really matter at the end the day.
And are you going to dedicate a huge amount of engineering time and money to solve that problem.
Well I can tell you right now you're probably not.
So there is a certain point where you might start to identify possible issues and you say you know what.
Realistically that is just not likely to happen.
You know it's not likely for a user to try to create five tweets at the same time while also deleting
two of them and editing the other three or something like that.
So you really got to sit down and make some engineering judgment.
Is this actually worth trying to solve.
Because a lot of the time you're probably going to inevitably say no it's not so this isn't really a
solution for say I just want to throw this out there right away.
Because even in the app that we are going to build you might start to say hey Stephen wait a minute
in our ticketing application if a user creates a ticket and then does this and then this and then this
well they can end up an issue if the timing is just right and some service fails at the same time.
OK.
I accept that there might be holes there might be gaps.
But again at the end of the day we probably cannot write code to capture every single case because number
one it might not just might not matter.
Number two it might just take too much engineering time to fix OK.
So again Kim's short video here.
OK.
Was eight minutes I still failed.
Well any right.
Let's pause right here.
We're gonna come back the next video and take a look at some possible strategies to solve these big
issues.