Ribbon实现客户端负载均衡

转载:https://blog.csdn.net/lzxlfly/article/details/87895630

一、Ribbon简介

Ribbon是Netflix发布的负载均衡器,提供了对来自HTTP和TCP客户端行为的控制。为Ribbon配置提供者服务地址列表后,Ribbon可以根据我们指定的负载均衡算法,自动帮助消费者去请求提供者。Ribbon提供了许多负载均衡算法,如常见的轮询、随机等。我们也可以为Ribbin实现自定义负载算法。 

二、通过配置自定义Ribbon

 负载均衡策略

Spring Cloud Netflix默认为Ribbon提供了以下bean:

Bean TypeBean NameClass Name

IClientConfig

ribbonClientConfig

DefaultClientConfigImpl

IRule

ribbonRule

ZoneAvoidanceRule

IPing

ribbonPing

DummyPing

ServerList<Server>

ribbonServerList

ConfigurationBasedServerList

ServerListFilter<Server>

ribbonServerListFilter

ZonePreferenceServerListFilter

ILoadBalancer

ribbonLoadBalancer

ZoneAwareLoadBalancer

ServerListUpdater

ribbonServerListUpdater

PollingServerListUpdater

自定义Ribbon客户端

可以通过注解@RibbonClient声明附加配置,此处声明的配置会覆盖配置文件中的配置。

@Configuration
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class TestConfiguration {
}

需要说明的是自定义的类必须加上@Configuration注解且不能包含在@componentscan注解扫描的包中,否则自定义的类将由所有加@ribbonclient注解的地方共享,若用@ComponentScan(或@SpringBootApplication),应该采取措施来避免它被包含到扫描的范围中。

如下,建立FooConfiguration,自定义serverlistfilter和ribbonPing类型bean,放在在@ribbonclient配置中

@Configuration
protected static class FooConfiguration {
	@Bean
	public ZonePreferenceServerListFilter serverListFilter() {
		ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
		filter.setZone("myTestZone");
		return filter;
	}
 
	@Bean
	public IPing ribbonPing() {
		return new PingUrl();
	}
}

自定义所有默认Ribbon

@RibbonClients不同于@RibbonClient,它 可以为所有的Ribbon客户端提供默认配置

@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)
public class RibbonClientDefaultConfigurationTestsConfig {
 
	public static class BazServiceList extends ConfigurationBasedServerList {
		public BazServiceList(IClientConfig config) {
			super.initWithNiwsConfig(config);
		}
	}
}
 
@Configuration
class DefaultRibbonConfig {
 
	@Bean
	public IRule ribbonRule() {
		return new BestAvailableRule();
	}
 
	@Bean
	public IPing ribbonPing() {
		return new PingUrl();
	}
 
	@Bean
	public ServerList<Server> ribbonServerList(IClientConfig config) {
		return new RibbonClientDefaultConfigurationTestsConfig.BazServiceList(config);
	}
 
	@Bean
	public ServerListSubsetFilter serverListFilter() {
		ServerListSubsetFilter filter = new ServerListSubsetFilter();
		return filter;
	}
 
}

通过配置自定义Ribbon

从1.2.0版本开始,Spring Cloud Netflix支持自定义Ribbon客户端配置

支持配置的属性如下:

  • <clientName>.ribbon.NFLoadBalancerClassName: 配置ILoadBalancer的实现类
  • <clientName>.ribbon.NFLoadBalancerRuleClassName:配置IRule的实现类
  • <clientName>.ribbon.NFLoadBalancerPingClassName: 配置IPing的实现类
  • <clientName>.ribbon.NIWSServerListClassName: 配置ServerList的实现类
  • <clientName>.ribbon.NIWSServerListFilterClassName:配置ServerListFilter的实现类

如application.yml配置

microservice-provider-order: 
  ribbon:
    NIWSServerListClassName: com.ultradata.task.ConfigurationBasedServerList
    NFLoadBalancerRuleClassName: com.ultradata.task.RandomeRule

com.ultradata.task.ConfigurationBasedServerList、com.ultradata.task.RandomeRule类自己实现即可,也可以是默认的类

如com.netflix.loadbalancer.ConfigurationBasedServerList,com.netflix.loadbalancer.WeightedResponseTimeRule

三、与Eureka配合使用

  • 当Ribbin与Eureka结合使用时候,ribbonServerList将被com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList的实现覆盖,该实现会将服务列表交给Eureka的服务治理机制来进行维护。
  • IPing接口被com.netflix.niws.loadbalancer.NIWSDiscoveryPing覆盖,NIWSDiscoveryPing也委托给了Eureka来维护。
  • 默认情况下,用于获取实例请求的ServerList接口实现将采用Spring Cloud Eureka中封装的org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList,其目的是为了让实例维护策略更加通用,所以将使用物理元数据来进行负载均衡,而不是使用原生的AWS AMI元数据。
  • Spring Cloud Ribbon默认使用eureka实例元数据中提供的“zone”信息构建服务器列表,通过设置eureka.instance.metadatamap.zone的值,可以实现跨区域的实例配置,如将不同机房配置不同的区域值即可eureka.instance.metadatamap.zone=beijing。

但也可以通过设置ribbon.eureka.enabled=false来禁用Eureka维护。

1、由于eureka中整合了Ribbin,pom.xml引入eureka-client依赖即可

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>

2、Rinbbon负载均衡操作,有两种方法

(1)为RestTemplate添加@LoadBalanced注解,启动RestTemplate客户端负载均衡

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;
 
@EnableDiscoveryClient
@SpringBootApplication
@ComponentScan("com.ultradata.task")
public class ConsumerApplication {
	public static void main(String[] args) throws Exception {
		SpringApplication.run(ConsumerApplication.class, args);
	}
	
	@LoadBalanced
	@Bean
	public RestTemplate restTemplate(){
		return new RestTemplate();
	}
}

消费者controller如下

import java.net.URI;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
 
@RestController
public class ConsumerOrderController {
	private static final Logger LOGGER = LoggerFactory.getLogger(ProviderOrderController.class);
	
	@Autowired
	private RestTemplate restTemplate;
	
	@GetMapping("/order/${orderId}")
	public String order(@PathVariable String orderId) {
		return restTemplate.getForObject("http://microservice-provider-order"+orderId, String.class);
	}
}
(2) 启动类不必为RestTemplate添加@LoadBalanced注解,直接用Ribbon提供的LoadBalancerClient实现
import java.net.URI;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
 
@RestController
public class ConsumerOrderController {
	private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerOrderController .class);
	
	@Autowired
	private RestTemplate restTemplate;
	@Autowired
	private LoadBalancerClient loadBalancerClient;
	
	@GetMapping("/order/${orderId}")
	public String order(@PathVariable String orderId) {
		ServiceInstance serviceInstance = loadBalancerClient.choose("microservice-provider-order");
		LOGGER.info("ServiceId:{},Host:{}:Port:{}",serviceInstance.getServiceId(),serviceInstance.getHost(),serviceInstance.getPort());
		URI url = URI.create(String.format("http://%s:%s/pay"+, serviceInstance.getHost(), serviceInstance.getPort()));
		return restTemplate.getForObject(url+orderId, String.class);
	}
}

四、脱离Eureka使用

去掉启动类上的@EnableDiscorveryClient注解

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
 
@SpringBootApplication
public class ProviderApplication {
	public static void main(String[] args) throws Exception {
		SpringApplication.run(ProviderApplication.class, args);
	}
}

application.yml配置如下

server:
  port: 8081
spring:
  application:
    name: microservice-consumer-pay
microservice-provider-order:
  ribbon:
    listOfServers: node01:8080,node02:8080,node03:8080
ribbon:
  eureka:
   enabled: false
#false不使用Eureka

listOfServers的地址列表是microservice-provider-order提供者的Ribbin的客户端地址列表,供microservice-consumer-pay调用

 控制层实现和之前整合Eureka一样,不再展示。

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值