SpringCloud 基础——Ribbon 负载均衡(RestTemplate 与 Feign)

源码地址:https://pan.baidu.com/s/1Hmvh1Bbss_Z1w1I7I1mwDw 提取码:e41h

由于微服务数量繁多,一个服务一台服务器显然不够安全,必须配置集群以实现高可用。既然一个服务有多台服务器,那地址、端口也将不同,那么该如何调用服务?服务调用又有哪些策略呢?
下面来看看负载均衡组件 Ribbon 是如何实现的吧。

一、创建一个 servcieA2 服务

这个服务工程与之前的 serviceA1 服务工程一样,只要改一下端口即可,我这里是用的 7072 端口。服务名同 serviceA1 服务工程,都命名为 serviceA。

二、Ribbon + RestTemplate

要使用负载均衡,我们需要在 service-rest 服务加一些东西。
1. pom.xml 文件中加入 Ribbon 依赖

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-ribbon</artifactId>
	<version>1.4.2.RELEASE</version>
</dependency>

2. 记得把 service 类中的方法调用改为用服务名调用,因为用主机+端口是调用了一个指定的服务,而用服务名是指定了一个服务的集群。

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ServiceRestService {
	@Autowired
	private RestTemplate restTemplate;
	
	@SuppressWarnings("unchecked")
	public List<String> getServiceA(){
		return restTemplate.getForObject("http://serviceA/getList", List.class);
//		return restTemplate.getForEntity("http://localhost:7071/getList", List.class).getBody();
	}
	
}

3. 启动类的 restTemplate() 中加入 @LoadBalanced 注解。到这里,就加入了负载均衡功能,负载均衡策略是默认的轮询机制。

	@Bean
	@LoadBalanced
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}

4. 使用自带的其他负载均衡策略。新建一个 BalanceRule 类,如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;

@Configuration
public class BalanceRule {
	@Bean
    public IRule myRule(){
        //return new RoundRobinRule();//轮询
        //return new RetryRule();//重试
        return new RandomRule(); // 随机
        //return new DefineRule();  // 自定义策略
    }
/*	// 同一应用范围不能有多种策略,会报错
	@Bean
	public IRule myRule2(){
		return new RoundRobinRule();//轮询
	}
*/	
}

Ribbon 已经定义了 7 中负载均衡策略,可直接使用。

策略名策略声明策略描述
BestAvailableRulepublic class BestAvailableRule extends ClientConfigEnabledRoundRobinRule选择一个最小的并发请求的server
AvailabilityFilteringRulepublic class AvailabilityFilteringRule extends PredicateBasedRule过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值)
WeightedResponseTimeRulepublic class WeightedResponseTimeRule extends RoundRobinRule根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。
RetryRulepublic class RetryRule extends AbstractLoadBalancerRule对选定的负载均衡策略机上重试机制。
RoundRobinRulepublic class RoundRobinRule extends AbstractLoadBalancerRuleroundRobin方式轮询选择server
RandomRulepublic class RandomRule extends AbstractLoadBalancerRule随机选择一个server
ZoneAvoidanceRulepublic class ZoneAvoidanceRule extends PredicateBasedRule复合判断server所在区域的性能和server的可用性选择server

以上总结来自 https://blog.csdn.net/rickiyeat/article/details/64918756

5. 自定义负载均衡策略。新建一个 DefineRule 类

import java.util.List;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

public class DefineRule extends AbstractLoadBalancerRule {

	// 每台被调用的次数,当前要求每台被调用3次
	private int total = 0;
	// 当前提供服务的机器在服务列表的索引
	private int currentIndex = 0;

	@Override
	public void initWithNiwsConfig(IClientConfig iClientConfig) {
	}

	// 在choose方法中,自定义我们自己的规则,返回的Server就是具体选择出来的服务 
	// 当前规则:按照轮询的规则,但是每个被轮询到的服务调用3次。
	@SuppressWarnings("unused")
	@Override
	public Server choose(Object o) {
		// 获取负载均衡器lb
		ILoadBalancer lb = getLoadBalancer();
		if (lb == null) {
			return null;
		}

		Server server = null;
		while (server == null) {
			if (Thread.interrupted()) {
				return null;
			}
			// 获取可用服务列表
			List<Server> upList = lb.getReachableServers();
			// 获取所有服务列表
			List<Server> allList = lb.getAllServers();
			int serverCount = allList.size();
			if (serverCount == 0) {
				return null;
			}

			// 若调用次数小于3次,一直调用可用服务列表中索引为 currentIndex 的服务
			if (total < 3) {
				server = upList.get(currentIndex);
				total++;
			} else {
				// 到了3次之后,服务列表中的索引值++,表示下一次调用下一个服务
				total = 0;
				currentIndex++;
				// 当索引大于可用服务列表的size时,要重新从头开始
				currentIndex = currentIndex % upList.size();

				if (server == null) {
					Thread.yield();
					continue;
				}

				if (server.isAlive()) {
					return (server);
				}

				server = null;
				Thread.yield();
			}
		}
		return server;
	}
}

(1)要使用自定义负载均衡策略时,直接在 BalanceRule 类中 return new DefineRule(); 即可
(2)也可以在启动类加入注解 @RibbonClient(name="serviceA", configuration=DefineRule.class) ,表示调用 serviceA 服务时使用 DefineRule 自定义负载均衡策略。
(3)可以给其他服务指定不同的负载均衡策略,在启动类加入如下注解:

@RibbonClients(value= {
		@RibbonClient(name="serviceA", configuration=DefineRule.class),
		@RibbonClient(name="", configuration=xxx.class),
		@RibbonClient(name="", configuration=xxx.class)
})

三、Ribbon + Feign

Feign 组件默认集成了 Ribbon 功能,所以引入了 Feign 依赖就可以不引入 Ribbon 依赖了,不过继续引入也不报错。启动类不用另外加注解。
Feign 服务调用使用的负载均衡策略也是默认的轮询机制,当然也可以使用自带的另外 6 种负载均衡策略,也能用自定义的负载均衡策略,用法同 Ribbon + RestTemplate。后面就不赘述了。

博主经验尚浅,也暂无微服务相关项目经验,如果理解不到位甚至理解错误,希望评论区讨论,请多指教!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值