电商商城定制开发【云原生】SpringCloud系列之客户端负载均衡Ribbon

【】SpringCloud电商商城定制开发系列之客户电商商城定制开发端负载均衡Ribbon

基本概念

电商商城定制开发在微服务架构中,电商商城定制开发负载均衡是必须使用的技术,电商商城定制开发通过它来实现系统的高可用、电商商城定制开发集群扩容等功能。电商商城定制开发负载均衡可以分为两种:电商商城定制开发服务端负载均衡和客户端负载均衡。电商商城定制开发通常所说的负载均衡指服务器负载均衡,可通过硬件设备或软件来实现,硬件比如:F5、Array等,软件比如:LVS、Nginx等。
负载均衡按实现方式分类可区分为:服务端负载均衡(比如Nacos负载均衡)客户端负载均衡
SpringCloud 是基于客户端的负载均衡工具,它可以将面向服务的 REST 模板请求自动转换成客户端负载均衡的服务调用。执行过程如下图:

  1. 服务消费者与服务提供者实例在启动时向 Nacos 注册;
  2. 订单服务向商品服务发起通信前,Ribbon 向 Nacos 查询商品服务的可用实例列表;
  3. Ribbon 根据设置的负载策略从服务提供者可用实例列表中选择实例;
  4. 服务消费者实例向服务提供者实例发起请求,完成 RESTful 通信;

Ribbon 是由 Netflix 发布的负载均衡器,它有助于控制 HTTP 和 TCP 的客户端的行为。Ribbon 属于客户端负载均衡。
为 Ribbon 配置服务提供者地址后,Ribbon 就可基于某种负载均衡算法,自动的帮助服务消费者进行请求。同时 Ribbon 默认为我们提供了很多负载均衡算法,例如:轮询、随机算法等。

配置 Ribbon

Ribbon 内置多种负载均衡策略,常用的分为以下几种。

  • RoundRobinRule:

轮询策略,Ribbon 默认策略。默认超过 10 次获取到的 server 都不可用,会返回⼀个空的 server。

  • RandomRule:

随机策略,如果随机到的 server 为 null 或者不可用的话。会不停地循环选取。

  • RetryRule

重试策略,⼀定时限内循环重试。默认继承 RoundRobinRule,也⽀持自定义注⼊,RetryRule 会在每次选取之后,对选举的 server 进⾏判断,是否为 null,是否 alive,并且在 500ms 内会不停地选取判断。而 RoundRobinRule 失效的策略是超过 10 次,RandomRule 没有失效时间的概念,只要 serverList 没都挂。

  • BestAvailableRule

最小连接数策略,遍历 serverList,选取出可⽤的且连接数最小的⼀个 server。那么会调用 RoundRobinRule 重新选取。

  • AvailabilityFilteringRule

可用过滤策略。扩展了轮询策略,会先通过默认的轮询选取⼀个 server,再去判断该 server 是否超时可用、当前连接数是否超限,都成功再返回。

  • ZoneAvoidanceRule

区域权衡策略。扩展了轮询策略,除了过滤超时和链接数过多的 server,还会过滤掉不符合要求的 zone 区域⾥⾯的所有节点,始终保证在⼀个区域/机房内的服务实例进行轮询。
这里所有负载均衡策略名本质都是 com.netflix.loadbalancer 包下的类:

要更改微服务通信时采用的负载均衡策略也很简单,在 application.yml 中采用下面格式书写即可。

provider-service: #服务提供者的微服务id   ribbon:     NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #设置对应的负载均衡类 
  • 1
  • 2
  • 3

当采用随机策略,杂乱的顺序说明随机策略已生效。

Ribbon主要组件和作用

ILoadBalancer:定义一系列的操作接口,比如选择服务实例。

IRule:算法策略,内置算法策略来为服务实例的选择提供服务。

ServerList:负责服务实例信息的获取,可以获取配置文件中的,也可以从注册中心获取。

ServerListFilter:过滤掉某些不想要的服务实例信息。

ServerListUpdater:更新本地缓存的服务实例信息。

IPing:对已有的服务实例进行可用性检查,保证选择的服务都是可用的。

如果需要自定义相关组件,需要实现上述接口。

Ribbon使用

Ribbon 的使用方式主要分为下面这三种,

  1. 原生 API,Ribbon 是 Netflix 开源的,如果你没有使用 Spring Cloud,也可以在项目中单独使用 Ribbon,在这种场景下就需要使用 Ribbon 的原生 API。
  2. Ribbon + RestTemplate,当我们项目整合了 Spring Cloud 时,就可以用 Ribbon 为 RestTemplate 提供负载均衡的服务。
  3. Ribbon + Feign,关于 Feign 的使用方式后续我会继续整理到博客中,欢迎持续关注。

原生API

配置一个服务列表,数据格式为 IP + PORT,可以固定写几个服务列表,也可以从别处读取,比如注册中心。
构建一个负载实例,将服务列表传入,再指定对应的负载均衡策略,RandomRule 是随机策略。具体的应用逻辑写在 call 方法里,call 方法的参数是 Server 对象,Server 也就是我们第一步构建的服务列表信息,得到 Server 后就可以获取到对应的 IP 和端口,然后进行接口的调用。
代码案例如下:

	/**	 * 轮询请求测试	 */	@Test	public void roundRobinRuleTest(){		// 服务列表		List<Server> serverList = Arrays.asList(new Server("localhost", 8080),				new Server("localhost", 8081),				new Server("localhost", 8082));		// 构建负载实例		BaseLoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder().buildFixedServerListLoadBalancer(serverList);		loadBalancer.setRule(new RoundRobinRule());		// 调用5次来测试效果		for (int i = 0; i < 6; i++) {			String result = LoadBalancerCommand.<String>builder().withLoadBalancer(loadBalancer).build()					.submit(new ServerOperation<String>() {						@Override						public Observable<String> call(Server server) {							try {								String addr = "http://" + server.getHost() + ":" + server.getPort();								System.out.println("调用地址:" + addr);								return Observable.just("");							} catch (Exception e) {								return Observable.error(e);							}						}					}).toBlocking().first();			System.out.println("调用结果:" + result);		}	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

RestTemplate调用

RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。
将 RestTemplate 和 Ribbon 整合起来,只需要在配置 RestTemplate 实例的时候,加一个 @LoadBalanced 的注解,这样 RestTemplate 在调用接口时,就不需要用固定的 IP 加端口的方式调用接口,而是可以用服务名称的方式进行接口的调用,自动具备客户端负载均衡的效果。

// RestTemplate 配置类@Configurationpublic class RestConfiguration {	@Bean    // @LoadBalanced 注解让RestTemplate 能够直接使用服务名称调用对应的接口	@LoadBalanced	public RestTemplate restTemplate() {		return new RestTemplate();	}	}    @Autowired	private RestTemplate restTemplate;		@GetMapping("/get")	public Object get() {		User user = restTemplate.getForEntity("http://system-service/user/get?id=1", User.class).getBody();		//User user = restTemplate.getForEntity("http://localhost:8084/user/get?id=1", User.class).getBody();		return user;	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位大佬指出。
主页

保持热爱,奔赴下一场山海。🏃🏃🏃

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发