当前位置:首页 > 服务端 > Nacos实现服务间的负载均衡

Nacos实现服务间的负载均衡

2022年09月16日 23:20:33服务端8

一点背景

Nacos支持权重配置,是比较实用的功能。例如可以把好的机器权重升高,让硬件资源好的服务器享受更高的优先级;在某个服务器出现异常的时候可以降低这个服务器的权重或者暂时停止这个服务器的流量。

Nacos是自带Ribbon的。Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。

Nacos配置负载均衡Demo

继续采用之前的项目进行改进来跑负载均衡。之前的项目:Nacos安装(docker),运行,持久化(单机MySQL),Eureka迁移至Nacos

总体结构

Nacos实现服务间的负载均衡 _ JavaClub全栈架构师技术笔记

Nacos实现服务间的负载均衡 _ JavaClub全栈架构师技术笔记

首先是两个服务provider:

ProviderApplication.java

@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {

	public static void main(String[] args) {
		SpringApplication.run(ProviderApplication.class, args);
	}

	@RestController
	class EchoController {
		@Value("${server.port}")
		private String port;

		@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
		public String echo(@PathVariable String string) {
			System.out.println(string);

			return "Hello Nacos Discovery00 " + "server port : " + port + string;
		}
	}
}

Controller返回一行字符串+当前服务的端口。

配置文件:

application.properties:

server.port=8080
spring.application.name=service-provider

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

另外一个服务Provider01提供相同的服务,端口在8081。

定义一个消费者Consumer:

ConsumerApplication.java

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {

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

	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}

	@RestController
	public class TestController {
		@Autowired
		private RestTemplate restTemplate;

		@RequestMapping(value = "/echos", method = RequestMethod.GET)
		public String echo() {
//			System.out.println("str:"+str);
			return restTemplate.getForObject("http://service-provider/echo/mxb", String.class);
		}
	}
}

他的作用是调用服务service-provider。

配置文件:

application.properties:

server.port=8070
spring.application.name=service-consumer

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

他运行在8070。

这样就可以运行起来服务了,效果如下:

把他们全部run起来:

Nacos实现服务间的负载均衡 _ JavaClub全栈架构师技术笔记

我们访问 http://localhost:8070/echos,可以看到:

Nacos实现服务间的负载均衡 _ JavaClub全栈架构师技术笔记

刷新一下可以看到:

Nacos实现服务间的负载均衡 _ JavaClub全栈架构师技术笔记

默认方式下是轮询,所以每次刷新都会换一个服务。

Nacos实现服务间的负载均衡 _ JavaClub全栈架构师技术笔记

在Nacos控制台上可以看到两个服务,其中provider的实例数是两个。

实现在Nacos控制台上配置服务权重

Nacos默认是轮询。此时在控制台上修改服务的权重是无效的,仍然是轮询。

Nacos实现服务间的负载均衡 _ JavaClub全栈架构师技术笔记

可以在消费者Consumer的代码上面加上:

ConsumerApplication.java

@Bean
@Scope(value = "prototype")
public IRule loadBalanceRule()
{
	return new NacosRule();
}

这样就可以支持在控制台上手动配置权重了。

参考了博客:微服务实战(七)实现服务负载均衡 - SpringCloud GateWay + Nacos + Robin

那么为什么这样可以实现呢?怎样实现这种人工赋权的呢?

阅读一下Nacos的源码

在package com.alibaba.cloud.nacos.ribbon下,有个NacosRule类继承自AbstractLoadBalancerRule,内容如下:

/**
 * Supports preferentially calling the ribbon load balancing rules of the same cluster
 * instance.
 *
 * @author itmuch.com
 */
public class NacosRule extends AbstractLoadBalancerRule {

	private static final Logger LOGGER = LoggerFactory.getLogger(NacosRule.class);

	@Autowired
	private NacosDiscoveryProperties nacosDiscoveryProperties;

	@Autowired
	private NacosServiceManager nacosServiceManager;

	@Override
	public Server choose(Object key) {
		try {
			String clusterName = this.nacosDiscoveryProperties.getClusterName();
			String group = this.nacosDiscoveryProperties.getGroup();
			DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
			String name = loadBalancer.getName();

			NamingService namingService = nacosServiceManager
					.getNamingService(nacosDiscoveryProperties.getNacosProperties());
			List<Instance> instances = namingService.selectInstances(name, group, true);
			if (CollectionUtils.isEmpty(instances)) {
				LOGGER.warn("no instance in service {}", name);
				return null;
			}

			List<Instance> instancesToChoose = instances;
			if (StringUtils.isNotBlank(clusterName)) {
				List<Instance> sameClusterInstances = instances.stream()
						.filter(instance -> Objects.equals(clusterName,
								instance.getClusterName()))
						.collect(Collectors.toList());
				if (!CollectionUtils.isEmpty(sameClusterInstances)) {
					instancesToChoose = sameClusterInstances;
				}
				else {
					LOGGER.warn(
							"A cross-cluster call occurs,name = {}, clusterName = {}, instance = {}",
							name, clusterName, instances);
				}
			}

			Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose);

			return new NacosServer(instance);
		}
		catch (Exception e) {
			LOGGER.warn("NacosRule error", e);
			return null;
		}
	}

	@Override
	public void initWithNiwsConfig(IClientConfig iClientConfig) {
	}

}

其中,重载的choose函数实现了对Server的选择。

NacosRule.choose(Object key)调用了
ExtendBalancer.getHostByRandomWeight2(List<Instance> instances)调用了
Balancer.getHostByRandomWeight(List<Instance> hosts)调用了
Chooser<K, T>.randomWithWeight()

在randomWithWeight里面,先生成了一个double类型的随机数random,然后对所有的权重weight数组double weight[]进行二分查找Arrays.binarySearch(weights,random)。

这个二分查找的解释是:

     * Searches the specified array of doubles for the specified value using
     * the binary search algorithm.  The array must be sorted
     * (as by the {@link #sort(double[])} method) prior to making this call.
     * If it is not sorted, the results are undefined.  If the array contains
     * multiple elements with the specified value, there is no guarantee which
     * one will be found.  This method considers all NaN values to be
     * equivalent and equal.

那么这个weight里面到底是什么呢?

在class Ref<T>里面,有个refresh()函数,可以看出来这个weight数组存的是累计占比。

获取的大致原理学习了博客:java中根据权重随机获取数据根据权重随机选取指定条数记录的简单算法实现(C#)

Nacos实现服务间的负载均衡 _ JavaClub全栈架构师技术笔记

Ribbon默认的rule是轮询,因此在没有设置的情况下默认规则是轮询。如果想使用结合Nacos后台权重设置的策略,只需要将 NacosRule 注册成为Bean,替换默认的 Rule即可。

参考博客

微服务实战(七)实现服务负载均衡 - SpringCloud GateWay + Nacos + Robin

java中根据权重随机获取数据

根据权重随机选取指定条数记录的简单算法实现(C#)

作者:mxb1234567
来源链接:https://blog.csdn.net/mxb1234567/article/details/109532872

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/server/42336.html

标签: Nacos
分享给朋友:

“Nacos实现服务间的负载均衡” 的相关文章

SpringBoot项目改为SpringCloud项目使用nacos作为注册中心

SpringBoot项目改为SpringCloud项目使用nacos作为注册中心

本章讲解的是在不改变原有业务的情况下将springboot改为springcloud项目使用nacos作为注册中心 首先在官网下载好nacos注册中心,在bin目录中startup.cmd文件为启动命令默认端口号是8888 接下来修改原有项目依赖...

nacos启动教程

nacos启动教程

1、下载nacos压缩包 链接:https://pan.baidu.com/s/1PE6D73rIuOhnfvKVqvDwhA  提取码:oj9y 2、解压  3、修改conf里的配置文件(application.properties...

Nacos数据库配置

Nacos数据库配置

本文来说下nacos数据库配置 文章目录 Nacos控制面板,新建配置 Nacos数据库配置 初始化mysql 修改配置文件 本文小结...

windows下安装nacos

windows下安装nacos

1、下载 下载地址:https://github.com/alibaba/nacos/releases/tag/1.1.0 选择这个zip下载。 下载完毕后我们可以看看目录结构: 这里的bin目录里面有windows启动文件startup.cmd,...

nacos配置中心无法连接或启动报错

nacos配置中心无法连接或启动报错

如果你启动后是下面这样的,那就说明你连接上了,并且红框中最右边的name就是你在配置中心里的DataId 如果你启动后没有上面那样或者是报错,并且你的代码没问题,那最有可能就是版本不兼容,可以参考下面的版本 <parent>...

nacos 适配达梦、人大金仓数据库

nacos 适配达梦、人大金仓数据库

文章目录 一、准备工作...

Nacos入门基础

Nacos入门基础

一、Nacos 1、基本概念 (1) Nacos 是阿里巴巴推出来的一个新开源项目,是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助...

ubuntu安装nacos

ubuntu安装nacos

1.下载nacos,github下载地址:https://github.com/alibaba/nacos/releases 选用目前最新的版本:1.3.0,这个版本直接在页面就可以修改nacos登录密码,并且还可以创建其他的登录用户,之前用过1.0.0版本如果修改naco...

Nacos快速入门(一):Nacos初探

Nacos快速入门(一):Nacos初探

1、简介 Nacos官网:https://nacos.io/zh-cn/index.html 1.1、概览 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服...

Nacos的简单使用

Nacos的简单使用

一、Nacos简介 Nacos是阿里系开发的兼容Spring Cloud的服务注册中心组件,是微服务国产化的先驱。Nacos作为与Eureka的对比,不仅具有Eureka固有的集群化、注册中心等功能,还具有配置中心的功能,并且更加简单使用,拆箱即用,也支持二次开发...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。