Spring Cloud Ribbon

本文详细介绍了Spring Cloud Ribbon作为客户端负载均衡器的使用,包括如何脱离Eureka独立使用,如何在Eureka中配合使用,以及Ribbon的常用配置如饥饿加载、策略选择等。示例展示了Ribbon如何实现轮询访问服务实例,并提供了配置不同负载均衡策略的方法。
摘要由CSDN通过智能技术生成

客户端负载均衡Ribbon

在整个微服务架构中,为了保证各个服务的高可用,一定少不了负载均衡。目前主流的负载均衡实现就两种:一种是服务端实现负载均衡,有硬件的(比如F5),也有软件的(比如Nginx)。另一种就是客户端根据自己的请求情况实现负载均衡。常见的,一个服务A,部署到3台机器,A1,A2和A3,配合Nginx形成一个简单的集群,当客户端请求过来之后,随机访问A1、A2、A3,这就是服务端负载均衡;同样的,将A服务部署到3台机器,A1、A2、A3,当客户端自己记录自己的请求情况,依次访问A1、A2、A3或者基数秒访问基数服务,偶数秒访问偶数服务,这就是客户端负载均衡。

Ribbon是Netflix开源的一款用于客户端负载均衡的工具,也是Sprong Cloud Netflix中的一员。它主要的实现是,首先通过Eureka获取相关服务的信息,然后通过一定的负载均衡算法去访问不同的服务。如下图:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTM4MTg2Mw==,size_16,color_FFFFFF,t_70

关于Ribbon的依赖

在目前的Spring Cloud版本中,已经默认将Ribbon加入,所以也不用单独引用Ribbon依赖,如果下面的示例无法进行,则在相关项目中加入Ribbon依赖。

<dependency>
    <groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

脱离Eureka单独使用Ribbon

注:下述3个项目,我这里分别以cloud-server0,cloud-server1,cloud-server2命名。

1、创建2个简单的项目(cloud-server0和cloud-server1项目,这里表示同一个项目部署了两套),并且都将2个项目命名为同一个服务名,并提供2个简单的接口,如下:

spring.application.name=cloud-balanced

第一个服务(cloud-server0项目中编写)

@Controller
public class Server0Controller {

	// 当前接口使用的服务端口是:9000
	@GetMapping("/ribbon/api")
	@ResponseBody
	public String methodB() {
		return "我是服务0:9000";
	}
}

第二个服务(cloud-server1项目中编写)

@Controller
public class Server1Controller {

	// 当前接口使用的服务端口是:9001
	@GetMapping("/ribbon/api")
	@ResponseBody
	public String methodC() {
		return "我是服务1:9001";
	}
}

2、创建第3个项目(cloud-server2项目,这里需要创建为Spring Cloud项目),编写负载均衡实现

public class RibbonTest {

	public static void main(String[] args) {
		// 创建服务列表
		Server server1 = new Server("localhost", 9000);
		Server server2 = new Server("localhost", 9001);
		List<Server> serverList = new ArrayList<>();
		serverList.add(server1);
		serverList.add(server2);

		// 创建负载实例
		BaseLoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);

		// 调用10次观察效果
		for (int i = 0; i < 10; i++) {

			ServerOperation<String> serverOperation = new ServerOperation<String>() {

				@Override
				public Observable<String> call(Server server) {
					String requestUrl = "http://" + server.getHost() + ":" + server.getPort() + "/ribbon/api";
					System.out.println("请求地址: " + requestUrl);
					try {
						URL  url = new URL(requestUrl);
						HttpURLConnection conn = (HttpURLConnection) url.openConnection();
						conn.setRequestMethod("GET");
						conn.connect();
						InputStream is = conn.getInputStream();
						byte [] bytes = new byte[1024];
						int length = is.read(bytes);
						return Observable.just(new String(bytes, 0, length));
					} catch (Exception e) {
						return Observable.error(e);
					}
				}
			};

			String result = LoadBalancerCommand.<String>builder().withLoadBalancer(loadBalancer).build().submit(serverOperation)
					.toBlocking().first();
			System.out.println("服务端响应结果: " + result);
		}

	}
}

3、执行后,可以看到是以轮询的方式对2个服务进行访问,结果如下:

请求地址: http://localhost:9001/ribbon/api
服务端响应结果: 我是服务1:9001
请求地址: http://localhost:9000/ribbon/api
服务端响应结果: 我是服务0:9000
请求地址: http://localhost:9001/ribbon/api
服务端响应结果: 我是服务1:9001
请求地址: http://localhost:9000/ribbon/api
服务端响应结果: 我是服务0:9000
请求地址: http://localhost:9001/ribbon/api
服务端响应结果: 我是服务1:9001
请求地址: http://localhost:9000/ribbon/api
服务端响应结果: 我是服务0:9000
请求地址: http://localhost:9001/ribbon/api
服务端响应结果: 我是服务1:9001
请求地址: http://localhost:9000/ribbon/api
服务端响应结果: 我是服务0:9000
请求地址: http://localhost:9001/ribbon/api
服务端响应结果: 我是服务1:9001
请求地址: http://localhost:9000/ribbon/api
服务端响应结果: 我是服务0:9000

在Eureka中使用Ribbon

注:下述eureka项目,我这里以cloud-eureka命名。

1、将上述3个项目都改造为Spring Cloud项目,并创建一个Eureka项目,然后将上述3个服务都注册到Eureka中去

注意:需要将前2个项目的服务名定义为同一个(cloud-server0和cloud-server1项目),在配置文件加入以下配置:

spring.application.name=cloud-balanced

2、在上述第3个项目中(在cloud-server2项目中编写),配置RestTemplate,如下:

@Configuration
public class RestTemplateConfig {

	// @LoadBalanced注解会将当前restTemplate bean作为LoadBanlanceClient接口的实现类装配为Spring容器中
	// 注意:使用了@LoadBalanced之后,服务之间的相互调用将不再支持ip+port的方式,只能以服务名称的方式相互访问
	@LoadBalanced
	@Bean
	public RestTemplate initRestTemplate() {
		// 这里只是简单配置RestTemplate,工作中请勿这么操作!!!
		return new RestTemplate();
	}
	
}

3、编写服务消费(在cloud-server2项目中编写)

@Controller
public class Server2Controller {

	@Autowired
	private RestTemplate restTemplate;
	
	@RequestMapping("/server2/api0")
	@ResponseBody
	public String methodA() {
		
		// ip+端口直接替换成服务提供者的名称进行服务消费
		String result = restTemplate.getForObject("http://cloud-balanced/ribbon/api", 
				String.class);
		System.out.println("请求结果: " + result);
		return result;
		
	}
	
}

4、启动上述4个项目之后,多次调用服务消费者接口(cloud-server2中的接口),可以看到,同样以轮询的方式进行服务消费,结果如下:

请求结果: 我是服务1:9001
请求结果: 我是服务2:9002
请求结果: 我是服务1:9001
请求结果: 我是服务2:9002
......

Ribbon常用配置

饥饿加载

所谓饥饿加载,字面意思就是和懒加载相对立。懒加载一般是需要用到的时候才去加载,饥饿加载则是,提前加载需要用到的东西。

在使用Ribbon对服务进行调用的时候,对服务的加载时间加上网络传输时间,很容易造成http调用超时,则可以开启饥饿加载来应对。

# 开启Ribbon饥饿加载
ribbon.eager-load.enabled=true
# 指定要饥饿加载的服务名,也就是需要调用的服务(比如上面的cloud-balanced),多个服务用英文逗号隔开
ribbon.eager-load.clients=cloud-balanced

 控制台有如下日志打印,说明已经为目标集群服务进行了饥饿加载,如下:

2021052122454271.png

禁用eureka

脱离eureka使用Ribbon(应该很少有这么干的吧),上面提供了编程式的访问服务,如果还想配合RestTemplate快速调用其他服务,就需要手动指定需要调用的服务地址,如下:

# 禁用eureka
ribbon.eureka.enabled=false
# 禁用 Eureka 后手动配置服务地址(多个服务配置多条).格式:服务名.ribbon.listOfServers,配置项的值为该服务的所有访问地址,用英文逗号隔开
cloud-balanced.ribbon.listOfServers=localhost:9000,localhost:9001

配置负载均衡策略

Ribbon默认的负载均衡策略是轮询(它们全部都实现Irule接口),当前使用版本,还提供以下策略:

1、BestAvailableRule   会优先跳过因多次访问故障而处于"熔断"状态的服务,然后选择一个并发最小的server

2、AvailabilityFilteringRule   会优先跳过因多次访问故障而处于"熔断"状态的server,以及跳过并发数超过阈值的server,然后对剩余server进行轮询访问

3、ZoneAvoidanceRule    基于区域和可用性筛选服务器的规则

4、RandomRule   在目标集群中随机选择一个Server

5、RetryRule     对于选定负载均衡策略(默认以轮询进行),再加上重试机制。简单来说就是,可以配合其他任何负载均衡策略,在指定时间内如果目标server没有响应,会进行重复访问。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTM4MTg2Mw==,size_16,color_FFFFFF,t_70

6、RoundRobinRule        (默认规则)最著名和最基本的负载均衡策略,即轮询规则。

7、WeightedResponseTimeRule    根据响应时间分配一个权重(Weight),响应时间越长,权重越小,被选中的可能性越低。如果统计值不足够计算,以轮询进行。(在低版本中是:ResponseTimeWeightedRule,已废弃)

负载均衡策略配置示例1(配置文件方式),如下:

# 选择随机策略作为cloud-balanced集群的负载策略
cloud-balanced.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

负载均衡策略配置示例1(代码配置方式,推荐以这种方式),如下:

// 一个集群创建一个空的配置类,指定@RibbonClient或@RibbonClients注解
// name:集群服务名  configuration:负载策略
// @RibbonClient用于指定一个服务集群,@RibbonClients用于指定多个服务集群,根据情况选择其中一个
@RibbonClient(name = "cloud-balanced", configuration = RandomRule.class)
@RibbonClients(value = {@RibbonClient(name = "cloud-balanced", configuration = RandomRule.class)})
public class RibbonLoadbalancerConfig {

}

 重试策略配合其他策略(这里以随机策略为例),配置完成之后再选择上述任意一种方式进行配置,示例:

@Configuration
public class RibbonConfig {

	// 重新装配RetryRule
	@Bean
	public RetryRule initRetryRule() {
		// 同时还提供两个有参的构造方法,可以点进源码查看
		RetryRule retryRule = new RetryRule();
		// 设置负载策略为随机
		retryRule.setRule(new RandomRule());
		// 设置最大重试超时时间,单位毫秒,默认为500毫秒
		retryRule.setMaxRetryMillis(1000);
		return retryRule;
	}
	
}

负载均衡策略配置示例1(自定义负载策略,实现IRule接口,然后再选择上述任意一种方式进行配置),如下:

// 这里不用再对MyRule进行装配为Spring Bean,因为Ribbon会为实现了IRule接口,且被指定为负载策略的类装配
public class MyRule implements IRule {

	private ILoadBalancer iLoadBalancer;
	
	// 定义负载均衡策略
	@Override
	public Server choose(Object key) {
		// 获取目标集群中所有server
		List<Server> servers = iLoadBalancer.getAllServers();
		// 永远返回第一个server,即永远访问第一个server
        // 具体可以去实现其他更复杂逻辑
		return servers.get(0);
	}

	@Override
	public void setLoadBalancer(ILoadBalancer lb) {
		this.iLoadBalancer = lb;
	}

	@Override
	public ILoadBalancer getLoadBalancer() {
		return iLoadBalancer;
	}

}

其它说明

像一些http访问超时之类的配置,因为Ribbon是配合RestTemplate使用,所以其他的一些配置应该作用于RestTemplate。又或者想使用其他重试框架,比如Spring Retry,Spring Retry是基于AOP实现的,则需要在代码中单独进行编写。一般来讲,默认使用Ribbon的重试机制即可,如果面临某些接口,需要一些特定的或者不同的重试策略的时候,就可以再考虑加入Spring Retry。

 

 

 

购物商城项目采用PHP+mysql有以及html+css jq以及layer.js datatables bootstorap等插件等开发,采用了MVC模式,建立一个完善的电商系统,通过不同用户的不同需求,进行相应的调配和处理,提高对购买用户进行配置….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值