Spring Cloud LoadBalancer是一个客户端负载均衡器,类似于Ribbon,但是由于Ribbon已经进入维护模式,所以Spring Cloud全家桶在Spring Cloud Commons项目中,添加了Spring cloud Loadbalancer作为新的负载均衡器。

客户端负载均衡

Loadbalancer与Ribbon都是客户端负载均衡,说白就是在客户端获取能够调用的服务列表,通过随机、轮询、权重配置、ip、健康检测等负载策略,选择要调用的服务实例。
相对而言服务端的负载均衡就是客户端发起调用后,服务器端比如Nginx组件在维护的服务列表中通过负载均衡选择一个响应请求的服务实例。同样Nginx也可以在upstream中配置随机、轮询等负载均衡策略。

image-aksb.png

image-xuui.png

LoadBalancer源码浅析

LoadBalancer默认支持随机RandomLoadBalancer跟轮询RoundRobinLoadBalancer两种负载均衡策略。RandomLoadBalancerchoose方法就是从客户端获取的服务列表中随机选择一个服务。
服务列表由ServiceInstanceListSupplier的实现类提供,这里我们微服务调用通过DiscoveryClientServiceInstanceListSupplier代理类从注册中心上面获取ServiceInstanceList,Nacos的底层实现类是NacosReactiveDiscoveryClient

diagram.png

public class RandomLoadBalancer implements ReactorServiceInstanceLoadBalancer {

	private static final Log log = LogFactory.getLog(RandomLoadBalancer.class);

	private final String serviceId;

	private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;

	/**
	 * @param serviceInstanceListSupplierProvider a provider of
	 * {@link ServiceInstanceListSupplier} that will be used to get available instances
	 * @param serviceId id of the service for which to choose an instance
	 */
	public RandomLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,
			String serviceId) {
		this.serviceId = serviceId;
		this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
	}

	@SuppressWarnings("rawtypes")
	@Override
	public Mono<Response<ServiceInstance>> choose(Request request) {
		ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider
				.getIfAvailable(NoopServiceInstanceListSupplier::new);
		return supplier.get(request).next()
				.map(serviceInstances -> processInstanceResponse(supplier, serviceInstances));
	}

	private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier,
			List<ServiceInstance> serviceInstances) {
		Response<ServiceInstance> serviceInstanceResponse = getInstanceResponse(serviceInstances);
		if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
			((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
		}
		return serviceInstanceResponse;
	}

	private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
		if (instances.isEmpty()) {
			if (log.isWarnEnabled()) {
				log.warn("No servers available for service: " + serviceId);
			}
			return new EmptyResponse();
		}
		int index = ThreadLocalRandom.current().nextInt(instances.size());

		ServiceInstance instance = instances.get(index);

		return new DefaultResponse(instance);
	}

}
文章作者: 编程之家
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 编程之家
springcloud 客户端负载 fegin nacos loadBlancer
喜欢就支持一下吧