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进行任何操作。整理架构建立了。
3. 此类是对服务列表进行更新,比如服务的上线,下线等。
DynamicServerListLoadBalancer.java 类是ribbon的自己实现的。
负载均衡在ribbon中的自我实现策略,默认为轮训,我们可以按自己的需求自己实现即可。
4. ServerList.java
此类是ribbon持有服务列表的接口类,其他任何三方的服务注册与发现中心可以实现它,比如此处我们使用的是nacos所谓服务发现与注册中心,则alibaba就实现了这个接口NacosServerList.java 就是对这个接口的实现。
因此,项目需要引入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();
}
}
更新服务列表。
调用:
@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);
}
}
追踪到yaml配置文件中了:
至此,nacos自己的实现类和nacos软件建立通讯,对list列表进行更新。
6.总结
上图对gateway 和ribbon和nacos的关系做了比较明确的示意。