Spring Cloud

|
Divnesh BLOG

Spring Microservice

Microservice is becoming a popular choice for implementing applications that need to be highly scalable, deployable, reliable, etc. Many organizations have slowly started moving towards Microservices architecture based applications.

 

Early adopters of microservices are Netflix, Amazon, Uber, LinkedIn, Twitter, etc. Netflix also contributed heavily to the developer community by outsourcing their microservices solutions.

 

Spring framework provides required components for implementing microservices in a simpler way.

 

In this course, we will discuss creating, packaging, and deploying microservices using Spring Boot and Spring Cloud components.

 

 

Demos

Spring Version

Remarks

Demos shown in videos

Spring Boot - 1.5.8.RELEASE and Cloud Version is Dalston.RELEASE

 

Demos on Cloud Config, Ribbon, Hystrix API's that are available for download

Spring Boot-2.5.3 and Cloud Version is 2020.0.3

Upgraded to the latest version

Demos on Zuul, and Zipkin APIs that are available for download

Zuul and Zipkin server microservices use Spring Boot-2.3.9.RELEASE and Cloud Version is Hoxton.SR6. But the other microservices are upgraded to use the latest Zipkin client libraries.

As these libraries are no longer supported and maintained by Spring Cloud.

Demos on Consul, Spring cloud LoadBalancer, Spring cloud Gateway, Resillience4j, and Prometheus APIs that are available for download

Spring Boot - 2.3.2.RELEASE and Cloud Version is - Hoxton.SR6

 

 

 

Monolithic Application

Have you ever written an application that looks like this?

 

presentation --> Business --> Persistence --> Database

 

Do you deploy the entire application as a single WAR file or JAR?

 

  • Well, it means you have been writing monolithic apps!
  • Mono – single. If your entire codebase is a single war/jar file it means, it’s a monolithic app.
  • In monolithic apps, all the functionalities are part of a single process. Such an application may consume APIs of other applications and may also expose some of its functionalities as services.
  • Twitter, Facebook, Amazon, etc all started off as monolithic applications.

 

Disadvantage :

  • There are several monolithic applications functioning without any problem then why is it that it’s not considered an ideal solution?

 

The Monolithic application was a good solution for the requirements of earlier times.

 

But with recent needs for better user experience, monolithic applications fail to deliver the following functionalities:

 

  • The entire app must be redeployed for a small change, thus increasing the downtime
  • Larger the app, larger deployment time and startup time is required
  • If specific parts of the application experience a larger load entire app must be deployed in multiple servers to take care of scaling. This takes the resources and increases maintenance problems
  • Large code becomes intimidating
  • If later any functionality can be written using python or scala or C#, modification is extremely difficult.

 

Alternatives :

  • There are alternatives for monolithic architecture, such as Service Oriented Architecture, Microservices, etc.

Microservice

Microservice is an architectural style. In this style, the application is made up of smaller ( or micro ) apps that communicate with each other, through open protocols like HTTP.

 

Microservices are distributed in nature. It can either decompose a monolithic app into a microservice or can develop a microservice-based solution from the beginning.

 

The characteristics of Microservices are that they are:

 

  • individually developed, i.e. development of one microservice does not depend on the completion of another microservice
  • individually deployed, i.e. one microservice can be deployed in a separate docker image with a different environment from another
  • individually maintained, i.e. changes to a microservice does not affect the entire application
  • individually scaled, i.e. if one of the microservice is experiencing an increase in load then that can be scaled alone
  • communicated through lightweight protocols like REST
  • individually monitored, i.e. errors and performance of a separate microservice cannot be found without bothering about the performance of other microservices
  •  organized around business capabilities. In other words, the application is split into smaller services which are not based on technology stack (like presentation, DB, etc.) but based on specific business functionalities
  • dumb as they do not differentiate between communication originating from one microservice to another (Microservices uses "Dumb Pipes and Smart Endpoints" - Dumb pipes are the communication channels between microservices. And the microservices act as Smart Endpoints as they determine the specific recipient of the communication)
  • with decentralized databases
  •  in strong support of DevOps

 

SOA and Microservice

 

What is the difference between an Orange and an Orange segment? You will find more similarities than differences. The same is the case with SOA ( Service Oriented Architecture ) and Microservices. You cannot talk about microservices without talking about SOA.

Microservices are fine-grained SOA. An SOA has ESB ( Enterprise Service Bus ) whereas Microservices have a much simpler and direct communication mechanism.

Adrian Cockcroft at Netflix: "We used to call the things we were building on the cloud "cloud-native" or "fine-grained SOA," and then the ThoughtWorks people came up with the word "microservices." It’s just another name for what we were doing anyway, so we just started calling it microservices, as well. … You’re trying to find words for things that resonate"

 

Steve Jones, MDM at Capgemini: Microservices is SOA, for those who know what SOA is.

 

  • Amazon: Amazon’s successful evolution from retailer to technology platform is its SOA (service-oriented architecture), which broke new technological ground and proved that SOAs can deliver on their promises.
  • Uber: We decided to follow the lead of other hyper-growth companies—Amazon, Netflix, SoundCloud, Twitter, and others—and break up the monolith into multiple codebases to form a service-oriented architecture (SOA). Specifically, since the term SOA tends to mean a variety of different things, we adopted a microservice architecture.

 

Similarities:

  • Both address issues of monolithic architecture
  • Both focus on splitting the application into smaller individual components
  • Both uses service endpoints for communication
Though they are similar, SOA failed whereas Microservices are trending. This is due to two reasons:

  • SOA has been there for a decade and a lot of lessons were learned on the mistakes arising from it
  • The tools needed for SOA to succeed are available only now. Hence one can say that Microservice is SOA done right.

Differences:

  • Communication: Microservices use simpler communication protocols like REST, Advanced Message Queuing Protocol (AMQP). SOA accommodated more of SOAP based communication protocol for its popularity.
  • Security: SOAP is with complex security standards. Also, XML can contain even executable data thus increasing security risks. Microservices now use advanced resilience concepts like a circuit breaker, fallback, OAuth2 integration, etc.
  • Complexity: SOA is with complex service orchestration as services have strong contractual agreements. SOA used ESB as the central command mechanism. Microservices have a simpler contract agreement.
  • Implementation: SOA implementation differed from each other and many were vendor dependent.
  • DevOps: In SOA, one had control over the development aspects. So, one was still dependent on other teams for maintenance and deployment operations.  Microservice is best suited for DevOps as each team develops and maintains but also deploys. Thus, one team is responsible for the entire life cycle of the microservice.

If monolithic is bad, people would not have been using it.

 

Monolithic has its advantages (if it’s reasonable in size)* such as:

 

  • easier to get the bigger picture of the application, as the entire code base is in one place
  • only one jar/war file must be deployed
  • relatively simple and straightforward to develop
  • dependency on network latency and security is greatly reduced

Microservices is a buzzword technology gaining a lot of traction. Based on the need, competence, and size of the applications, one may have to choose between Monolithic, SOA, Microservice, etc.

 

Summary :

 

  • Monolithic applications are deployed as a single file
  • Monolithic applications have problems in deployment, scaling, technology, etc
  • Microservices is an architectural style in which the bigger single application is broken down into loosely coupled services
  • Microservices are individually maintained, deployed, developed, tested
  • Microservices intercommunicate using lightweight protocols like REST.
  • Each Microservice can use its own set of technologies.

Application :

a telecom application called InfyTel and delve into evolving this app from its monolithic architecture to a full-fledged microservice version in multiple stages.

 

The first stage of the application is its monolithic version.

run UI : npm install
npm start 

 http://localhost:4200

Issue with monolithic approach : 
The monolithic version of our application, though working flawlessly, has issues. For example,
  • If we have to scale up the add friend functionality what should we do?
    • We will have to scale the entire application though only add friend functionality is facing a peak request rate. This leads to a loss of resources
  • If the get plan functionality can be better implemented in python, what should we do?
    • This is difficult as we are stuck with one code base written in Java.
  • If we need to update the logic of call details, what should we do?
    • We end up stopping the entire application when we deploy the newer version. Thus even unrelated functionalities get affected
  • If we make a modification to Customer functionality, what is the impact?
    • We have to do a regression testing of the whole application
How does one go about splitting a huge monolithic application into microservices? There are several considerations to choose from. Briefly, they are:

  • Service Boundaries: We have to split functionalities based on their bounded contexts. Bounded contexts define the scope of the services such that a change in one does not affect other services. This ensures that the services are autonomous and are loosely coupled with others. This is based on Domain Driven design principles. Each application/domain is split into subdomains.
  • Single Responsibility: Each Microservice should do only one thing. It should be responsible for the only thing.
  • Common Closure Principle: Functionalities that change should be packaged together so that changes to one do not percolate to other teams.
In order to avoid the issues of the monolithic version, we are going to split the single monolithic application into 4 microservices ( Customer, FriendFamily, Plan, CallDetails ). The application now looks like below:


Why did we split our monolithic into 4 microservices?
  • The call details have a 'single-responsibility' of only dealing with the call details of a given customer.
  • The plan has a 'single-responsibility' of only dealing with plan related functionality of getting all plans and getting a specific plan. 
  • The friend family has a 'single-responsibility' of only dealing with adding and retrieving friends. 
  • The customer has a 'single-responsibility' of only dealing with customer functionality like login, view profile, register. 
Can we have to add family to another and fetch family in another? The answer is maybe not, because if the Family structure changes the both have to be changed. The granularity of services is an architecture choice.

  • Create 4 different spring boot applications:
    1. infytel-customer
    2. infytel-calldetails
    3. infytel-plans
    4. infytel-friend-family
  • All of them will point to the same database, but they have their own port and application names
  • There is no change in the table script
    • The functionalities retained in different microservices are: 

issue with microservice with shared Common Schema DB:

Microservices are by nature distributed applications. One immediate impact of microservices is whether the database should be shared or distributed?

Having a single shared DB is dangerous. If the DB fails the entire application fails. Hence the best practice is to not use a shared DB.

Also, microservices are supposed to be independent of each other with loose coupling. But in the approach we have taken,

  • the Customer microservice is using FriendFamily table which actually belongs to FriendFamily microservice.
  • the Customer microservice is also using the Plan table which belongs to the Plan microservice.
This is because the Customer has a one to one relationship with the Plan table and one to many relationship with the FriendFamily table through foreign keys. This is tight coupling and not a good approach.

The right approach in dealing with databases in a microservice architecture is:

  • Each microservice should have its own set of tables in a separate database or schema
  • One microservice should not try to directly access tables owned by another microservice. If there is a data dependency then a microservice should call another service through REST API to fetch data.
  • Foreign key constraints should not be there. We can still have columns to establish a link between entities.
  • We should not use joins between tables owned by two different microservices. If you need data from both tables to make a database call to fetch data owned by own service and make REST call to fetch data from the other. This pattern is called API Composition.
How to use independent DB for Infytel microservice?
  1. Remove foreign key constraints from all the tables
  2. All microservices should have only entity classes related to their own functionality alone. Therefore remove other entity classes from the customer microservice
  3. Since there are no foreign key constraints and no other entity classes in the microservices, add endpoints in the microservices which will provide relevant data.
  4. View Profile endpoint in customer microservice currently fetches data from Friend and Family and the Plan table directly. Now it needs to get these data from other microservices.
  5. In Friend and Family microservice, create a new endpoint for fetching friend and family details for a customer
  6. In Plan Microservice, create a new endpoint for fetching plan details for a customer
  7. Modify View Profile endpoint in Customer Microservice to invoke these two new endpoints for fetching relevant details


Observation of using Microservice with independent DB :
We can see that even though we have avoided joins at the table level, we have ended up increasing the REST endpoints. Because of this, the complexity in the application level has increased. Also, the number of network calls needed also has increased. Initially, the profile request involved one call to the customer REST endpoint and one call to the DB. Now it has become 3 calls to DB and 3 calls to endpoints in different microservices. Also, joining at the API level is slower than table level join.

Intro to Cloud
Deploying our application on the cloud makes hardware maintenance much easier as it becomes the responsibility of the cloud provider. But just deploying it in the cloud does not mean our application is taking advantage of the facilities given by the cloud. For example, moving our application to cloud only relieves us from the problems of maintaining the underlying infrastructure. We can set up virtual machines with any configuration we need.


But cloud-enabled applications are not cloud-native applications. Cloud native applications are specifically written in such a way that it takes advantage of the cloud. For example,

  • Will your application take advantage of multiple instances of related services and load balance across them?
  • In the cloud, a lot of things can go wrong. If a service is suddenly unavailable, is your application resilient enough?
  • In the cloud, instances can be increased, decreased, moved around, and so on. Will your application automatically adapt to such changes?
If yes, then the application is cloud-native as it was designed to work on cloud advantages.


Our applications have to be cloud native, in other words, they should be written in such a way that it can make use of the advantages of the cloud ecosystem. Elasticity, availability, security are some of the features we get by deploying our application in a cloud environment.


We have just seen how to create microservices using spring boot and how they can interact among themselves. As part of this course, we are also going to see how we can develop such microservices such that they are cloud enabled.


But despite these issues, we use this approach as the benefit of loose coupling and independence of microservices far outweigh these cons.


Challenges in Cloud:
  • Since the services are deployed at random hosts and ports, how can Customer microservice know where to find the other microservices?
  • Most of the configuration details of the 4 microservices are similar. How can we avoid this duplication?
  • Since in cloud plan and friend-family are dynamically deployed, how will the customer microservice know where to find them?
  • When we scale friend-family in the cloud, how customer service can load balance the load across multiple instances of them?
  • What if while fetching the profile the request friend-family service fails. How to bring in resilience?
  • Since the application is now spread across as multiple microservices, how do we trace the flow of a request?
Cloud Solution :
We have many solutions to the challenges posed by cloud native applications. Some of them are:
  • Netflix OSS
  • Spring Cloud
  • Vertx
  • Restlet
  • Akka
  • Ninja
We will be using Spring Cloud in this course. Spring Cloud also uses open source components from Netflix.

What is Netflix OSS?
Netflix also a tech giant is an online entertainment industry catering to 62 million users. The company came up with different in-house solutions to cloud microservice problems and they made their solutions open source. They are the pioneers of Microservice Architecture. Netflix OSS is an open-source project for a variety of solutions including build, deployment, data analytics, etc.

All their solutions are currently being used in their products and have proven their effectiveness. Many organizations have adopted Netflix OSS solutions for their projects.

What is Spring Cloud ?
Spring Cloud is a suite of projects from Spring. As Netflix OSS components are tough to use in its raw form Spring Cloud framework is used.

Some of the major projects under the Spring Cloud umbrella project are:
  • Spring Cloud Config
  • Spring Cloud Netflix
  • Spring Cloud Security
  • Spring Cloud Sleuth, etc
The Spring Cloud Netflix provides spring integration for the common components from Netflix OSS with Spring Boot

Centralized Config
Let us consider the configuration details for microservices. All microservices have the below configuration, apart from application name and port:
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/infytel
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

All these are placed inside the application itself. The problem with this approach is that if any configuration requires modification then these configurations must be changed in multiple services and redeploy them. If a service has multiple instances, then all the instances must be redeployed.

Storing Configuration

What are some of the alternatives in placing the configuration details?

  • Placing the configuration as environment variables - but there is a limit on the creation of environment variables
  • Placing them in external files – but access to such file system is difficult in the cloud

An ideal solution would be to use an external version control system like GIT, as it not only avoids the above-mentioned problems but also gives traceability of changes.

Cloud Storage

In the next stage of our application, let us use Cloud Config to access our configurations from GIT.

https://github.com/PlaygroundConfiguration/SpringMicroservices.git
How to use Cloud Config?
  1. Create a GIT repository
  2. Create a file called application.properties in the repository
  3. Place the common properties in the application.properties file
    1. spring.datasource.driverClassName=com.mysql.jdbc.Driver
    2. spring.jpa.hibernate.ddl-auto=update
    3. spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
  4. Create separate properties file for each microservice with the name of the file matching the spring.application.name of the service
  5. Place the respective properties in their respective files
  6. Create a spring starter project for config server with relevant dependencies
  7. Add information of the git server in the properties file of the config server
    1. server.port=1111
    2. spring.application.name=ConfigServer
    3. #If InfyGit is using
    4. spring.cloud.config.server.git.uri=https://infygit.ad.infosys.com/spring-microservice/infytel.git
    5. # If GitHub is using
    6. #spring.cloud.config.server.git.uri=https://github.com/PlaygroundConfiguration/SpringMicroservices.git
  8. Add @EnableConfigServer annotation in the application file of the config server
  9. Add relevant dependencies to all the microservices

<dependencyManagement>
     <dependencies>
         <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>Greenwich.RELEASE</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
     </dependencies>
</dependencyManagement>
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

  1. Create a bootstrap.properties file in each microservice with a property for the config server and the database credentials                                                                            
    • spring.cloud.config.uri=http://localhost:1111
    • spring.datasource.username=root
    • spring.datasource.password=root
  2. Remove database connection details from the application.properties of individual services.
  3. Run the application


Configuring properties of Spring Cloud Config Server

When Cloud-Config is used, each microservice gets two properties files with the name 'application.properties'. One in GIT and the other one present locally. Which one will take precedence?

To ensure that the properties file from GIT takes higher priority, it needs to be accessed first before the local properties file for which the bootstrap context is used.

Spring Cloud creates a parent context to the spring application context called the ‘bootstrap’ context. This context takes precedence over the application context. This context is responsible for loading configuration details from an external source. Both these contexts share the Spring Environment, thus making configuration usage seamless.

Since the bootstrap context takes precedence the URI of the config-server must be mentioned in bootstrap.properties/YAML for the clients.

Note: 

In the recent releases of Spring Boot versions >2.4.x, the bootstrap context initialization using property sources like bootstrap.properties/bootstrap.yml is deprecated.  

As the demos are using Spring Boot 2.5.3 version we can add these configuration data to the application.properties file itself. No need for additional bootstrap.properties. 

Also, the property to be added in the microservices is modified in recent releases as spring.config.import=optional:configserver:http://localhost:1111. Refer to the downloaded demos for the complete code.

To connect to the Infygithub/Github instead of the password we can also use the Personal Access Token. The access token can be generated from -> Settings -> Developer Settings -> Personal Access Tokens

Spring uses Environment to get the configuration details from various sources such as the environment variables, properties files, YAML files, etc. These are built in property sources. When we use cloud config, it adds an additional property source to the Environment such that it takes the properties from the cloud config server.

When cloud config is used, the additional property source takes a higher priority. It means that, any duplicate properties in other property sources are ignored.

We can access the configuration files by using endpoint on the config server in any one of the below patterns:

http://<config_server_host>:<port>:/<application>-<profile>.yml

http://<config_server_host>:<port>/<application>-<profile>.properties

The properties file used in the GIT must have the same name as that of the client's spring.application.name

spring.application.name = CallDetailsMS



We can have multiple profiles as well and if a profile is not mentioned it will load the default profile, which is the same name as that of the spring.application.name.

If we try to access a microservice property for a given profile, the order of files used will be:

  • Yaml file for that profile
  • Properties file for that profile
  • application.yml file
  • application.properties file

For example, if we have a property called x=10 in application.yml and x=20 in the application.properties, the final value used will be 10

The config-server is contacted by the clients only once, during the start of the project. Therefore any changes made to the configuration after the application starts will not be reflected in the application.

We can also configure the clients retry attempts to contact the config server using properties like

If a port is not specified for the config server, it runs in its default port 8888. Also, if the Cloud-Config server is down, then the client will throw an error not during startup, but while trying to access the property at runtime. To avoid this we can have the failFast property set to true. By this, the client will fail at startup time rather than at the run time.
                                            spring.cloud.config.failFast=true
Also, in order to avoid Config-server to be a single point of failure, we usually deploy multiple instances of it to ensure high availability. If the cloud config server is unavailable, it will use the properties files in the individual applications as a fallback

Dynamic Configuration Changes

When we make any changes to the properties file in GIT, the config-clients automatically do not update themselves with the modified values. This is because the configurations are taken only once at the time of startup. For example, if we modify the property of CustomerMS, we have to restart CustomerMS so that it can again fetch the properties from the config server. However, this is not a practical approach.
To overcome this we need to :

  • Add @RefreshScope annotation on the bean which is using the property
  • Add spring-boot-actuator endpoint dependency
            <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
  • In order to access the actuator endpoints using HTTP, we need to both enable and expose them by adding the below property in the relevant microservices:
            management.endpoints.web.exposure.include=*
  • Send a POST request to the /refresh endpoint of the service. This refreshes the microservice without restarting/redeploying it.
In this case, we would add @RefreshScope on the CustomerController, add actuator dependency on the CustomerMS and send a POST request to http://localhost:8001/actuator/refresh which is where the CustomerMS is running

RefreshScope
The @RefreshScope annotation is needed only if we are using @Value. If we are getting the values from the spring environment variable directly, we don’t need this annotation. Every time we use getProperty() on the spring environment variable, it fetches the latest value. However, we would still need to have the /refresh actuator endpoint and send a POST request to it.

Spring Cloud Bus
The problem with using the /refresh endpoint is that we have to manually fire a POST request to it. It is not automatically done when the configuration changes. Also, we need to fire a request to /refresh on all the services which might get affected by the change in the property. That means we have to keep track of which property is used in which application. If we have 100 microservices using the property, we need to fire /refresh on all those microservices.

The solution is to use Spring-Cloud-Bus. This, along with a Queuing service like RabbitMQ, will trigger refresh events on all dependent microservices. However, Spring-Cloud-Bus is beyond the scope of the curriculum.

Summary

  • Spring Cloud project allows us to write cloud compatible code
  • One of its sub-project is Spring Cloud Config
  • Cloud-Config allows keeping all configurations in a central place
  • Since this uses the Bootstrap context, we need to use bootstrap.properties file
  • A config server contacts the GIT repo.
  • The config clients contact the config server at startup to gather the configurations
  • Changes made to configurations don’t automatically reflect in the clients
  • The configuration files use a specific order of priority.

Quiz : 


1 . What is the use of spring.cloud.config.fail-fast=true property for the microservices?
Microservices should not start running if the config server has not yet started
exp : If the cloud-config server is down, then the client will throw an error at runtime not during startup so the config server has to start first then Microservices are allowed to start.

2. Without failfast property, what happens if the config server has not started, but the microservices have started?
Microservices will get run time error when trying to access config details
exp : Microservices will throw an error as configuration from config server un-accessible

3. A microservice has both local as well cloud config. Which of the below is true?
The local will override the cloud

4. Which of the below will take priority in cloud config?
application.yml
yml config has high priority over properties file
5. Below are some of the config files in the cloud. What will be the final value of the property hello in a microservice with spring.application.name “CustMS”?

application.yml:
hello: world
application.properties:
hello=Infy
name=test
CustMS.yml:
hello: Spring

answer : Spring
exp : value from default profile(CustMS) will be used

6. If the config server shuts down in between, all the microservices which are already up and running will start failing. False
Below are some of the config files in the cloud. What will be the final value of the property hello in a microservice with spring.application.name "CustMS" with profile "dev"?

application.yml:
hello: world
application.properties
hello=Infy
name=test
CustMS-dev.yml:
hello: Spring
CustMS.yml:
hello: Cloud

answer : Spring
CustMS- dev.yml profile will have highest priority so configurations from this file will be used

7 . If the config server fails, the local configuration will be used - True

8. If we change the values of properties in cloud config, all microservices will immediately reflect that change.
False
exp : Configurations are taken only once at the time of startup. Need to add actuator dependency with @RefreshScope annotation on the bean which is using the property also POST request to the /refresh endpoint

9. Which of the following needs to performed to use @RefreshScope?
    add actuator endpoint
    send post request to actuator endpoint

10. A config server is running on port 8888, consider the below configuration
CustMS.properties:
hello=world  --- JSON
exp :If we are accessing default profile for CustMS from config server it will be served by default in JSON format

11. A config server is running on localhost at port 8888 with below configuration:

CustMS-dev.properties:
hello=world
What will be the output when we access the URL: http://localhost:8888/CustMS-dev.properties

Display properties file content in JSON format

exp : Config server properties files can be accessed using REST endpoints and if we are accessing profile for CustMS from config server it will be served by default in JSON format

Introduction to Load Balancing

Suppose Infytel has announced an offer that customers with 5 friends will get a 5% discount. Since this is a limited time offer, there is a surge in people adding their friend details. To manage the load we are scaling by increasing the instances of infytel-friend-family from one to two. Now, we have to find a way to balance the load of requests between these two instances, else only one instance will get more or all the load and the other instance will become redundant.
Client Side vs Server Side Load Balancing
Since the number of instances has increased, the infytel-customer must send requests to both these instances so that the load is properly balanced.

One way is to put a load balancer in front of the infytel-friend-family instances. This is usually a hardware load balancer.

The infytel-customer would simply send the request to the load balancer and it is the responsibility of the load balancer to decide to whom it should forward the request. This concept is also known as Server-Side load balancing.


But, Server-side load balancing has several problems:

  • If the load balancer fails, then we don’t have access to any of the instances of the microservice
  • Since each microservice would have a dedicated load balancer, we have to manage, track, and maintain hundreds of such load balancers.
  • It increases network latency. Now, it would take two hops to reach the service. One to the load balancer and another from the load balancer
Server-side load balancers can either be hardware or software load balancers. They are usually hardware load balancers. Some examples of Hardware load balancers are:

  • F5 BIG-IP load balancer
  • CISCO system catalyst
  • Barracuda load balancer
  • Coytepoint load balancer

Client-side load balancing is a natural solution to this. The client is responsible for deciding to whom it will send the request. The client-side load balancers are thus software load balancers and not traditional hardware load balancers. Of course, the downside is we are mixing our application code with load balancing code.

The various load balancers provided by Spring Cloud to perform client-side load balancing are Ribbon, Spring Cloud Load Balancer, etc.


Some examples of software load balancers are:
  • HAProxy
  • NGINX
  • mod_athena
  • Varnish

Ribbon :

Steps to use Ribbon:
  1.  Add the dependency in the infytel-customer
  2. <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
  3. Create a Configuration class with the below bean
  4. @Bean @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
  5. Autowire the RestTemplate as @Autowired RestTemplate template; in the CustomerController
  6. Add @RibbonClient(name="custribbon") annotation on the CustomerController class
  7. Add the below properties in the properties file:
  8. custribbon.ribbon.eureka.enabled=false
    custribbon.ribbon.listOfServers=http://localhost:8001,http://localhost:8002

  9. Autowire the rest template and update the infytel-friend-family invocation in CustomerController as
  10. List<Long> friends = template.getForObject("http://custribbon/customers/" + phoneNo+"/friends", List.class);
  11. Run the application, with the two instances of FriendFamilyMS running in two different ports

Notes:

 If you want to start an instance of Friend FamilyMS on a different port use the following command after the maven build of your project is done.

    java -jar -Dserver.port=9797 target/FriendFamilyMS-0.0.1-SNAPSHOT-exec.jar // java -jar -Dserver.port=<<port no>> target/<<jar name>>-exec.jar

Featured Post

HTML cheetsheet

List: Link tgs Dropdown

Popular Post

(C) Copyright 2018, All rights resrved InShortView. Template by colorlib