Continue learning about SpringCloud today.

Last time we talked about Eureka and service providers and consumers

This article is about service gateways and load balancing in detail

The following code uses the simplest code examples, not real business code

The learning materials used in the study are as follows:

Article: SpringCloud minimalism Primer

Video: Spring Cloud from the beginning to the real world


Service gateway concept

In a distributed project architecture, services are split and different microservices are responsible for their own business functions, thus achieving decoupling at the software architecture level. However, if the number of microservices after splitting is too large, it is not conducive to system development, because each service has a different network address, the client repeatedly requests different microservices need to call different urls, if the maintenance of multiple different urls will undoubtedly increase the cost of development.

As shown in the figure below, a meal ordering system needs to call multiple microservice interfaces to complete a meal ordering business process. If there is a solution that can uniformly manage different microservice urls, it will certainly enhance the maintenance of the system and improve the development efficiency.

This solution is THE API gateway, which can manage and maintain all API requests, equivalent to opening a unified interface for the system. All external requests only need to access this unified entrance, and then the system can map different micro services through the API gateway. For developers, there is no need to pay attention to the specific micro service URL, and they can directly access the API gateway interface. The structure of the API gateway is shown in the figure below.

This solved the problem and made development much easier.

Zuul

What is Zuul?

Zuul is an open source API gateway server provided by Netflix. It is the middle layer of all requests from the client end and the back end of the website. It opens an API to the outside world and imports all requests into a unified entrance, shielding the specific implementation logic of the server end. Dynamic routing, identity authentication, IP filtering and data monitoring are implemented inside the gateway. We can implement the microservices gateway using Zuul, which is integrated with Spring Cloud.

Code implementation

  • Create the Maven project, POM.xml
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.0.2. RELEASE</version>
    </dependency>
 
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        <version>2.0.2. RELEASE</version>
    </dependency>
</dependencies>
Copy the code
  • Create the configuration file application.yml
server:
  port: 8030
spring:
  application:
    name: gateway
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
zuul:
  routes:
    provider: /p/**
Copy the code

Attribute Description:

Zuul.routes. provider: sets the mapping for the service provider provider

  • Creating a startup class
package com.janeroad;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy
@EnableAutoConfiguration
public class ZuulApplication {
    public static void main(String[] args) { SpringApplication.run(ZuulApplication.class,args); }}Copy the code

Notes:

@enableZuulProxy: contains @enableZuulServer. Set this class to be the gateway startup class.

@enableAutoConfiguration: helps Spring Boot applications load all qualified @Configuration configurations into the IoC container that Spring Boot is currently creating and using.

  • Zuul provides load balancing functions. Modify the provider code.
package com.janeroad.controller;

import com.janeroad.entity.Student;
import com.janeroad.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;

@RestController
@RequestMapping("/student")
public class StudentHandler {
    @Autowired
    private StudentRepository studentRepository;

    @Value("${server.port}")
    private String port;

    @GetMapping("/findAll")
    public Collection findAll(a){
        return studentRepository.findAll();
    }

    @GetMapping("/findById/{id}")
    public Student findById(@PathVariable("id") long id){
        return studentRepository.findById(id);
    }

    @PostMapping("/save")
    public void save(@RequestBody Student student){
        studentRepository.saveOrUpdate(student);
    }

    @PutMapping("/update")
    public void update(@RequestBody Student student){
        studentRepository.saveOrUpdate(student);
    }

    @DeleteMapping("/deleteById/{id}")
    public void deleteById(@PathVariable("id") long id){
        studentRepository.deleteById(id);
    }

    @GetMapping("/index")
    public String index(a){
        return "Current port:"+this.port; }}Copy the code

Service gateway Zuul startup effect

You can see that there are more gateways in the registry

Accessing 8030/p/student/findAll is equivalent to accessing the service provider 8010/student/findAll because the configuration file is mapped

At the same time, Zuul has its own load balancing function. Add a method to return the current service port in the Handler of EurekaClient, restart EurekaServer and EurekaClient and change the port of the provider to 8011. Create a new Provider startup class and start it, and finally restart gateway. Visit http://localhost:8761 and you can see that there are two providers

Visit http://localhost:8030/p/student/index twice, request the port 8010 and 8011 respectively the provider of the service, realize the load balance.

Ribbon Load Balancing

The invocation of RestTemplate only meets the most basic requirements. If the invocation demand for a service surges in a specific service scenario, Load Balancing is essential in a large distributed application system.

What is Ribbon?

Spring Cloud provides a solution for load balancing: Spring Cloud Ribbon is a load balancer released by Netflix and implemented based on Netflix Ribbon. It is a load balancer client used to control HTTP requests.

Spring Cloud Ribbon

Cloud. Spring. IO/spring – clou…

The Ribbon can also be used with the Eureka Server. That is, the Ribbon needs to be registered with the Eureka Server. After the registration is complete, the Ribbon can be combined with a load balancing algorithm. Examples such as polling, randomization, weighted polling, and weighted randomization help service consumers invoke interfaces. In addition to the default Ribbon load balancing algorithms, developers can customize Ribbon load balancing algorithms based on their own requirements. In actual development, Spring Cloud Ribbon needs to be used in conjunction with Spring Cloud Eureka. Eureka Server provides a list of all callable service providers. The Ribbon selects instances to invoke from these service providers based on specific load-balancing algorithms, as shown in the figure below.

The Ribbon uses the following load balancing policies:

  • Random: When accessing a service, randomly select one from the registry’s list of services.
  • Polling: When two service providers are started at the same time, client requests are processed alternately by them.
  • Weighted polling: The response time of all microservices in the list of services is weighted and polled to access these services.
  • Maximum availability: Select the microservice with the least concurrent traffic from the list of services.

Code implementation

  • Create Module, pom.xml
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.0.2. RELEASE</version>
    </dependency>
</dependencies>
Copy the code
  • Create the configuration file application.yml
server:
  port: 8040
spring:
  application:
    name: ribbon
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
Copy the code
  • Creating a startup class
package com.janeroad;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class RibbonApplication {
    public static void main(String[] args) {
        SpringApplication.run(RibbonApplication.class,args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(a){
        return newRestTemplate(); }}Copy the code

LoadBalanced: Declares a load balancing based on the Ribbon.

  • Handler
package com.janeroad.controller;

import com.janeroad.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Collection;

@RestController
@RequestMapping("/ribbon")
public class RibbonHandler {
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/findAll")
    public Collection findAll(a){
        return restTemplate.getForObject("http://provider/student/findAll",Collection.class);
    }

    @GetMapping("/index")
    public String index(a){
        return restTemplate.getForObject("http://provider/student/index",String.class); }}Copy the code

Open the browser and visit http://localhost:8761. The following page is displayed

Now that the Provider and Ribbon are registered in the registry, use the Postman tool to test the Ribbon interface, as shown in the figure below.

  • The.findall interface

  • FindById interface

  • Save the interface

When the query is complete, call the findAll interface and you can see that the new data has been added successfully.

  • The update interface

After the change is complete, query the findAll interface and you can see the changed data.

  • DeleteById interface

When the query is done, call the findAll interface and you can see that the data has been deleted.

Next, test the Ribbon load balancing by adding the following code to the RibbonHandler

@RequestMapping("/ribbon")
@RestController
public class RibbonHandler {

    @GetMapping("/index")
    public String index(a){
        return restTemplate.getForObject("http://provider/student/index",String.class); }}Copy the code

Start the registry, Provider with port 8010, Provider with port 8011, and Ribbon respectively.

Open your browser and visit http://localhost:8761

Can see both the Provider and the Ribbon has been registered in the registry, visit http://localhost:8040/ribbon/index, appear alternately shown below, to realize the load balance.