100% found this document useful (1 vote)
699 views

Microservices Notes and Practise

spring.cloud.config.server.git.uri=file:///C:/Users/akhil/Documents/microservices-with-spring-cloud/config-repo

Uploaded by

Akhil Sai
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
699 views

Microservices Notes and Practise

spring.cloud.config.server.git.uri=file:///C:/Users/akhil/Documents/microservices-with-spring-cloud/config-repo

Uploaded by

Akhil Sai
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 176

Micro service definition

Micro services are cloud enabled That means I would be able to have multiple instances for each of
these micro services

looking at the diagram of a production deployment for a set of microservices.

33

00:03:03,930 --> 00:03:09,370

You can see that at that at this moment there are two instances of MicroService1 four instances

34

00:03:09,460 --> 00:03:16,760

of MicroService1 and one instance of MicroService3 by cloud enabled I mean that if

35

00:03:16,770 --> 00:03:22,490


there is more load on MicroService3 I should be able to easily bring up another instance of

36

00:03:22,490 --> 00:03:23,490

MicroService3.

37

00:03:23,720 --> 00:03:30,070

This should not involve a lot of configuration I should be able to bring up an instance of MicroService3

or take down a instance of MicroService2 without having huge problems.

39

00:03:36,670 --> 00:03:39,590

That is what I mean by cloud enabled.


So as far as this course is concerned we already looked at RESTful web services what we look at in the
subsequent

41

00:03:48,730 --> 00:03:56,890

sections in this course is how to cloud enable them how to set up an architecture such that it would
be

42

00:03:56,890 --> 00:04:04,660

able to dynamically adjust and be able to bring new instances up and take the older instances down.

4. Step 00 - 03 - Introduction to Spring Cloud:


If you go to the home page of spring cloud which is cloud.spring.io it says spring cloud provides tools

00:00:34,500 --> 00:00:41,280

to quickly build some of the common patterns in distributed systems to the typical problems which are
8

00:00:41,280 --> 00:00:49,050

present for distributed systems in the cloud spring cloud provides a range of solutions.

00:00:49,050 --> 00:00:57,270

The most important thing that you need to understand is spring cloud is not really one project as such.

10

00:00:57,270 --> 00:01:04,780

There are a wide variety of projects under the umbrella of spring cloud on the spring cloud homepage.

11

00:01:04,800 --> 00:01:13,620

If you scroll down further you'll be able to see huge variety of projects which are related to spring

12

00:01:13,710 --> 00:01:14,520

cloud.

13

00:01:14,550 --> 00:01:19,680

One of the important projects in spring cloud is spring cloud Netflix.


Some of them are spring cloud config which is to provide a centralized configuration management.

23

00:02:00,540 --> 00:02:09,930

spring cloud bus enables the microservices and the infrastructure components things like config
server things like
24

00:02:09,960 --> 00:02:16,350

API gateway to talk to each other in this course we'd be using the Finchley M2.

25

00:02:16,380 --> 00:02:19,990

release of spring cloud.

One of the challenges we talked about earlier was

1)configuration management.

29

00:02:37,590 --> 00:02:44,250

We talked about the fact that there would be

2)multiple microservices multiple environments for each of

these microservices and multiple instances in many of those environments.


31

00:02:50,790 --> 00:02:57,480

This would mean that there is a lot of configuration for these microservices that the operations team

32

00:02:57,480 --> 00:02:59,320

needs to manage.

00:02:59,640 --> 00:03:07,860

Spring cloud config server provides an approach where you can store all configuration for all

34

00:03:07,860 --> 00:03:13,270

the different environment of all the microservices in a Git repository.

35

00:03:13,590 --> 00:03:19,830

So you can store all the configuration for different environments of different microservices in just

36

00:03:19,980 --> 00:03:30,210

one place in a centralized location and spring cloud config server can be used to expose that
configuration
37

00:03:30,240 --> 00:03:33,090

to all the microservices.

The next challenge we talked about was the dynamic scale up and scale down.
we'll also use Feign in

62

00:05:58,110 --> 00:06:07,500

the currency calculation service as a mechanism to write simple RESTful clients.


the solutions for visibility and monitoring are the zipkin distributing Tracing Server.

We would use Spring cloud sleuth to assign ID to request across multiple components and we would
use

65

00:06:22,430 --> 00:06:29,930

the Zipkin distributed tracing to trace a request across multiple components.

One of the important things about microservices is these microservices have a lot of common
features.

67

00:06:38,130 --> 00:06:45,600

For example logging, security , analytics and things like that you don't want to implement all these
common

68
00:06:45,600 --> 00:06:49,520

features in every microservice.

69

00:06:49,800 --> 00:06:55,140

API Gateways provide great solutions to these kind of challenges. We will use a Netflix Zuul API
gateway in this could.

06:59,890 --> 00:07:06,750

We will also implement fault tolerance using hystrix if a service is down.

72

00:07:06,750 --> 00:07:13,080

Hystrix help us to configure a default response in this video.

Advantage of micro services:


Advantage 1:

Adaption of new technologies and processes

When they build applications as a combination of microservices which can communicate with each
other

00:00:31,190 --> 00:00:38,400

using simple messages each of these microservices can be built in different technologies.

00:00:38,570 --> 00:00:43,760

Typical more monolith applications people would not have that flexibility.
For example Microservice one might be java MicroService two might be Nodejs Microservice three
might be

00:00:50,810 --> 00:00:57,770

written in Kotlin and tomorrow there might be a language X Y Z which is really doing well and which

00:00:57,770 --> 00:01:05,390

provides a lot of benefits to you and you can easily create a micro service in that specific language.

And also for the new Microservices that we create we can bring in new processors as well.

Advantage 2:

Dynamic scaling

he other important advantage of Microservices is Dynamic scaling consider an online shopping


application

12

00:01:21,920 --> 00:01:23,260

like Amazon.

13

00:01:23,380 --> 00:01:30,470


They don't really have the same amount of load or same amount of traffic or same amount of users
throughout

14

00:01:30,470 --> 00:01:33,690

the year especially during the holiday season.

15

00:01:33,710 --> 00:01:41,870

The load on the application will be a lot and during the rest of the year there might not be so much

16

00:01:42,110 --> 00:01:47,970

load during the Black Friday there might be a huge amount of load.

17

00:01:48,350 --> 00:01:56,450

If your microServices are cloud enabled they can scale dynamically and you can procure hardware and
release

18

00:01:56,460 --> 00:01:59,090

that dynamically as well.

Advantage 2:
Faster release cycles that means bring new features faster to market

It's much easier to release micro services compared to monolith applications.

22

00:02:16,880 --> 00:02:26,550

This means that you can bring new features faster to market and that's a big advantage to have in the

23

00:02:26,550 --> 00:02:27,910

modern world.

5. Microservices with Spring Cloud - V1

====================================

1. Next Section uses Latest Version of Spring Boot


When should you persue v1 when your using older version of spring boot <=2.3

Jump into v2 course:

6. Microservices with Spring Cloud - V2:

1. What's NEW in V2

And as part of the latest versions of Spring Boot and Spring Cloud, you'd be using Spring Cloud

LoadBalancer instead of Ribbon. In the earlier versions of Spring Boot and Spring Cloud,

before 2.3, Ribbon was the load balancer.

However, we would be using Spring Cloud LoadBalancer as the load balancer in this specific section.

We would be using Spring Cloud Gateway instead of Zuul and we will be using Resilience4j instead of
Hystrix as the circuit breaker.

In the next section, we will be using Docker to containerize microservices, we will be running all the
microservices using Docker and Docker Compose, and
in the section after that, we would be jumping into Kubernetes. We will be orchestrating all our
microservices with Kubernetes.

So here is the section on Microsevices with Spring Cloud V2 and we have Docker

V2 in Section 7 aand Kubernetes V2 in Section 8.

6. Microservices with Spring Cloud - V2:


7. Step 04 - Setting up Spring Cloud Config Server - V2:

===============================

Create cloud config server


8. Step 05 - Installing Git and Creating Local Git Repository - V2:
Make sure you dont have any spaces in the folder name
Cmd: git commit -m "adding limit-service property file"

Result:

Author identity unknown

*** Please tell me who you are.

Run

git config --global user.email "[email protected]"

git config --global user.name "Your Name"

to set your account's default identity.

Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'Akhil sai@DESKTOP-7D60FF9.(none)')

----

Cmd: git config --global user.email [email protected]

Cmd: git config --global user.email [email protected]

Cmd: git commit -m "adding limit-service property file"

Result:

[master (root-commit) b3c2a3e] adding limit-service property file

1 file changed, 2 insertions(+)


create mode 100644 limits-service.properties

10. Step 06 - Connect Spring Cloud Config Server to Local Git Repository - V2:

Let's now connect Spring Cloud Config Server to the Git repository.

The way we can do that is actually to go to the application.properties of the Spring Cloud Config

Server and configure the folder.

What is the folder where we configured our repository at? Let's do a present working directory.
connect Spring Cloud Config Server to the Git repository.:

property name: spring.cloud.config.server.git.uri=


In windows using forward slashes in path
Hit http://localhost:8888/limit-service/default

So we haven’t added @EnableConfigServer


Issue resolved by make sure the application name in property file and external property file should be
same
Now, we have connected the Spring Cloud Config Server to the Git Repo.:

Connect Limits Service to Spring Cloud Config Server - V2:

I have connected before tutor explanation Connect Limits Service to Spring Cloud Config Server

How do we connect the Limits service to the Spring Cloud Config Server?

Let's get started.5


One of the most important prerequisites is in our pom.xml.

When we created this project, we already selected spring-cloud-starter-config.

This is the client project that is needed to enable Limits service to talk to the centralized configuration

And the next thing that we would want to do is to configure the URL of the Cloud Config Server

in the application.properties.

What is the URL of the Cloud Config Server? The URL of the Cloud Config Server is localhost:8888.

So let's pick that up.

So, this is the value that we would want to configure as the URL of the Cloud Config Server.

Make sure that you are configuring this in the application.properties in limits-service.

So, what do we want to do is to import the configuration for the application from the Cloud Config

Server.

In earlier versions of Spring Boot, we needed to create a separate file


called bootstrap.properties,

but it is not really needed anymore.


You can see that it's fetching config from server at localhost:8888
and you can see that the name that is being used is limits-service,

this is the application name that we have configured and the profile that is being used is default.

One thing we already saw is the values in the application.properties have less
priority compared

to the values which are present in your Git repository.

We have now connected the Limits Microservice to the Spring Cloud Config Server to the Git Repo.

13. Step 08 - Configuring Profiles for Limits Service - V2


Addition of below property not required as we can see in above screen shot that dev profile is active
Let's say, I would want to configure the properties for Microservice X, Microservice Y,

how do I do that?

All that I'd need to do is to copy limits-service.properties and actually, I'll call this microservice-x.

properties or I would configure microservice-y. properties.

The biggest advantage of going with this approach is now all your configuration related to your
application is centralized

And if I would want to have separate properties for microserrvice-x in dev and QA, I can create a dev
and QA files as well.
By separating out the configuration from your applications, you are making your
operations easier.

Your operations team can control all configuration related to all microsevices
for multiple environments in a single location.

So, whenever they would want to make a change in an application, they make a
change in the GitHub repository

commit it in and that's it, change is ready and distributed to multiple


environments

14. Step 09 - Introduction to Currency Conversion & Exchange Microservices - V2:


Micro service 1:
Micro service 2:

15. Step 10 - Setting up Currency Exchange Microservice - V2:


Tutor deleted limit-service and spring cloud config server project from eclipse work space so that we
can focus only on currency exchange and currency conversion microservices.
17. Step 11 - Create a simple hard coded currency exchange service - V2:
18. Step 12 - Setting up Dynamic Port in the the Response - V2:
A little later in the course you would see that we would have multiple instances of Currency
Conversion

Microservice and the Currency Exchange Microservice and when I'm calling from
Currency Conversion

Microservice, I would need to know which instance of the Currency Exchange


Microservice is providing the response; is this Instance 1 or is this Instance 2 or
is this Instance 3?

Is this Currency Exchange instance running on port 8000 or 8001 or 8002?

That would help us identify whether our load balancers and the naming servers are working properly
and to be able to track the instance of Currency Exchange that is providing the response back, what
we'll do is, we'll add in a variable in here.

The variable I would want to add in is a string variable and I'll call this environment.

So, in this environment, we'll send a few environement details back in the response of the REST API.

I'll not add it to the Currency Exchange constructor

Extract into local variable


How do I get the value of the port?

Spring offers a class called environment.


Let's say I would want to have two instances of this application running.
Create a copy of instance
Right now we only have port in the environment. A little later when we play
with other tools, we will add more information to the environment

19. Step 13 - Configure JPA and Initialized Data - V2:

let's now make it fetch some details from the database and we would be using
an in-memory database called H2.

and we will be using JPA to talk to the in-memory database and to be able to
talk to the database,

we would need to add a few more dependencies in.

So, I'm opening up my pom.xml, currency-exchange-service/pom.xml


If you're not familiar with Spring Data JPA or JPA or Hibernate in general, I'd
recommend you to check out our section in the appendix.

It gives you a good introduction to JPA and Hibernate and Spring Data JPA.
To be contd.. after JPA Section

Below image shows that spring configured h2dialect through its Auto
configuration as we added h2 dialect dependency in pom.xml
We would not want to use a random database URL like jdbc:h2:mem:baa68bb2-
8fcd-4c1c-b8a6-0df42e3b7a4e.

So, what we'll do is, we'll configure one.

In the earlier versions of JPA the above was default.

In later version they made it random.

now I'd want to also enable H2 console.


When application restarts table will drop and as the result inserted data will lost
so stop this

Create a sql file with name data.sql beside application.properties.

When spring starts the data in sql will be excuted.


#In spring 2.5 spring directly executing data.sql, becuase it expecting schema.sql in class path.

#As schema.sql is not there in path spring is failing fast.

#So ask spring to load enitties thorugh hibernate not using schema.sql

#please use below property

spring.jpa.defer-datasource-initialization=true
https://docs.spring.io/spring-boot/docs/current/reference/html/
howto.html#howto.data-initialization
21. Step 14 - Create a JPA Repository - V2:

Now, I would want to use this from our CurrencyExchangeController.


However, what we want to do in here is not the count or I don't want to return
all the things back.

What I would want to do is to actually search the table by from and to. So,
based on the from column and the to column,

I would want to actually find something and return that back.

And to be able to do that, you can actually extend the repository interface and
add in a few methods.

so, you can add findBy; which column name you'd want to find by? FromAndTo.
So, you'd want to do a findBy
Step 15 - Setting up Currency Conversion Microservice - V2:
25. Step 17 - Invoking Currency Exchange from Currency Conversion
Microservice - V2:

I can see that there is a response coming back. So, the quantity is 15, the
conversionMultiple is 65, and the totalCalculatedAmount is 975, and the
environment, the port where it's getting the response back from is 8000.

26. Step 18 - Using Feign REST Client for Service Invocation - V2:

we had to write a lot of tedious code around RestTemplate to get the Currency
Conversion service to talk with the Currency Exchange Microservice.

To make a simple REST API call, we need to write about 20 lines of code. And
imagine what would happen if in a Microservice architecture you have hundreds
of Microservices, they'd be calling each other and you'd need to repeat this kind
of code everywhere. And that's where Spring Cloud provides you with a
framework called Feign.

Feign makes it really, really easy to call other Microservices and to make use of
Feign.

we need to add a specific dependency into our Currency Conversion service

What we will use is, let's copy the starter-config, which uses the groupId
org.springframework.cloud. openfeign.

what we would want to do is we would want to be able to talk to the currency-


exchange-service from the CurrencyConversionController, and to be able to do
that what we need to do is to create a proxy.

So, what we'll do is we'll create a new class.


@EnableFeignClients - Scans for interfaces that declare they are feign clients.

Annotation for interfaces declaring that a REST client with that interface should be created (e.g. for autowiring into
another component).
Service name and host and port number is part of proxy class and remaining url resource path is part of
method definition in feign in proxy class as shown below.
27. Step 19 - Understand Naming Server and Setting up Eureka Naming Server - V2:

However, there is still a small problem.

What is the problem? In the CurrencyExchangeProxy

we are hard coding the URL of the currency-exchange-service.

So, if I would want to get the Currency Conversion Service to talk to a different instance of Currency

Exchange service.

what do I need to do?

I need to go here and change the URL 8001, 8002 and so on.

The state we would want to be able to get to is we'd want to be able to dynamically launch Currency
Exchange instances and distribute load between them.

Right now, let's say this instance is on port 8000. this is on 8001, and 8002.
As instances come up and go down, we'd want to be able to automatically
discover them and load balance between them.

If I, let's say, feign provide an option where you can hard code multiple URLs in
here, even that would not be a good solution because, let's say 8000 went down
and let's say a new instance was brought up on 8002.

Then you have to change the configuration of this application or the code of this
application all the time.

And that's the reason why we go for something called a Service Registry or a
Naming Server.

What would happen is in a Microservice architecture, all the instances of all the
Microservices would

register with a Service Registry.


29. Step 20 - Connect Currency Conversion & Currency Exchange Microservices - V2:

So, the Currency Conversion Microservice would register with the Service Registry, the
Currency Exchange Microservice would register with the Service Registry and all the other
microservices also would register with the Service Registry.

And let's say the Currency Conversion Microservice wants to talk to the Currency Exchange
Microservice.

It would ask the Service Registry, hey, what are the addresses of the Currency Exchange

Microservice?

The service registry would return those back to the Currency Conversion Microservice and
then the Currency Conversion Microservice can send the request out to the Currency
Exchange Microservice.

So, all the instances would register with the Naming Server or the Service Registry and
whenever Currency Conversion Microservice wants to find out what are the active instances,

it asks the Naming Server, gets the instances, and load balances between them.

I know there's a lot of theory.

Let's get our hands dirty and understand that further.

Let's get started with creating a Naming Server in Spring Cloud.

One of the options to do that is Eureka.


Naming server or service registry both are same.
The import is now done, the project is now ready for our use, and I'll go into the
NamingServerApplication and over here, what we need to do is to add in a annotation,
@EnableEurekaServer. So, @EnableEureka Server, this would import the EnableEurekaServer
class in. Over here, we are importing the annotation in and we have done
@EnableEurekaServer.
There are a couple of other configurations that are usually recommended by
Eureka.

What we are creating in here is a Eureka server and we don't want to register
with itself and to do that, there are a couple of properties that we would want
to add in.
All that we needed to do was very, very simple thing, add a dependency.

So, add Eureka client dependency and that's all is needed for you to connect
with Eureka.

owever, I would want to be really, really safe.

So, I'd typically actually configure the URL directly in the application.properties.
So, we can configure the naming server URL in the application.properties as
well.

So, I'm opening up the application.properties in currency-exchange-service and


configure eureka.
30. Step 21 - QuickStart by Importing Microservices:

Same as above step so skipping

31. Step 22 - Load Balancing with Eureka, Feign & Spring Cloud LoadBalancer -
V2:
now what I would want to do is to go to the currency exchange proxy and all
that I would need to

do to make it load balance between multiple instances is actually comment this


and actually add a new line with just the name.

So, what do we want to do is, we'd want the feign client to talk to Eureka and
pick up the instances of currency-exchange and do load balancing between
them.

All that magic would happen just by removing this URL.


So, what is happening in here is, inside the Currency Conversion Microservice,
there is a load balancer component which is talking to the naming server,
finding the instances, and doing automatic load balancing between them.

And this is what is called client-side load balancing.

And this is happening through feign.


And how does feign do load balancing? If you actually go into our currency-
conversion-service pom.xml,

if you look at the dependency hierarchy which is present in here, and just type
in load; l-o-a-d, standing for lord balancer, you'd see that there is a load
balancer, spring-cloud-starter-loadbalancer, which is brought into the class path
by spring-cloud-starter-netflix-eureka-client and this is the load balancer
framework that is used by feign to actually distribute the load among the
multiple instances which are returned by Eureka.

In the earlier versions of Spring Cloud, the load balancer which


was used was Ribbon.
and in the recent versions, Spring Cloud shifted to using Spring Cloud Load
Balancer as the load balancer.
The great thing is, if you're using Eureka and Feign, then load balancing comes
for free.

This is client-side load balancing and this comes for free for you.

What I would recommend you to do is to stop certain instances of Currency


Exchange and start new instances.

You would see that typically within 15 to 30 seconds, all the changes are
reflected and the load balancing

will be done between all the available active instances at that particular point in
time.

So, what we are creating in here is a very dynamic structure.

32. Step 22 - Setting up Spring Cloud API Gateway:

From java brains

an api gateway is an important concept in microservice architecture


it forms an entry point for external clients or really anything that's not a part
of your core microservice system.

so you're a back-end developer and you've built an application with


microservices your awesome online shopping application.
you're super happy with what you have
00:52
going on in the server your application
api is all ready and now you need to
00:56
hand it over to a front-end dev team
00:59
to write the ui client for it in html
01:01
and javascript

if there different url for different micro service. At the end after deploying
these in prod. Some issue came in picture and we need to refavtor the
code .
To fix those issues user service should be spilt into two MCs they are user
profile MC and session MC.
but hang on the ui guy yeah he's using it.
so you walk up to him and say hey listen

02:39
that user microservice you're calling
02:40
yeah you need to update the api why
02:43
because i'm refactoring the code

here are two new microservices that you

need to call now


02:50
are you kidding me man what the okay s
if you stop and think about what you did
02:56
wrong it basically boils down to a very
02:58
simple concept in computer science

you need it to build an abstraction


03:02
layer there's no reason
for the ui guy to know all the details
03:07
of each and every micro service that you
03:08
have in the backend

for the ui guy to know all the details


03:07
of each and every micro service that you
03:08
have in the backend
as a facade
it does nothing on its own
03:15
really except that it routes the
03:17
requests and responses
03:18
made by anyone outside your micro server
03:20
system and this abstraction layer is all
that they need to be worried about
03:25
you give this information to the ux guy
03:27
and you're done
03:28
the subtraction layer has all the apis
03:30
that you want to expose to the outside
03:32
world
03:33
and when the request comes in it knows
03:35
which actual micro service to call
03:37
in that sense this abstraction service
03:40
acts as a traffic controller or a
03:42
router it forms a single entry point for
03:45
all your micro services if you do this
it sits at the very edge of your
04:15
microservice architectural diagrams
04:17
and as a result it's sometimes referred
04:19
to as an edge micro service

to introduce an api gateway into the


04:31
picture first

every micro service in your system has


04:39
rest apis of their own but you obviously
04:41
don't want all of them to be accessible
04:43
to the outside world what are the apis
04:46
that you are
04:46
okay with other people calling what is
04:48
that contract going to look like
04:50
identify that first design and craft
04:53
that api

04:54
then you bring in this micro service
04:57
that will act as a gateway
04:59
you can either write your own or use one
05:01
of the available technologies
05:02
there's really nothing special to this
05:04
you're basically creating a bunch of
05:06
apis
05:06
in accordance to this public api that
05:08
you've decided to expose
05:10
but all it does internally is call one
05:12
of your existing microservices and pass
05:14
along the response

05:16
this technique is also called api
05:18
composition right you're composing an
05:20
Api out of other existing apis
you can do to take advantage of it for
1) example

05:38
you can add some kind of a monitoring
05:40
system that measures how many requests
05:41
are coming in
2) how long they're taking and all that

05:44
stuff this is great for operations and
3) support teams you can authenticate users here you can pass

05:49
security tokens like jwt you can

4)
implement security measures and prevent

05:54
stuff like
05:54
handling denial of service attacks
05:56
prevent access to certain users and ips

now if you end up needing to do all this


06:03
other stuff then you probably
06:05
want to avoid writing your own api
06:06
gateway and look at one of the existing
06:08
technologies
there are a bunch of options to choose
06:11
from one popular option is the open
06:13
source api gateway implementation
06:15
from the netflix microservice stack it's
06:18
called
zuul
there are other options including hosted
06:27
implementations by
06:28
nginx and aws 
no matter which one you
06:31
choose the patterns are pretty much the
06:32
sam

what are
06:37
the disadvantages of using the api
06:39
gateway pattern 

Disadvantage:
1)you've added
06:44
a network hop here
so things are going to be a little bit
06:47
slow period there's really nothing you
06:49
can do about it since the pattern kind
06:51
of requires it

2) second disadvantage let me ask you how

06:55
many of these api gateways do you need
do you just create one well one could be
07:00
a problem
07:01
you build microservices with fault
07:03
tolerance and redundancy in mind so that
07:05
even if some of these instances were to
07:06
go down
07:07
the system will still function what if
07:09
your one api gateway goes down
07:11
since it's a single entry point your
07:13
whole system goes down as a result
07:15
that's not good so yeah you can create
07:18
multiple api gateways
07:19
and split your incoming calls to them
07:22
using stuff like load balancers and
07:24
elastic ips
3) the other problem with api gateway is

07:27
that it can technically get a little too
07:30
complicated so let's say you have a web
07:32
client for your micro services

the other problem with api gateway is


07:27
that it can technically get a little too
07:30
complicated so let's say you have a web
07:32
client for your micro services
07:34
and you have an ios client team and an
07:36
android team
07:37
they might need different apis in
07:39
different gateway configurations
07:41
in that case rather than over complicate
07:43
the single api gateway
07:45
you can create multiple types of api
07:47
gateways one for each client
07:49
type and you can have those clients call
07:51
the right api gateway or
07:53
configure load balancers that route
07:55
requests to the right api gateway

some
07:58
people call this pattern. the ‘back end for front end ‘

32. Step 22 - Setting up Spring Cloud API Gateway:

In the previous few steps, we implemented Currency Conversion Microservice, Currency


Exchange Microservice, Limits Microservice and in typical microsevices architectures, there
would be hundreds of microservices like these and these microservices have a lot of common
features:
1) authentication,
2)
3) authorization,
4) logging,
5) Rate limiting.

Where do you implement all these common features?

That's one of the typical questions in a microservice architecture

and the typical solution is to go for an API gateway.

In the older versions of Spring Cloud, the popular API gateway to use was Zuul.

Since Zuul is no longer supported by Netflix.

Spring Cloud has moved on and now the recommended option as an API gateway is Spring
Cloud Gateway. In this step, let's get started with implementing a Spring Cloud Gateway and
look at the features it brings in.
34. Step 23 - Enabling Discovery Locator with Eureka for Spring Cloud Gateway:

In the previous step, we launched up our Spring Cloud API gateway. In this step, let's start playing with
it.

One of the things we did earlier is we registered the API gateway with the Eureka naming server.

Let's go to our favorite urls.txt;


Let's see what would happen if I execute this. localhost:8765/CURRENCY-EXCHANGE/currency-
exchange/from/USD/to/INR.
Oops, error. It says NOT_FOUND.

What we are doing in here is we are passing in the name that currency exchange is registered with in
here and we'd want the API gateway to talk to Eureka with that name, find the server and then
execute requests to this URL.

However, as we see, it's not enabled yet.

To enable this feature in Spring Cloud API gateway,

we need to add in a application.property.


spring.cloud.gateway.discovery.locator.enabled=true
you can implement all the common features in your API gateway and the API Gateway would take
care of the common features and then invoke the currency exchange.

If you'd want to implement things like authentication, you can implement them on API Gateway and
you can only allow those things which are authenticated in your microservices.

So, all the authentication logic can be implemented on the API gateway.
In this step, we learned how we can proxy through the API gateway to other microservices using
Eureka using the Cloud Gateway Discovery Locator feature.

36. Step 24 - Exploring Routes with Spring Cloud Gateway:

In the previous step, we learned how to build routes through the Eureka Naming Server and redirect
all the requests through the API Gateway.

In this step, let's look at how you can build custom routes.

One of the options to build custom routes is to actually create a configuration file.

So, let's create a new class.

I'll call this ApiGatewayConfiguration


and because this would contain a few beans, I'll actually mark this as configuration.

let's define a few custom beans.

What we are creating in here is something called a route locator.


So, let's create a RouteLocator bean by creating a method which would return a gateway router and
to be able to create a route locator, we would need a RouteLocatorBuilder.

let's call this builder and using this builder, we can customize the routes which we would want to use.

What we want to do is to create the route locator mapping and return it back.

So, return builder.routes.build. This is when we are not customizing any routes in here.

What we want to do is to customize the routes.

I can start customizing it. So, routes, .route and over here I can define a function defining the route.
If the path of the request is .get, then what do we want to do?

We would want to do a redirect.

We'd want to redirect it to a different URI.

http://httpbin.org:80 is a simple HTTP Request & Response Service and it is a public site.
You can see that you are getting a response back from a specific server.

So, this httpbin.org exposes a lot of API.

What we are doing is, we are hitting one of these APIs.

it's returning a response back with a

1)few headers;

2) the origin,

3)where is the request coming from and

4)what was the original request URL.

what we also want to do is we would want to add a header or a path parameter.

Now, over here I can configure the filters.

So, I can say filters and I can configure a Lambda function for the filter as well.

So, f lambda function and what do we want to do as part of the filter? f.;

we'd want to, let's say, add a request header or a request parameter.

You can do a lot of things as part of your filters.

Let's just add a request header.


So, before routing the request to the new URL,

You can also add request parameter


So, I'll say .route, and over here we can define another route. What we want to do is the URL for the
currency-exchange service.

This URL looks a little complex, right?

currency-exchange is repeating twice.


What I can do is actually look for /currency-exchange and then redirect to the naming server.

What I would want to have is URL something of this kind.

So, I would rather have a URL of this kind than this kind.

How can I get that done?

what I would want to do is I would want to redirect it using the naming server and I would also want
to do load balancing.

The way you can do that is by configuring a custom route in here.

So, what I would do is go ahead and disable the application.properties.


.

So, if a request starts with currency-exchange, what I would want to do over here is talk to Eureka,
find the location of this service and load balance between the instances which are written.
//if we want to redirect currency-conversion-new to currency-conversion-feign
http://localhost:8765/currency-conversion-feign/from/USD/to/INR/quantity/10
but what we would need to actually do is we would want to define the regular expression, identifying
the next thing as a segment.

How do you define a regular expression identifying this as a specific segment?

(?<segment>.*)

So, this is the thing which we have added in; within parentheses (?<segment>.*)

and following this we can over here we'd want to use the same segment.

So, whatever follows currency-conversion-new , I would want to append it to currency-conversion-


feign.
The way I can do that in here is by saying ${segment}.

(?<segment>.*) is regular expression

segment here is path segment

(?<name>X) named capture group in java SE regular expression

X? X, once or not at all


‘. ‘ Any character (may or may not match line terminators)

* zero or more times

(?<segment>.*) - That means replace any character which occupies zero or more times in ${segment}

37. Step 25 - Implementing Spring Cloud Gateway Logging Filter:

In the last step, we saw how you can actually add custom filters on specific paths.

In API gateway you can also add global filters.

let's say, I would want to log every request that goes through the API gateway.

and for that, I would want to create a new filter.


What do I want to log?

I'd want to log some information about the request.

Where is the information about the request present?

It's present in the first parameter exchange


What is cross cutting:
Before understanding the Crosscutting Concern, we have to understand the Concern.
A Concern is a term that refers to a part of the system divided on the basis of the functionality.
There are two types of concerns:

1. The concerns representing single and specific functionality for primary requirements are known as core concerns.
OR
Primary functionality of the system is known as core concerns.
For example: Business logic
2. The concerns representing functionalities for secondary requirements are referred to as crosscutting concerns or system-wide concerns.
OR
The crosscutting concern is a concern which is applicable throughout the application and it affects the entire application.
For example: logging, security and data transfer are the concerns which are needed in almost every module of an application, hence they are cross-cutting concerns.
Courtesy

This figure represents a typical application that is broken down into modules. Each module’s main concern is to provide services for its particular domain. However,
each of these modules also requires similar ancillary functionalities, such as security logging and transaction management. An example of crosscutting concerns is
"logging," which is frequently used in distributed applications to aid debugging by tracing method calls. Suppose we do logging at both the beginning and the end
of each function body. This will result in crosscutting all classes that have at least one function.
if you'd want to implement things like authentication for all the requests, then this might be a right
place to implement that as well.

In the last few steps, we discussed a lot about Spring Cloud Gateway. Spring Cloud Gateway is an
awesome way to route to your APIs and implement your cross-cutting concerns things like

a)security

b) monitoring/metrics.

These are the best things that you can implement in a Spring Cloud Gateway.

This is built on top of Spring WebFlux and that's the reason why we needed to use the reactive
approach.
Some of the important features of Spring Cloud Gateway are it can match requests on any request
attribute.

Earlier, we saw how you can actually match based on the path.

In addition to that, actually, you can match based on a lot of different things.

So, if you scroll down, you can match based on headers, you can match based on host, you can match

based on the request method.

you can match based on a query parameter.

So, you can match your request based on a lot of different parameters.

so, you can match routes on any request attribute and you can define predicates and filters.

Over here, what we are defining is how to match, and that's what is called a predicate.
We saw that Spring Cloud Gateway integrates with the Spring Cloud Discovery Client as well;

it also provides load balancing.

We also looked at how you can do a path rewriting using Spring Cloud Gateway.
We looked at several examples related to services which are proxied through Cloud Gateway.

The architecture is very, very simple.

We define a handler mapping and based on the handler mapping, the appropriate handler is called.

And as part of the handler, we have a number of filters which would be executed and finally, the
request would be sent out to the service, which needs to handle that request.

And when the response comes back, you can also do a lot of things with it and you can send it back to
the client.

38. Step 26 - Getting started with Circuit Breaker - Resilience4j:

we have talked about the fact that in a microservices architecture , there is complex call chain.

As shown in the example here, a microservice can call another microservice, that microservice might
be dependent on another microservice, and so on and so forth.
And what would happen if one of these services is down or is very slow?

Let's say Microservice4 is down or it's very, very slow.

What would happen?


There would be an impact on the entire chain.

If the Microservice 4 is down, then Microservice 3 also will be down, Microservice 2 also will be down
because these are all depending on Microservice4.

Even if it's slow, then there is a corresponding impact on the other microservices too.

In these microservices, there will be a build-up of calls.

Because this microservice is slow, all these chains also get impacted.
So, the questions are,

Q1) can we return a fallback response if a service is down? If I see that the Microservice4 is down, in
the Microservice3, can I return a fallback response?

Use Cases:

Ans) This might not always be possible. For example, in the case of a credit card transaction or
something

of that kind, you do not have any fallback responses possible.

But in the case of a shopping application, instead of returning a set of products, you might return

a default set of products; that's possible.

-------

Q2) The other question to consider is, can we implement a circuit breaker pattern to reduce the load?

Ans) If I see that Microservice4 is down, instead of repeatedly hitting it and causing it to go down,

can I actually return the default response back without even hitting the Microservice?

Now, there are a lot of nuances to the Circuit Breaker pattern.


We'll talk about them when we implement the Circuit Breaker pattern a little later.

The other question to consider is,

Q3) can we retry requests in case of temporary failures? If there is can I retry it a few times and

Ans) only when it has failed multiple times, I return a default response back?

The last question is,

Q4) can we implement something like rate limiting?

I'd want to allow only a certain number of calls to a specific microservice in a specific period of time.

If you are using Spring Boot, then there is a Circuit Breaker framework which is available, which is
called Resilience4j.
If you do a Google for Resilience4j getting started, you would land up on this specific page.

Resilience4j is a lightweight, easy-to-use fault tolerant library inspired by Netflix Hystrix.

In the previous versions of Spring Boot and Spring Cloud, Netflix Hystrix was the recommended circuit
breaker framework.

However, with the evolution of Java 8 and functional programming, Resilience4j has become the
recommended framework.
You'd see that we already have starter-actuator in here.

So, what we'd do is, we would need two additional dependencies;

starter-aop and resilience4j-spring-boot.


Now, to understand the circuit breaker feature what we'd do is, we'd create a new controller.

39. Step 27 - Playing with Resilience4j - Retry and Fallback Methods:

let's focus on the Circuit Breaker features.

Let's start with a very, very simple feature of CircuitBreaker frameworks, which is called Retry.

So, all that I would need to do is to add in @Retry.


But this API method will not be retried because this would succeed at the first time.

So, what we'll do is, we'll add some logic in here which causes failures.

So, let's not really add retry right away.

So, let's make this fail and then, let's focus on retry.

So, what I would do is, I would actually create a new RestTemplate and let's just call some dummy
API.

This URL will not work because we don't have anything launched up there

But we just hardcode something which we know will fail.

So, let's say we are calling another API and getting that back as is.
And now, this would fail, right? So, If I just have the code as it is and wait for the application to
restart and pick up the change

and if I run this, Sample API fails, right? It returns a slash error, it says I/O error on GET request for
this.

Now, let's say this microservice which we are calling is down temporarily

and sometimes you know that if you invoke the same thing multiple times, it might give you a
response back.

And in those kinds of situations, you can go for retry.

So, if you add @Retry and if you do a Ctrl + Shift + O to organize the imports, you should see an import

io.github.resilience4j.retry.annotaion.Retry and over here, I would want to use the default


configuration.

So, I can say, (name = "default") for now.

So, we are using the default retry configuration and

what we will also add in is a simple logger called private Logger logger =
LoggerFactory.getLogger(CircuitBreakerController. class)
And if you go back and see, "Sample API received" three times.

So, what you are seeing in here is that the retry is happening three times.

So, in this method, when it's executing, if there's an exception, what would happen is, it would be
retried thrice

and if the retry fails all the three times, only then it would return a error back.

Now, you might be wondering, how can I configure a specific number of retry intervals.

So, what we'd do is, we create our own specific retry configuration .

So, let's go to application.properties and go to our


another thing you can do actually over here is also configure a fallback method.

So, one of the attributes on the annotation is fallback and you can configure what is the fallback
method.
You'll get a problem, we'll see what the problem is, very shortly.

It says, UndeclaredThrowableException.

What's happening?

CircuitBreakerController.hardcodedResponse.
We have a method hardcodedResponse, but there is nothing which accepts throwable as an
argument.

So, over here, you need to add a parameter.

The parameter should be of the type throwable.

Let's add (Exception ex) {, as we know, exception class extends Throwable

you can also have different responses returned back for different kinds of exception.

So, if I get a runtime exception, I would want to do something else.

If I get a different kind of exception, I would want to do something else.

So, you can have different fallback methods for different kinds of exceptions.

Configuring interval retries:

So, for example, I can configure what should be the interval between retries.

So, if an API call is failing, I would wait for a little while and then make the API call again.

I can configure how much time to wait for. The configuration is waitDuration and you can configure 1

second, for example.


if you actually look at the logs right now, you would see that each of this retry is done after one
second, that's exactly what we configured in here.
Here if wait duration configured is

1sec – really waiting for 3 sec

2sec - really waiting for 4 sec

3sec - really waiting for 5 sec


The other thing you can also configure is exponential backoff.

What is exponential backoff?

and now you'd say that the response takes a little bit more time.

Why is it taking a little bit more time?

Because each subsequent request, it would wait for a little longer.

You can see that the

first retry happened after one second.

The second retry happened after one and a half seconds.

The third retry happened after almost two and a half seconds
and the next retry took about four seconds, almost four seconds.

So, you can see that each subsequent retry is taking longer and longer, and that's what is called
ExponentialBackoff.

So, whenever you are working on the Cloud, for example AWS, and you are working with some API,
most of the APIs use exponential backoff.
So, if I'm calling an API and the first attempt is failing, what it would do is it would make the next

attempt after, let's say, one second. The subsequent attempt, that's the third attempt, will be made
after two seconds.

The attempt after that would be made after four, eight, 16.

So, it's exponentially increasing

and that's one of the features that the resilience4j retry also supports.

In this step, we looked at the retry features which are present in resilience4j.

Use case:

These are useful when a service is momentarily down. down.

You'd just give the service a little bit of time and then call it again.

However, what if the service is really down for a long time?

That's the kind of scenarios where we would go for a Circuit Breaker pattern.

Let's explore that further in the next.


40. Step 28 - Playing with Circuit Breaker Features of Resilience4j:

In the previous step, we played with Retry. In this Step, let's play with Circuit Breaker.

I'll start with the default configuration without any specific configuration as such.

So, @CircuitBreaker (name = "default", fallbackMethod = "hardcodedResponse")

Now, to see the magic of CircuitBreaker, what we would need to do is to fire a lot of requests to this
specific API.

How can I fire a lot of requests to this specific API?


One of the options that we have is use the watch command. So, you can use any option where you
can actually fire a lot of requests.

You can even manually fire these requests as well by just refreshing the screen.

What I'm using is a watch utility, which is present in Unix.

What I'm doing is, watch curl and pasting in the URL. See what would happen.
You can see that it's actually sending a request every two seconds

and what I want is a little bit more than that.

want to send the request every, I want to be able to send 10 requests per second.
So, what I'm saying in here is, send a request every 0.1 second.

So, watch -n 0.1 curl localhost:8000/sample-api.

It's not really important for you to replicate this in your local machine.

If you just refresh it 100 times, then you should be able to see it in action too.

So, let's go ahead and run this. Now,


you can see that it's firing 10 requests a second and what you would see right now when you go back
to the console is that the CircuitBreaker Sample api is being called up to a certain extent

and after that, you'd see that there are requests going on.

However, you'd see that there are no method calls in here.

So, what is happening in here?

The CircuitBreaker is returning the response back without even calling this method.

Let's see that in action again. So, you can see that there is no log being generated in here.

That means the method is not being called, directly

the fallback method is being called and the response is returned back.

However, you can see that there are requests being fired.

If a microservice is down, then what does the CircuitBreaker do?

Hey, this microservice calls everything is failing.

Then, why do I need to really call it and add load to it?

Why can't I return a default response back directly?

So, that is what the CircuitBreaker does.

It will break the circuit and it will directly return a response back.

Now, you might be wondering, how do I know if the microservice is back up and I can call it again?

And to be able to answer that, we'd need to understand how a CircuitBreaker works.
If you go to the resilience4j documentation that we looked at earlier and click CircuitBreaker,

you'd see that there are multiple states for a CircuitBreaker.


A circuit breaker can be in three different states:

1)CLOSED,

2) OPEN and

3) HALF_OPEN.

What are the different states?

Closed is when I am calling the dependent microservice continuously. So, in a closed state, I'll always
be calling the dependent microservice.

In a open state, the CircuitBreaker will not call the dependent microservice,

it would directly return the fall-back response.

And in a half_open state, a CircuitBreaker would be sending a percentage of requests to the


dependent microservice.

and for rest of the requests, it would return the hardcoded response or the fall-back response back.

When does a CircuitBreaker switch from one state to another?

For example, the CircuitBreaker is in the closed state. When you start the application up, the
CircuitBreaker is typically in a closed state. Let's say, I'm calling the depenedent microservice 10,000
times and I see that all of them are failing or I see that 90 percent of them are failing

In that kind of scenario, the CircuitBreaker would switch to a open state.

Once it switches to an open state, it waits for a little while; there's a wait duration that you can
configure.

there's a wait duration that you can configure.


After thatwait duration, the CircuitBreaker would switch to a half_open state.

During the half_open state, The CircuitBreaker would try and see if the dependent microservice is up.

So, it sends a percentage of the request, you can configure how much percentage it would send, let's

say 10% or 20% of the requests to the dependent microservice, and if it gets proper responses for
that, then it would go back to the closed state.

If it does not get proper responses, then it would go back to the open state.

And that's what we are seeing in action in here.


so, at the start launch of the application, you can see that the CircuitBreaker was firing a lot of
requests to the dependent microservice.

After a certain number of failures, the CircuitBreaker went into open state

and when it goes into an open state, you can see that there is a gap between these two log intervals.
There is almost a 40 seconds gap

and after that, you can see that it's making lesser number of requests.
You can see that it's making only about 10 requests per minute.

It's checking if the service is back up.

If the service is back up, then it would go back to the closed state.

But in our case, the service will never be back up.

so, what it does is it waits for one more minute and then it retries again.

So, you can see that at 14:44, it's again trying to make a few requests.
It sees that it's down. 14:45,

it again tries to make a few requests.

So, every minute or so, you can configure the duration, the CircuitBreaker retries a few requests and
see if it's getting a response back.

If you scroll further down in the documentation, you can see that there are a wide range of things
ou can configure on the CircuitBreaker. failureRateThreshold configures the failureRateThreshold in
percentage.

when the failure rate is equal or greater than the threshold, the CircuitBreaker transitions to open

and starts short-circuiting calls.

slowCallRateThreshold 100.

So, you can also configure a specific slow call duration. So, you can say, any call above 60 seconds,

this is the default value, you can actually configure your own value for it.

Any call which takes more than 60 seconds, is treated as a slow call and if 100% of the calls, by
default, are slow,

then the circuit again becomes open. So, you can see that there are a wide range of configurations
that are possible in here.

I would recommend you to spend some time looking at all the different configurations that are
possible.

If you would want to see how this can be configured for Spring Boot, the best place to look at would
be the Spring Boot 2 documentation.

Only 90 % of the calls fail then circuit should open

42. Step 29 - Exploring Rate Limiting and BulkHead Features of Resilience4j - V2:

In this step, let's try and look at the Rate Limiting and the BulkHead features.
Let's start with the rate limiting.

So, what is rate limiting?

What is rate limiting?

Basically, rate limiting is all about saying, in 10 seconds, I'd want to only allow 10000 calls to the
sample API.

So, that's what we are setting in here.

So, we are setting a time period and during that time period, I only want to allow a specific number of

calls and you are configuring it to a specific API.

So, this specific API method, I only want to allow 10000 calls.

That is what is called rate limiting.

So, for all the API methods which are present in here, you can set different rate limits.

Over here, you can have different names for each of these APIs.

Now, how can you configure these limits?


and after that, you can also configure how many requests do you want to allow in 10 seconds period.

How many do you want to allow?

Two requests in every 10 seconds.

I'll comment the CircuitBreaker,

I'll comment the RestTemplate calls and I'll just return sample API back.
I was running watch command earlier and I would now run it with -n 1.

So, I'm sending a request every one second to the sample API.

You can see that some of the requests are successful, they are returning sample API back,

but you'd see that a few other responses would be failing.


So, you can see that this is giving me does not permit more calls.

If I go to the browser and try and fire in a few requests, success and the next one is getting an error.

So, it's saying, RateLimiter 'default' does not permit further calls. So, you can see that the RateLimiter
is cutting the service off.

In addition to RateLimiter, you can also configure how many concurrent calls are allowed.
That's called BulkHead. For each of the APIs inside a microservice, you can configure a bulkhead.

You might also like