在微服务实现中,比较重要的一个组建就是负载均衡,主要是同一个服务又多实例时,为了能够将请求分发到不同的实例节点上, 负载均衡是一个比不可少的组件。在spring cloud eureka的实现中,默认使用了ribbon作为服务均衡的实现, 本篇文章主要是以demo的方式优先了解ribbon的一个具体的使用,然后才能更好的从源码角度分析ribbon的工作原理。
微服务准备
在该demo种,将会创建两个简单的服务,提供相同的接口,名称为spring-cloud-eureka-client-a 与spring-cloud-eureka-client-b服务,这两个服务配置基本一致,不同的时,同在本地运行时,需要修改一下端口的信息。我们为了简便,会在本地运行一个简易的eureka server, 具体demo可以参考spring cloud服务注册之Eureka Server – DEMO
pom.xml
这两个项目都是maven项目,parent的依赖配置如下:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>spring-cloud</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>spring-cloud-eureka-server</module>
        <module>spring-cloud-eureka-client</module>
        <module>spring-cloud-eureka-client-a</module>
      <module>spring-cloud-autoconfigure</module>
    </modules>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.1.12.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
这两个微服务的pom配置基本一致, 具体pom.xml的配置如下:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>spring-cloud-eureka-client-a</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
        </dependency>
        <dependency>
            <groupId>com.netflix.eureka</groupId>
            <artifactId>eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.netflix.eureka</groupId>
            <artifactId>eureka-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>
    </dependencies>
</project>
spring-cloud-eureka-client-a
application.yaml
yaml文件配置作为spring服务启动的默认配置文件, 具体配置如下:
spring:
  cloud:
    discovery:
      enabled: true
  application:
    name: spring-eureka-client-b
  main:
    allow-bean-definition-overriding: true
server:
  port: 8082
management:
  endpoints:
    web:
      exposure:
        include: prometheus, env,info, health
  health:
    show-details: always
eureka:
  client:
    prefer-ip-address: true
    service-url:
      defaultZone: http://localhost:8761/eureka/
spring-cloud-eureka-client-b
application.yaml
spring:
  cloud:
    discovery:
      enabled: true
  application:
    name: spring-eureka-client-b
  main:
    allow-bean-definition-overriding: true
server:
  port: 8081
management:
  endpoints:
    web:
      exposure:
        include: prometheus, env,info, health
  health:
    show-details: always
eureka:
  client:
    prefer-ip-address: true
    service-url:
      defaultZone: http://localhost:8761/eureka/
Controller
该Controller在两个服务中为相同的代码,具体就是返回当前的实例信息, 具体代码如下:
package org.spring.learn.eureka.client.controller;
import com.netflix.appinfo.ApplicationInfoManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.eureka.EurekaClientConfigBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @author xianglujun
 * @date 2021/9/15 18:26
 * @since
 */
@RestController
public class InfoController {
    @Autowired
    private ApplicationInfoManager applicationInfoManager;
    @GetMapping("/info")
    public String info() {
        return applicationInfoManager.getInfo().getId();
    }
}
Application启动类
启动类则是启动spring cloud的微服务信息, 具体源码如下:
package org.spring.learn.eureka.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class SpringEurekaClientDemoBApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringEurekaClientDemoBApplication.class, args);
    }
}
负载均衡客户端配置
这里我们通过引入ribbon的方式, 在客户端配置ribbon, 并负载均衡的调用以上的两个服务,具体配置如下:
RestTemplate配置
@Service
public class RibbonService {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
调用远程服务
@RestController
public class InfoController {
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("/info")
    public String info() {
        return restTemplate.getForObject("http://SPRING-EUREKA-CLIENT-B/info", String.class);
    }
}
启动服务
@SpringBootApplication
@EnableDiscoveryClient
public class SpringEurekaClientDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringEurekaClientDemoApplication.class, args);
    }
}
当服务启动完成之后,我们通过调用本地http://localhost:8080/info查看调用的实例信息, 有如下日志信息:
通过浏览器上输出信息,可以知道服务均衡起到了作用,至此负载均衡的实现demo实现到此完成。
 
				 
					

