Spring Cloud Ribbon

微服务框架 Spring Cloud 核心组件 Ribbon

Posted by leone on 2019-02-21

Spring Cloud Ribbon

开发环境

开发工具:Intellij IDEA 2018.2.6

springboot: 2.0.6.RELEASE

jdk:1.8.0_192

maven: 3.6.0

Ribbon 简介

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用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
77
78
79
80
81
82
83
84
85
86
<?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">
<modelVersion>4.0.0</modelVersion>

<packaging>jar</packaging>

<artifactId>spring-cloud-ribbon</artifactId>
<groupId>com.andy</groupId>
<version>1.0.6.RELEASE</version>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.spring.platform</groupId>
<artifactId>platform-bom</artifactId>
<version>Cairo-SR7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<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>com.andy</groupId>
<artifactId>spring-cloud-common</artifactId>
<version>1.0.6.RELEASE</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.3.RELEASE</version>
<configuration>
<!--<mainClass>${start-class}</mainClass>-->
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
  • 启动类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;

/**
* @author Leone
* @since 2018-12-21
**/
@SpringBootApplication
@EnableDiscoveryClient
@RibbonClients({@RibbonClient(name = "mc-user")})
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class, args);
}
}
  • application.yml
1
2


  • RibbonController.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
36
37
38
39
40
41
import com.andy.common.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

/**
* @author Leone
* @since 2018-12-21
**/
@Slf4j
@RestController
@RequestMapping("/api/ribbon")
public class RibbonController {

@Autowired
private RestTemplate restTemplate;

@Autowired
private LoadBalancerClient loadBalancerClient;

@GetMapping("/{userId}")
public User order(@PathVariable("userId") int userId) {
return restTemplate.getForObject("http://mc-user/user/" + userId, User.class);
}

@GetMapping("/choose")
public String choose() {
ServiceInstance choose = loadBalancerClient.choose("mc-user");
return "host: " + choose.getHost() + " port: " + choose.getPort() + " serviceId: " + choose.getServiceId();
}

@GetMapping("/user")
public User withOutEureka(@RequestParam Long userId) {
ServiceInstance choose = loadBalancerClient.choose("mc-user");
return restTemplate.getForObject(String.format("http://%s:%s/user/%d", choose.getHost(), choose.getPort(), userId), User.class);
}

}
  • RibbonConfig.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import com.netflix.loadbalancer.*;
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;

/**
* <p>
*
* @author leone
* @since 2019-04-04
**/
@Configuration
public class RibbonConfig {

/**
* 实例化ribbon使用的RestTemplate
*
* @return
*/
@Bean
// @LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}

/**
* 配置随机负载策略,需要配置属性mc-user.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
*/
//@Bean
public IRule ribbonRule() {
// 轮询
// return new RoundRobinRule();

// 权重 根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。
// return new WeightedResponseTimeRule();

// 重试 先按照轮询策略获取服务,如果获取失败则在指定时间内重试,获取可用服务
// return new RetryRule();

// 选择一个最小的并发请求的server
// return new BestAvailableRule();

// 符合判断server所在区域的性能和server的可用性选择服务
// return new ZoneAvoidanceRule();

// 随机
// return new RandomRule();

// 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)
return new AvailabilityFilteringRule();
}
}

github