`
y806839048
  • 浏览: 1121539 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

ribbon自定义负载均衡

阅读更多

 

Ribbon负载均衡器

上一篇文章我们已经实现了一个客户端负载均衡请求web服务的示例。

当时,我们留了一个伏笔,其中的负载均衡的规则策略可以定制,那么本文着重研究策略定制这部分内容,其他的ribbon客户端的构建和请求方法请参见上一篇文章。

ribbon的负载均衡的策略规则是独立的,即这部分功能可以独立于时间的客户端构造和请求发送。我们需要做的是,实现一个IRule接口的对象,对象里面当然会有一些需要你去覆盖实现的方法,这些方法中需要用代码实现你定制的服务器选择策略,但不包括实际的网络请求操作。

除了可以自己定制,Ribbon已经为我们设计了几个现成的规则策略,分别对应于多个不同IRule实现类。我们只需要将这些类对象传给负载均衡器ILoadBalancer的chooseServer()就可以了。其中,默认情况下,BaseLoadBalancer会选择轮询各个server的策略方式,叫做RoundRobinRule。源码如下:

public classBaseLoadBalancerextendsAbstractLoadBalancerimplements
        PrimeConnections.PrimeConnectionListener, IClientConfigAware {

    private static Logger logger = LoggerFactory
            .getLogger(BaseLoadBalancer.class);
    private final static IRule DEFAULT_RULE = new RoundRobinRule();
    private final static SerialPingStrategy DEFAULT_PING_STRATEGY = new SerialPingStrategy();
    private static final String DEFAULT_NAME = "default";
    private static final String PREFIX = "LoadBalancer_";

    protected IRule rule = DEFAULT_RULE;

    protected IPingStrategy pingStrategy = DEFAULT_PING_STRATEGY;

    protected IPing ping = null;

    @Monitor(name = PREFIX + "AllServerList", type = DataSourceType.INFORMATIONAL)
    protected volatile List<Server> allServerList = Collections
            .synchronizedList(new ArrayList<Server>());
    @Monitor(name = PREFIX + "UpServerList", type = DataSourceType.INFORMATIONAL)
    protected volatile List<Server> upServerList = Collections
            .synchronizedList(new ArrayList<Server>());

好,先说到这里,我们来实验一下默认的规则策略:

第一步,我们先构建一个负载均衡器,类型BaseLoadBalancer,它是ILoadBalancer的实现类。

负载均衡器,需要配置两样东西:

1、服务地址列表——谁来参选?

2、选择策略规则——怎么选?

第二步,按照服务方的地址端口列表,配置一个Server的List。添加给负载均衡器。

第三步,构造或选择一个IRule实现类,通过ConfigurationMannager来配置【客户端名称】.ribbon.NFLoadBalancerRuleClassName属性,将配置键赋予一个规则类。这里我们不操作,使用默认的。

package com.happybks.invokers;

import java.util.ArrayList;
import java.util.List;

import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

public classBalancerApplication{

	publicstaticvoidmain(String[] args){
		ILoadBalancer balancer=new BaseLoadBalancer();
		
		List<Server> servers = new ArrayList<Server>();
		servers.add(new Server("127.0.0.1",8091));
		servers.add(new Server("127.0.0.1",8092));
		balancer.addServers(servers);
		
		for(int i=0;i<10;i++) {
			Server choosedServer = balancer.chooseServer(null);
			System.out.println(choosedServer);
		}

	}

}

默认策略,就用BaseLoadBalancer类默认初始化定义好的,chooseServer方法会为我们选择已有的RoundRobinRule。

(本文出自ochina博主happBKs的博文:https://my.oschina.net/happyBKs/blog/1787825)

源码如下:

private final static IRule DEFAULT_RULE = new RoundRobinRule();
    /*
     * Get the alive server dedicated to key
     * 
     * @return the dedicated server
     */
    public Server chooseServer(Object key) {
        if (counter == null) {
            counter = createCounter();
        }
        counter.increment();
        if (rule == null) {
            return null;
        } else {
            try {
                return rule.choose(key);
            } catch (Exception e) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);
                return null;
            }
        }
    }

我们运行代码:10次选择server的结果打印如下:

16:41:10.754 [main] WARN com.netflix.config.sources.URLConfigurationSource - No URLs will be polled as dynamic configuration sources.
16:41:10.758 [main] INFO com.netflix.config.sources.URLConfigurationSource - To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
16:41:10.766 [main] INFO com.netflix.config.DynamicPropertyFactory - DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@75bd9247
16:41:10.818 [main] DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer [default]: clearing server list (SET op)
16:41:10.819 [main] DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer [default]:  addServer [127.0.0.1:8091]
16:41:10.819 [main] DEBUG com.netflix.loadbalancer.BaseLoadBalancer - LoadBalancer [default]:  addServer [127.0.0.1:8092]
127.0.0.1:8092
127.0.0.1:8091
127.0.0.1:8092
127.0.0.1:8091
127.0.0.1:8092
127.0.0.1:8091
127.0.0.1:8092
127.0.0.1:8091
127.0.0.1:8092
127.0.0.1:8091

 

关于负载均衡相关的四个配置项

这些配置项的前缀是【客户端名称】.ribbon

The supported properties are listed below and should be prefixed by <clientName>.ribbon.:

  • NFLoadBalancerClassName: should implement ILoadBalancer
  • NFLoadBalancerRuleClassName: should implement IRule
  • NFLoadBalancerPingClassName: should implement IPing
  • NIWSServerListClassName: should implement ServerList
  • NIWSServerListFilterClassName should implement ServerListFilter

 

其中比较重要的是NFLoadBalancerRuleClassName,我们可以通过这个配置项定制需要的负载均衡规则,可以是ribbon提供的原生的几种规则类,也可以是自己实现的规则类,这些类都实现了IRule接口。

NFLoadBalancerPingClassName用于配置查看服务器是否存活。

NFLoadBalancerRuleClassName指定负载均衡器的实现类。当然,可以设置自己实现的负载均衡器。

NIWSServerListClassName是服务器列表的处理类,用来维护服务器列表的。Ribbon已经实现了动态服务器列表。

NIWSServerListFilterClassName是服务器的拦截类。

 

负载均衡的两种配置方法:

一种直接调用ConfigurationManager获取配置实例,然后设置配置属性;一种是在application.yml中配置。

 

自定义策略规则:

下面我们以一个示例来构建一个自己的负载均衡规则。

示例:构建一个60%的概率选择8091,40%概率选择8092的规则

我们构建一个实现IRule接口的实现类:

package com.happybks.invokers;

import java.util.List;
import java.util.Random;

import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;

public classMyProbabilityRandomRuleimplementsIRule{

	ILoadBalancer balancer = new BaseLoadBalancer();

	@Override
	public Server choose(Object key){
		List<Server> allServers = balancer.getAllServers();
		Random random = new Random();
		final int number = random.nextInt(10);
		if (number < 7) {
			return findServer(allServers,8091);
		}
		return findServer(allServers,8092);
	}

	private Server findServer(List<Server> allServers, int port){
		for (Server server : allServers) {
			if (server.getPort() == port) {
				return server;
			}
		}
		System.out.println("NULL port="+port);
		return null;
	}

	@Override
	publicvoidsetLoadBalancer(ILoadBalancer lb){
		this.balancer = lb;
	}

	@Override
	public ILoadBalancer getLoadBalancer(){
		return this.balancer;
	}

}

客户端的请求程序这里我们还是直接在一个普通的main方法中实现

我们首先需要配置请求服务器列表,这个上篇文章已经介绍过。

之后我们对对应的客户端配置它的ribbon.NFLoadBalancerRuleClassName配置为我们刚才定义的那个实现了IRule的实现类的类名全名,注意:是IRule实现类的全名,一个字符串,不是class。

package com.happybks.invokers;

import com.netflix.client.ClientException;
import com.netflix.client.ClientFactory;
import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.config.ConfigurationManager;
import com.netflix.niws.client.http.RestClient;

public classMyRuleClientApplication{

	public static void main(String[] args) throws Exception {
		// 1、设置请求的服务器
		ConfigurationManager.getConfigInstance().setProperty("happybks-client.ribbon.listOfServers",
				"localhost:8091,localhost:8092"); // 1
		// 2、 配置规则处理类
		//本示例略,先默认使用其默认负载均衡策略规则
		ConfigurationManager.getConfigInstance().setProperty("happybks-client.ribbon.NFLoadBalancerRuleClassName",MyProbabilityRandomRule.class.getName());

		// 3、获取 REST 请求客户端
		RestClient client = (RestClient) ClientFactory.getNamedClient("happybks-client");

		// 4、创建请求实例
		HttpRequest request = HttpRequest.newBuilder().uri("/carsInfo/onsale").build();

		// 5、发 送 10 次请求到服务器中
		for (int i = 0; i < 10; i++) {
			System.out.println("the "+(i+1)+"th: ");
			HttpResponse response = client.executeWithLoadBalancer(request);
			String result = response.getEntity(String.class);
			System.out.println(result);
		}
	}

}

响应请求的服务方程序请参见之前的文章,我们不再累述。然后我们看看运行结果:

22:52:27.695 [main] WARN com.netflix.config.sources.URLConfigurationSource - No URLs will be polled as dynamic configuration sources.
22:52:27.701 [main] INFO com.netflix.config.sources.URLConfigurationSource - To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
22:52:27.834 [main] INFO com.netflix.config.DynamicPropertyFactory - DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@97e1986
22:52:28.787 [main] INFO com.netflix.http4.ConnectionPoolCleaner - Initializing ConnectionPoolCleaner for NFHttpClient:happybks-client
22:52:28.798 [Connection pool clean up thread] DEBUG com.netflix.http4.ConnectionPoolCleaner - Connection pool clean up started for client happybks-client
22:52:28.799 [Connection pool clean up thread] DEBUG com.netflix.http4.MonitoredConnectionManager - Closing expired connections
22:52:28.799 [Connection pool clean up thread] DEBUG com.netflix.http4.NamedConnectionPool - Closing expired connections
22:52:28.799 [Connection pool clean up thread] DEBUG com.netflix.http4.MonitoredConnectionManager - Closing connections idle longer than 30000 MILLISECONDS
22:52:28.800 [Connection pool clean up thread] DEBUG com.netflix.http4.NamedConnectionPool - Closing connections idle longer than 30000 MILLISECONDS
22:52:29.032 [main] WARN com.netflix.client.ClientFactory - Class com.happybks.invokers.MyProbabilityRandomRule neither implements IClientConfigAware nor provides a constructor with IClientConfig as the parameter. Only default constructor will be used.

22:52:29.035 [main] INFO com.netflix.loadbalancer.BaseLoadBalancer - Client: happybks-client instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=happybks-client,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
22:52:29.111 [main] INFO com.netflix.loadbalancer.DynamicServerListLoadBalancer - Using serverListUpdater PollingServerListUpdater
22:52:29.145 [main] WARN com.netflix.client.ClientFactory - Class com.happybks.invokers.MyProbabilityRandomRule neither implements IClientConfigAware nor provides a constructor with IClientConfig as the parameter. Only default constructor will be used.
22:52:29.165 [main] INFO com.netflix.loadbalancer.DynamicServerListLoadBalancer - DynamicServerListLoadBalancer for client happybks-client initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=happybks-client,current list of Servers=[localhost:8091, localhost:8092],Load balancer stats=Zone stats: {unknown=[Zone:unknown;	Instance count:2;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:localhost:8092;	Zone:UNKNOWN;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 GMT+08:00 1970;	First connection made: Thu Jan 01 08:00:00 GMT+08:00 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
, [Server:localhost:8091;	Zone:UNKNOWN;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 GMT+08:00 1970;	First connection made: Thu Jan 01 08:00:00 GMT+08:00 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
]}ServerList:com.netflix.loadbalancer.ConfigurationBasedServerList@152aa092
22:52:29.165 [main] INFO com.netflix.client.ClientFactory - Client: happybks-client instantiated a LoadBalancer: DynamicServerListLoadBalancer:{NFLoadBalancer:name=happybks-client,current list of Servers=[localhost:8091, localhost:8092],Load balancer stats=Zone stats: {unknown=[Zone:unknown;	Instance count:2;	Active connections count: 0;	Circuit breaker tripped count: 0;	Active connections per server: 0.0;]
},Server stats: [[Server:localhost:8092;	Zone:UNKNOWN;	Total Requests:0;	Successive connection failure:0;	Total blackout seconds:0;	Last connection made:Thu Jan 01 08:00:00 GMT+08:00 1970;	First connection made: Thu Jan 01 08:00:00 GMT+08:00 1970;	Active Connections:0;	total failure count in last (1000) msecs:0;	average resp time:0.0;	90 percentile resp time:0.0;	95 percentile resp time:0.0;	min resp time:0.0;	max resp time:0.0;	stddev resp time:0.0]
, [Server:localhost:8091;	Zone:UNKNOWN;	Total Requests:
分享到:
评论

相关推荐

    SpringCloud 服务负载均衡和调用 Ribbon、OpenFeign的方法

    无论是自定义负载均衡规则还是利用默认策略,都能帮助开发者有效地管理和调度微服务之间的调用,提升系统的可靠性和性能。在SpringCloud生态中,服务调用不再局限于单一的服务实例,而是能够根据负载情况动态地在多...

    SpringCloud自定义负载均衡算法

    然而,这些策略可能无法满足所有业务场景的需求,因此我们有时需要自定义负载均衡算法。 自定义负载均衡算法的步骤大致如下: 1. **创建自定义策略类**:首先,你需要创建一个实现`IRule`接口的类,这个接口是...

    7.Ribbon负载均衡器详细介绍

    4. **自定义负载均衡规则** 如果默认的负载均衡策略无法满足需求,我们可以自定义 `IRule` 实现。首先创建一个新的类继承 `IRule`,然后重写 `choose` 方法,该方法返回要选择的服务器。接着,在服务启动时,通过...

    Eureka,ribbon修改负载均衡策略

    默认情况下,Ribbon 使用轮询策略,但实际应用中,我们可能需要根据业务需求自定义负载均衡策略。 **修改 Ribbon 负载均衡策略** 1. **配置策略类** 首先,我们需要创建一个新的负载均衡策略类,继承自 `IRule` ...

    springcloud入门代码基于Spring Cloud实现的Ribbon客户端负载均衡模板代码

    5. **自定义负载均衡策略**:如果默认的负载均衡策略无法满足需求,我们可以创建自定义策略类,通过实现`IRule`接口并覆盖`choose`方法,然后在Ribbon客户端配置中指定这个策略。 在提供的压缩包文件"springcloud-...

    SpringCloud使用Ribbon实现负载均衡

    Spring Cloud是构建微服务架构的一套工具集,其中Ribbon是它提供的一个客户端负载均衡器,可以帮助我们实现服务间的智能路由。本篇文章将详细探讨如何在Spring Cloud中使用Ribbon实现负载均衡。 首先,我们要理解...

    SpringCloud-Ribbon负载均衡服务调用及手写Ribbon算法代码

    默认的Ribbon策略可能无法满足所有场景需求,因此我们可以自定义负载均衡算法。这通常通过实现IRule接口来完成,例如: ```java public class MyRule extends AbstractLoadBalancerRule { @Override public ...

    Ribbon负载均衡代码

    例如,可以自定义负载均衡策略,或者设置连接超时、重试机制等。 3. **IRule接口** Ribbon的核心是`IRule`接口,它定义了选择服务器的方法。Spring Cloud提供了一些默认的规则实现,如`RoundRobinRule`(轮询)、`...

    02Spring Cloud Ribbon:负载均衡的服务调用1

    此外,还可以通过Ribbon的`IClientConfig`接口和`IRule`接口自定义更复杂的负载均衡规则。 总之,Spring Cloud Ribbon结合`RestTemplate`为服务间的调用提供了负载均衡能力,使得微服务架构中的服务调用更加健壮和...

    spring_cloud_gateway负载均衡,动态路由

    spring cloud gateway的负载均衡和...gateway这个服务是 springcloude gateway + ribbon 做的负载均衡 gateway_01 这个服务 是动态路由的实现 其中redis部分,有一个jar是自己封装的,可以自己手写redis工具类替换掉

    1、Nocas入门案例 2、通过Ribbon实现负载均衡 3、通过Nocas实现服务的注册、发现

    在 nocas入门-demo 中,你可能看到配置了Ribbon的客户端,如设置默认的负载均衡策略或自定义策略。Ribbon支持多种负载均衡算法,如轮询(Round Robin)、随机(Random)、最少活跃连接数(Least Active)等。通过...

    客户端负载均衡器Ribbon(实验代码)

    4. **自定义负载均衡策略**:如果需要自定义负载均衡规则,可以创建一个新的`IRule`实现,并在客户端配置中指定使用该规则。 实验步骤可能包括以下部分: 1. **搭建环境**:安装并配置Eureka服务器,启动一些...

    Springboot集成Netflix-ribbon、Enreka实现负载均衡-源码

    此外,还可以很容易地使用Ribbon实现自定义的负载均衡算法。 Ribbon属于进程内负载均衡,它只是一个类库,集成于服务消费方进程,消费方通过它来获取到服务提供方的地址。在Netflix的架构中,Ribbon通常与Eureka...

    SpringCloud-Ribbon,使用RestfulTemplate实现负载均衡练习

    在实际项目中,还可以根据需要自定义负载均衡策略,或者与其他Spring Cloud组件(如Hystrix、zuul)结合,实现更复杂的微服务架构功能。在压缩包文件"Ribbon-RestfulTemplete"中,可能包含了示例代码和配置文件,...

    浅谈Spring Cloud Ribbon的原理

    Ribbon的优点是可以简化服务集群内的架构,提供客户端的软件负载均衡算法,并且可以自定义负载均衡算法。Ribbon与Eureka的紧密结合,使得服务调用端具备负载均衡能力,不用在服务集群内再架设负载均衡服务。 在使用...

    SpringCloud之四 负载均衡Feign

    4. **集成Ribbon**:Feign默认集成了Ribbon,Ribbon是一个客户端负载均衡器,它能够帮助Feign在调用远程服务时实现负载均衡。 5. **与Eureka整合**:通过与Eureka的整合,Feign能够利用服务注册与发现机制来选择合适...

    第二节 微服务之负载均衡组件Ribbon1

    本节将深入探讨两种主要的负载均衡实现方式:服务端负载均衡和服务端负载均衡,并重点讲解Spring Cloud Ribbon作为客户端负载均衡器的应用。 1. **服务端负载均衡(Nginx)** - Nginx 是一种广泛应用的服务端负载...

    02 微服务负载均衡器Ribbon&LoadBalancer实战.pdf

    同时,Ribbon也支持自定义负载均衡策略。 要集成Ribbon到Spring Cloud项目中,需引入相应依赖并配置`@LoadBalanced`注解到`RestTemplate`,使其实现客户端负载均衡能力。此外,Ribbon还提供了多种扩展功能,如修改...

    springcloud-搭建微服务(聚合工程)及配置Eureka(搭建Eureka集群)+负载均衡(Ribbon)调用eureka服务

    4. 配置Ribbon,指定使用Eureka作为服务列表来源,并自定义负载均衡策略(如果需要)。 5. 在服务消费者中,通过`@LoadBalanced`注解的RestTemplate或Feign客户端,实现对服务提供者的负载均衡调用。 以上就是关于...

    基于Ribbon的微服务通讯及负载均衡的实现_迟殿委.pdf

    【基于Ribbon的微服务通讯及负载均衡的实现】 微服务架构是现代软件开发领域的一种重要模式,它提倡将大型的复杂应用分解为一组小型、独立的服务,每个服务都能独立开发、部署和扩展。这样的设计使得系统更具灵活性...

Global site tag (gtag.js) - Google Analytics