Ribbon是一种客户端的负载均衡,本质上是跑在服务消费者的进程里。服务消费者要访问服务时,通过ribbon向一个服务注册的列表查询,然后以配置的负载均衡策略选择一个后端服务发起请求。
前面ribbon的实现,讲到LB的定义的两个主要方法,分别是后端服务相关的调用:
|
public
void
addServers
(
List
<Server>
newServers
)
;
public
List
<Server>
getServerList
(
boolean
availableOnly
)
;
|
在netflix中这个服务注册列表其实就是eureka服务端集中管理的注册服务列表。获取这个列表应该就是是通过eureka的client来完成的。
也就是ribbon中应该在某个地方集成了eureka client来维护服务列表。这里尝试追踪细这个过程,确认下猜想。
ribbon的实现的继承图上可以看到除了介绍的基本实现LoadBalancer外,还有DynamicServerListLoadBalancer的实现,可以动态的加载后端服务列表。正如名所示,可以动态的加载后端的服务列表。
DynamicServerListLoadBalancer中使用一个ServerListRefreshExecutorThread任务线程定期的更新后端服务列表。
|
class
ServerListRefreshExecutorThread
implements
Runnable
{
public
void
run
(
)
{
updateListOfServers
(
)
;
}
}
public
void
updateListOfServers
(
)
{
servers
=
serverListImpl
.
getUpdatedListOfServers
(
)
;
updateAllServerList
(
servers
)
;
}
|
其实是通过com.netflix.loadbalancer.ServerList.getUpdatedListOfServers() 方法加载后端服务列表。ServerList这个接口正是用来获取加载后端服务列表。(这么一个名词来做动作,有一点点别扭!)可以看到有这么多加载的方式。
看到ConfigurationBasedServerList是从配置中(可以是通过Archaius这样的集中配置)加载的。 而DiscoveryEnabledNIWSServerList这个实现中包含DiscoveryEnabled猜想应该就是服务发现框架里的服务吧。看进去果然是通过eureka client 从eureka server获取服务列表进而在ribbon中可以动态的加载。 从声明
|
public
class
DiscoveryEnabledNIWSServerList
extends
AbstractServerList
<DiscoveryEnabledServer>
{
|
能看到管理的服务不是一般的服务,是DiscoveryEnabledServer的服务。观察List<DiscoveryEnabledServer> com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList.obtainServersViaDiscovery() 的实现可以了解整个过程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private
List
<DiscoveryEnabledServer>
obtainServersViaDiscovery
(
)
{
List
<DiscoveryEnabledServer>
serverList
=
new
ArrayList
<DiscoveryEnabledServer>
(
)
;
DiscoveryClient
discoveryClient
=
DiscoveryManager
.
getInstance
(
)
.
getDiscoveryClient
(
)
;
if
(
vipAddresses
!=
null
)
{
for
(
String
vipAddress
:
vipAddresses
.
split
(“
,”
)
)
{
// if targetRegion is null, it will be interpreted as the same region of client
List
<InstanceInfo>
listOfinstanceInfo
=
discoveryClient
.
getInstancesByVipAddress
(
vipAddress
,
isSecure
,
targetRegion
)
;
for
(
InstanceInfo
ii
:
listOfinstanceInfo
)
{
if
(
ii
.
getStatus
(
)
.
equals
(
InstanceStatus
.
UP
)
)
{
DiscoveryEnabledServer
des
=
new
DiscoveryEnabledServer
(
ii
,
isSecure
,
shouldUseIpAddr
)
;
des
.
setZone
(
DiscoveryClient
.
getZone
(
ii
)
)
;
serverList
.
add
(
des
)
;
}
}
return
serverList
;
}
|
可以看到就是通过一个com.netflix.discovery.EurekaClient作为一个句柄来获取eureka中注册的服务列表。获取活的服务,并根据instanceInfo 构造成ribbon需要的DiscoveryEnabledServer并加到服务列表中。
完。