Ribbon简介
Ribbon有助于控制HTTP和tcp客户端的行为,为ribbon配置服务提供者地址列表后,Ribbon就可以基于某种负载均衡算法吗,自动的帮助服务消费者去请求。Ribbon默认为我们提供很多负载均衡算法,例如轮询,随机等,
SpringCloud在,当Ribbon和Eureka配合使用时,Ribbon可以自动 从Eureka Server获取服务提供者地址,并基于负载均衡算法,请求其中一个服务提供者实例。
为服务消费者整合Ribbon
创建一个子模块 在子模块的pom.xml中添加
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
在启动类添加如下代码
@SpringBootApplication
@EnableDiscoveryClient
public class YmkRibbonConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(YmkRibbonConsumerApplication.class, args);
}
// 开启客户端负载均衡
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
在入口类上添加@EnableDiscoveryClient
注解,表示该应用是一个Eureka客户端应用,这样该应用就自动具备了发现服务的能力。
RestTemplate可以帮助我们发起一个GET或者POST请求,这个我们在后文会详细解释,这里我们只需要提供一个RestTemplate Bean就可以了,在提供Bean的同时,添加@LoadBalanced
注解,表示开启客户端负载均衡
添加一个控制器
@RestController
public class HelloController {
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello(@RequestParam String name) {
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://provider/hello?name={1}", String.class,name);
return responseEntity.getBody();
}
}
添加application.yml 配置
server:
port: 8010
spring:
application:
name: ribbon-consumer
eureka:
client:
serviceUrl:
defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
instance:
prefer-ip-address: true
回到服务提供者项目,添加一行打印,用来测试是否有负载均衡的效果
@RestController
public class TestController implements TestService{
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello(String name) {
System.out.println("Hello "+name);
return "Hello "+name;
}
}
现在启动所有的项目,并开始测试。以此启动服务注册中心项目,服务提供者项目,服务消费者项目
可以看到
现在访问 http://localhost:8010/hello?name=ribbon
多次访问地址,然后看下控制台的打印
两个提供者项目都打印了,说明我们这里的负载均衡已经起作用了。
Ribbon配置自定义
很多场景下,可能需要自定义的Ribbon配置,例如修改Ribbon的负载均衡规则等。允许使用java代码或属性自定义Ribbon的配置。两种方式等价的。
使用java代码自定义Ribbon配置
在Springcloud中Ribbon默认的配置类是RibbonClientConfiguration。也可使用一个POJO自定义的Ribbon的配置。(自定义的配置会覆盖掉默认配置)。这种配置是细粒度的,不同名称的Ribbon客户端可以使用不同的配置。
创建一个Ribbon的配置类,新建一个包,然后新建类RibbonConfiguration,该类不应该在主应用程序上下文的@ComponentScan 中。
/**
* 该类为Ribbon的配置类
* 注意:该类不应该在主应用程序上下文的@ComponentScan 中。
*/
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
// 负载均衡规则,改为随机
return new RandomRule();
}
}
创建一个空类,并在其上添加@Configuration注解和@RibbonClient注解。
@Configuration
@RibbonClient(name = "provider", configuration = RibbonConfiguration.class)
public class TestConfiguration {
}
由上代码可知,使用@RibbonClient注解的configuration属性,可以自定义指定名称的Ribbon客户端。
在消费者项目添加如下代码,用来测试
@GetMapping("/log-user-instance")
public void logUserInstance() {
ServiceInstance serviceInstance = this.loadBalancerClient.choose("provider");
// 打印当前选择的是哪个节点
System.out.println("{}:{}:{}," + serviceInstance.getServiceId()+","+ serviceInstance.getHost()+","+ serviceInstance.getPort());
}
多次调用 http://localhost:8010/log-user-instance ,观查控制台打印结果。如下 负载均衡规则,已经由原来的轮询改为随机了。
全部配置
可以使用@RibbonClients 为所有的Ribbon 提供默认配置,如下
@RibbonClients(defaultConfiguration = RibbonConfiguration.class)
public class TestConfiguration {
}
多次调用 http://localhost:8010/log-user-instance ,观查控制台打印结果
效果一样的。
使用属性自定义Ribbon配置
相对于java代码配置,简单不小,只需要在application.yml 中添加如下配置即可
provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
这样就可以将名为 provider 的负载均衡设置为随机。
多次调用 http://localhost:8010/log-user-instance ,观查控制台打印结果
全局配置
由于spring-cloud的Ribbon并没有实现netflix Ribbon的所有配置项。netflix配置全局rule方式为:ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule,但是 spring-cloud并不支持,spring-cloud直接到服务粒度,只支持SERVICE_ID.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
脱离Eureka 使用Ribbon
因为往往Ribbon配合Eureka使用的,往往也有第三方服务没有注册到Eureka Server,甚至不是spring cloud开发的,也需要进行负载均衡,这时可以在服务消费者的配置文件中进行如下方式配置,实现负载均衡
serverId:
ribbon:
listOfServers:localhost:8010,localhost:8011
listOfServers属性用于为名为serverId的ribbon客户端设置的请求的地址列表。
属性配置的方式比java代码配置的方式具有更高的优先级。
更多关于RestTemplate的请求方式,以及参数的传递,参考此链接 : https://blog.csdn.net/keehom/article/details/80721599
源码下载: https://download.csdn.net/download/u013083284/10749566