1. ribbon-loadbalancer-2.3.0.jar 是负载均衡的祖师爷

其中gateway集成了ribbon; nacos和ribbon也有集成。最终达到一个结果,在ribbon中维护这一个列表,ancos服务发现的列表,做负载均衡,注意是ribbon中维护这这个列表,并不是复杂均衡的时候采取和nacos交互。
如果服务有变化,这个列表也会做相应的调整。

2 . 最顶级的接口ILoadBalancer.java

所有的负载均衡实现类均要实现此接口,比如: DynamicServerListLoadBalancer.java

/**
 * Interface that defines the operations for a software loadbalancer. A typical
 * loadbalancer minimally need a set of servers to loadbalance for, a method to
 * mark a particular server to be out of rotation and a call that will choose a
 * server from the existing list of server.
 * 
 * 负载均衡的顶级接口
 * @author stonse
 * 
 */
public interface ILoadBalancer {

	/**
	 * Initial list of servers.
	 * This API also serves to add additional ones at a later time
	 * The same logical server (host:port) could essentially be added multiple times
	 * (helpful in cases where you want to give more "weightage" perhaps ..)
	 * 
	 * @param newServers new servers to add
	 * 添加服务器到这个列表中List<Server> newServers
	 */
	public void addServers(List<Server> newServers);
	
	/**
	 * Choose a server from load balancer.
	 * 
	 * @param key An object that the load balancer may use to determine which server to return. null if 
	 *         the load balancer does not use this parameter.
	 * @return server chosen
	 * 从List<Server> newServers中选择一个服务器作为次轮的负载服务器
	 */
	public Server chooseServer(Object key);
	
	/**
	 * To be called by the clients of the load balancer to notify that a Server is down
	 * else, the LB will think its still Alive until the next Ping cycle - potentially
	 * (assuming that the LB Impl does a ping)
	 * 
	 * @param server Server to mark as down
	 * 标记此服务为下线(关闭)状态。
	 */
	public void markServerDown(Server server);
	
	/**
	 * @deprecated 2016-01-20 This method is deprecated in favor of the
	 * cleaner {@link #getReachableServers} (equivalent to availableOnly=true)
	 * and {@link #getAllServers} API (equivalent to availableOnly=false).
	 *
	 * Get the current list of servers.
	 * 获取当前服务器列表
	 *
	 * @param availableOnly if true, only live and available servers should be returned
	 * 如果为true则返回活着并且可用的服务器列表
	 */
	@Deprecated
	public List<Server> getServerList(boolean availableOnly);

	/**
	 * @return Only the servers that are up and reachable.
	 * 返回可用的serer列表
     */
    public List<Server> getReachableServers();

    /**
     * @return All known servers, both reachable and unreachable.
     * 获取所以的server列表,可用不可用的均可以获得。
     */
	public List<Server> getAllServers();
}

有了这个接口我们可以对持有服务列表的list进行任何操作。整理架构建立了。

spirngcloudgateway 自定义实现负载均衡_Server

3. 此类是对服务列表进行更新,比如服务的上线,下线等。

DynamicServerListLoadBalancer.java 类是ribbon的自己实现的。

spirngcloudgateway 自定义实现负载均衡_ribbon和nacos_02

负载均衡在ribbon中的自我实现策略,默认为轮训,我们可以按自己的需求自己实现即可。

spirngcloudgateway 自定义实现负载均衡_List_03

4. ServerList.java

此类是ribbon持有服务列表的接口类,其他任何三方的服务注册与发现中心可以实现它,比如此处我们使用的是nacos所谓服务发现与注册中心,则alibaba就实现了这个接口NacosServerList.java 就是对这个接口的实现。

spirngcloudgateway 自定义实现负载均衡_ribbon和nacos_04


因此,项目需要引入nacos的依赖。

5. NacosServerList.java

NacosServerList.java 和nacos进行通讯,可以对其服务的状态进行感知进而进行
下面看源码:

/*
 * Copyright 2013-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.alibaba.cloud.nacos.ribbon;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractServerList;

/**
 * @author xiaojing
 * @author renhaojun
 */
public class NacosServerList extends AbstractServerList<NacosServer> {

	private NacosDiscoveryProperties discoveryProperties;

	private String serviceId;

	public NacosServerList(NacosDiscoveryProperties discoveryProperties) {
		this.discoveryProperties = discoveryProperties;
	}

	@Override
	public List<NacosServer> getInitialListOfServers() {
		return getServers();
	}

	@Override
	public List<NacosServer> getUpdatedListOfServers() {
		return getServers();
	}

	private List<NacosServer> getServers() {
		try {
			String group = discoveryProperties.getGroup();
			List<Instance> instances = discoveryProperties.namingServiceInstance()
					.selectInstances(serviceId, group, true);
			return instancesToServerList(instances);
		}
		catch (Exception e) {
			throw new IllegalStateException(
					"Can not get service instances from nacos, serviceId=" + serviceId,
					e);
		}
	}

	private List<NacosServer> instancesToServerList(List<Instance> instances) {
		List<NacosServer> result = new ArrayList<>();
		if (CollectionUtils.isEmpty(instances)) {
			return result;
		}
		for (Instance instance : instances) {
			result.add(new NacosServer(instance));
		}

		return result;
	}

	public String getServiceId() {
		return serviceId;
	}

	@Override
	public void initWithNiwsConfig(IClientConfig iClientConfig) {
		this.serviceId = iClientConfig.getClientName();
	}

}

spirngcloudgateway 自定义实现负载均衡_gateway和ribbon_05


更新服务列表。

调用:

spirngcloudgateway 自定义实现负载均衡_gateway和ribbon_06

@Override
	public List<NacosServer> getUpdatedListOfServers() {
		return getServers();
	}

调用:

private List<NacosServer> getServers() {
		try {
			String group = discoveryProperties.getGroup();
			List<Instance> instances = discoveryProperties.namingServiceInstance()
					.selectInstances(serviceId, group, true);
			return instancesToServerList(instances);
		}
		catch (Exception e) {
			throw new IllegalStateException(
					"Can not get service instances from nacos, serviceId=" + serviceId,
					e);
		}
	}

spirngcloudgateway 自定义实现负载均衡_gateway和ribbon_07


追踪到yaml配置文件中了:

spirngcloudgateway 自定义实现负载均衡_gateway和ribbon_08


至此,nacos自己的实现类和nacos软件建立通讯,对list列表进行更新。

6.总结

spirngcloudgateway 自定义实现负载均衡_nacos和gateway_09


上图对gateway 和ribbon和nacos的关系做了比较明确的示意。