Cloud native microservices Chapter 5 Spring Cloud Netflix Eureka integrated load balancing component Ribbon

Table of Contents of Series Articles

Chapter 1 Application of Java Thread Pool Technology
Chapter 2 Application of CountDownLatch and Semaphone
Chapter 3 Introduction to Spring Cloud
Chapter 4 Eureka of Spring Cloud Netflix
Chapter 4 Ribbon of Spring Cloud Netflix

Insert image description here


Preface

Spring Cloud Ribbon is a set of client-side load balancing and service calling tools implemented based on Netflix Ribbon. Its main function is to provide client-side load balancing algorithms and service calling.

Today we take e-commerce microservices as an example to explain the practical application of Eureka and Ribbon in microservice governance.
Insert image description here
Insert image description here

1. Load balancing

Load Balance (Load Balance), simply put, is to distribute user requests equally to multiple servers to achieve the purpose of expanding server bandwidth, enhancing data processing capabilities, increasing throughput, and improving network availability and flexibility.
There are two common load balancing methods: server load balancing and client load balancing.

1.1. Server-side load balancing

Insert image description here

1.2. Client load balancing

Insert image description here

2. Ribbon implements inter-service calls

Ribbon can be used in conjunction with RestTemplate (Rest template) to implement calls between microservices.
Example:
Establishing a C-side API project customer-api

2.1. pom.xml configuration

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.hqyj</groupId>
        <artifactId>SpringCloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>customer-api</artifactId>
    <name>customer-api</name>
    <description>customer-api</description>

    <properties>
        <java.version>1.8</java.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--devtools 开发工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!--Spring Boot 测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--junit 测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- 修改后立即生效,热部署 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.hqyj</groupId>
            <artifactId>common-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

2.2. application.yml configuration

server:
  port: 80

eureka:
  client:
    register-with-eureka: false #本微服务为服务消费者,不需要将自己注册到服务注册中心
    fetch-registry: true  #本微服务为服务消费者,需要到服务注册中心搜索服务
    service-url:
      defaultZone: http://localhost:7001/eureka
      

2.3. Bean configuration class

Configure RestTemplate and enable load balancing

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/***
 * @title bean配置类
 * @desctption 配置RestTemplate、开启负载均衡
 * @author kelvin
 * @create 2023/5/11 14:33
 **/
@Configuration
public class ConfigBean {
    
    
    @Bean //将 RestTemplate 注入到容器中
    @LoadBalanced //在客户端使用 RestTemplate 请求服务端时,开启负载均衡(Ribbon)
    public RestTemplate getRestTemplate() {
    
    
        return new RestTemplate();
    }
}

2.4. Write code to call Eureka

2.4.1. Define user service interface

import com.hqyj.common.model.UserInfo;
import java.util.List;

/***
 * @title 用户服务 接口
 * @desctption 用户服务
 * @author kelvin
 * @create 2023/5/11 14:22
 **/
public interface UserConsumerService {
    
    

    /**
     * 获取用户信息列表
     * @return
     */
    public List<UserInfo> userInfoList();

}

2.4.2. Write user service implementation class

import com.hqyj.common.model.UserInfo;
import com.hqyj.customerapi.service.UserConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/***
 * @title 用户服务 实现类
 * @desctption 用户服务
 * @author kelvin
 * @create 2023/5/11 14:22
 **/
@Service
public class UserConsumerServiceImpl implements UserConsumerService {
    
    

    private String REST_URL_PROVIDER_PREFIX = "http://USER-SERVICE";
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 获取用户信息列表
     * @return
     */
    @Override
    public List<UserInfo> userInfoList() {
    
    
        return this.restTemplate.getForObject(this.REST_URL_PROVIDER_PREFIX + "/user/userInfoList",List.class);
    }
}

2.4.3. Write user service control layer code

import com.hqyj.common.model.UserInfo;
import com.hqyj.customerapi.service.UserConsumerService;
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 java.util.List;

/***
 * @title UserConsumerController
 * @desctption 用户控制层
 * @author kelvin
 * @create 2023/5/11 14:22
 **/
@RestController
@RequestMapping("/user")
public class UserConsumerController {
    
    

    @Autowired
    private UserConsumerService userConsumerService;

    @GetMapping("/userInfoList")
    public List<UserInfo> userInfoList(){
    
    
        return userConsumerService.userInfoList();
    }
}

2.4.4. Return results uniformly

Add DTO in the public module common-api

import lombok.Data;

/***
 * @title 统一返回格式类
 * @param <T>
 * @desctption 统一返回格式
 * @author kelvin
 * @create 2023/5/11 14:28
 **/
@Data
public class ResponseDTO<T> {
    
    

    /**
     * 返回编码
     */
    private Integer code;
    /**
     * 统一返回消息
     */
    private String message;
    /**
     * 统一返回数据体
     */
    private T data;

}

2.4.5. Unified exception handling

Implement the ResponseBodyAdvice interface

import com.hqyj.common.dto.ResponseDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/***
 * @title 统一异常处理类
 * @desctption 统一异常处理
 * @author kelvin
 * @create 2023/5/11 14:33
 **/
@RestControllerAdvice(basePackages = "com.hqyj.customerapi.controller")
@Slf4j
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {
    
    
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    
    
        //true为织入通知
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    
    
        ResponseDTO<Object> objectResponseDTO = new ResponseDTO<>();
        objectResponseDTO.setCode(200);
        objectResponseDTO.setData(body);
        return objectResponseDTO;
    }

    /**
     * 统一异常处理
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public Object exception(Exception e){
    
    
        log.error("系统异常",e);
        ResponseDTO<Object> objectResponseDTO = new ResponseDTO<>();
        objectResponseDTO.setCode(500);
        objectResponseDTO.setMessage("系统异常");
        return objectResponseDTO;
    }
}

2.5. Start the project and access the interface

2.5.1. Start the project

The two projects in the previous chapter need to be run first.
Insert image description here

2.5.2. Access interface

Access address: http://localhost/user/userInfoList
Insert image description here


Summarize

In previous distributed projects, we used zookeeper, redis, etc. to store service registration information. When the client calls the service, it needs to manually obtain the list of available services. It is very troublesome to use and is particularly unfriendly to junior developers. Be careful and you will make mistakes, such as zookeeper dependency version conflicts, zookeeper\redis cluster address filling errors, zookeeper\redis configuration items missing, etc.
The emergence of Ribbon solves some of the above problems, and Ribbon is a component in the Netflix ecosystem. It can be well integrated with Eureka and used in combination, which is very convenient.

Guess you like

Origin blog.csdn.net/s445320/article/details/133156575