SpringCloud中使用Ribbon的方法详解

springcloud之ribbon介绍

ribbon是负责负载均衡的,属于进程内负载均衡。请求发送到ribbon然后由ribbon发送到各个服务。

服务器端负载均衡:Nginx与F5集中式负载均衡只位于因特网与服务提供者之间,并负责把网络请求转发到各个提供单位。

进程内负载均衡是指从一个实例库选取一个实例进行流量导入,在微服务的范畴内,实例库一般是存储在Eureka、Consul、Zookeeper、etcd这样的注册中心,而此时的负载均衡器就是类似于Ribbon的IPC(Inter-Process Communication,进程间通信)组件,因此,进程内,因此,进程内负载均衡也叫做客户端负载均衡。

 Ribbon负载均衡策略

策略类 命令 描述
RandomRule 随机策略 随机选择server
RoundRobinRule 轮询策略 按照顺序循环选择server
RetryRule 重试策略

在一个配置时间段内当选择server不成功,则一直尝试选择一个可用的server

BestAvailableRule 最低并发策略 逐个考察server,如果server断路器打开,则忽略,再选择其中并发连接最低的server
AvailabilityFilteringRule 可用过滤策略 过滤掉一直连接失败并被标记位circuit tripped的server,过滤掉那些高并发连接的server(active connections超过配置的阈值)
ResponseTimeWeightedRule 响应时间加权策略 根据server的响应时间分配权重。响应时间越长,权重越低,被选择到的概率就越低;响应时间越短,权重越高,被选择到的概率就越高。这个策略很贴切,综合了各种因素,如:网络、磁盘、IO等,这些因素直接影响着响应时间。
ZoneAvoidanceRule 区域权衡策略 综合判断server所在区域的性能和server的可用性轮询选择server,并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server

 

可以在java配置文件中添加自己所需要的负载均衡策略如:

1
2
3
4
5
6
7
8
9
10
11
12
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class TestConfiguration {
    @Bean
    public IRule ribbonRule(){
        return new RandomRule();
    }
}

 也可以在yml文件中配置负载均衡的实现类:(注意:yml的配置高于java配置文件,若同时配置了Java和yml则会选择yml的配置)

1
2
3
client-a:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

 application.yml中配置ribbon的其他配置

1
2
3
4
5
6
7
client-a:
  ribbon:
    ConnectTimeout: 300000
    ReadTimeout: 300000
    MaxAutoRetries: 1 #对第一次请求的服务的重试次数
    MaxAutoRetriesNextServer: 1 #要重试的下一个服务的最大数量(不包括第一个服务)
    OkToRetryOnAllOperations: true

 ribbon默认是懒加载,所以第一次请求会慢很多(他需要从注册中心拿去服务实例列表,在进行自身策略的调整),为了避免这个问题使懒加载变为饿加载让其在项目启动时就加载,我们采用如下配置:

1
2
3
4
ribbon:
  eager-load:
    enable: true
    clients: client-a, client-b, client-c

ribbon1.2.0之后的版本支持了yml配置ribbon的行为,也就是说通过配置文件能决定让ribbon使用哪些实现类来完成负载均衡:

ribbon各个功能的接口:这些接口在用到的时候可查有哪些实现类,若有兴趣也可自己实现具体实现类来配置。

自定义配置实现类的列表:

Ribbon实例

搭建Eureka服务器

pom.xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<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>
    <groupId>eureka-client-ribbon</groupId>
    <artifactId>eureka-client-ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>Provider8003</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8
        </project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
 
</project>

 application.yml

1
2
3
4
5
6
7
8
9
10
11
12
server:
  port: 7001
 
eureka:
  instance:
    hostname: localhost
 
  client:
    register-with-eureka: false
    fetchRegistry: false
    service-url:
      defaultZone: http://localhost:7001/eureka

Application.java 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.zk.ribbon;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
 
@SpringBootApplication
@EnableEurekaServer
public class Application {
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

 搭建服务提供者

pom.xml 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<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>
    <groupId>eureka-client-ribbon</groupId>
    <artifactId>eureka-client-ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>Provider8003</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8
        </project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
 
</project>

 Police.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.zk.springribbon;
 
public class Police {
     
    private String id;// 警察编号,用来保存用户输入的参数
    private String url;// 处理请求的服务器url
    private String message;// 提示信息
     
     
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

 PoliceApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.zk.springribbon;
 
import java.util.Scanner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 
@SpringBootApplication
@EnableEurekaClient
public class PoliceApplication {
 
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String port = scan.nextLine();
        new SpringApplicationBuilder(PoliceApplication.class).properties("server.port=" + port).run(args);
    }
 
}

 PoliceController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.zk.springribbon;
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class PoliceController {
 
    @RequestMapping(value="/getPolice", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
    public Police getPolice(HttpServletRequest request){
        Police p = new Police();
        p.setUrl(request.getRequestURL().toString());
        p.setMessage("警察派出成功");
        return p;
    }
     
    @RequestMapping(value="/getPoliceById/{id}", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
    public Police getPolice(HttpServletRequest request, @PathVariable("id") String id){
        Police p = new Police();
        p.setId(id);
        p.setUrl(request.getRequestURL().toString());
        p.setMessage("指定警察派出成功");
        return p;
    }
}

 application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
server:
  port: 8003
 
spring:
  application:
    name: springCloud-ribbon-police
 
eureka:
  client:
    register-with-eureka: true
    fetchRegistry: false
    service-url:
      defaultZone: http://localhost:7001/eureka

  因为需要测试负载均衡,服务提供者需要开启多个服务实例。我们使用手动读取端口号的方式,启动多个服务实例,下面启动8002、8003端口,输入localhost:7001

服务调用者

配置 pom.xml,加入springCloud核心依赖、配置及eureka客户端依赖、Ribbon依赖

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<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>
    <groupId>eureka-client-ribbon</groupId>
    <artifactId>eureka-client-ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>eureka-client-ribbon</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8
        </project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
    </dependencies>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
 
</project>

 PersonApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.zk.springribbon;
 
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 
@SpringBootApplication
@EnableEurekaClient
public class PersonApplication {
 
    public static void main(String[] args) {
        new SpringApplicationBuilder(PersonApplication.class).web(true).run(args);
    }
 
}

 PersonController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.zk.springribbon;
 
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
 
@RestController
@Configuration
public class PersonController {
 
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
     
    @RequestMapping("/getPolice")
    public String getPolice(){
        RestTemplate rt = getRestTemplate();
        String result = rt.getForObject("http://springCloud-ribbon-police/getPolice", String.class);
        return result;
    }
     
    @RequestMapping("/getPoliceById/{id}")
    public String getPoliceById(@PathVariable("id") String id){
        RestTemplate rt = getRestTemplate();
        String result = rt.getForObject("http://springCloud-ribbon-police/getPoliceById/"+id, String.class);
        return result;
    }
 
}

 Application.yml

1
2
3
4
5
6
7
8
9
server:
  port: 9090
spring:
  application:
    name: springCloud-ribbon-person
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

  启动http://localhost:9090/getPolice,发现负载均衡服务接口已经调通了。

 

参考文档如下:https://www.cnblogs.com/li-yan-long/p/15989103.html

posted @   leagueandlegends  阅读(825)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示