序
本文主要研究一下EurekaRibbonClientConfiguration
EurekaRibbonClientConfiguration
spring-cloud-netflix-eureka-client-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/eureka/EurekaRibbonClientConfiguration.java
/**
* Preprocessor that configures defaults for eureka-discovered ribbon clients. Such as:
* @zone
, NIWSServerListClassName, DeploymentContextBasedVipAddresses,
* NFLoadBalancerRuleClassName, NIWSServerListFilterClassName and more
*
* @author Spencer Gibb
* @author Dave Syer
* @author Ryan Baxter
*/
@Configuration
public class EurekaRibbonClientConfiguration {
private static final Log log = LogFactory.getLog(EurekaRibbonClientConfiguration.class);
@Value("${ribbon.eureka.approximateZoneFromHostname:false}")
private boolean approximateZoneFromHostname = false;
@RibbonClientName
private String serviceId = "client";
@Autowired(required = false)
private EurekaClientConfig clientConfig;
@Autowired(required = false)
private EurekaInstanceConfig eurekaConfig;
@Autowired
private PropertiesFactory propertiesFactory;
public EurekaRibbonClientConfiguration() {
}
public EurekaRibbonClientConfiguration(EurekaClientConfig clientConfig,
String serviceId, EurekaInstanceConfig eurekaConfig,
boolean approximateZoneFromHostname) {
this.clientConfig = clientConfig;
this.serviceId = serviceId;
this.eurekaConfig = eurekaConfig;
this.approximateZoneFromHostname = approximateZoneFromHostname;
}
@Bean
@ConditionalOnMissingBean
public IPing ribbonPing(IClientConfig config) {
if (this.propertiesFactory.isSet(IPing.class, serviceId)) {
return this.propertiesFactory.get(IPing.class, config, serviceId);
}
NIWSDiscoveryPing ping = new NIWSDiscoveryPing();
ping.initWithNiwsConfig(config);
return ping;
}
@Bean
@ConditionalOnMissingBean
public ServerList> ribbonServerList(IClientConfig config, Provider eurekaClientProvider) {
if (this.propertiesFactory.isSet(ServerList.class, serviceId)) {
return this.propertiesFactory.get(ServerList.class, config, serviceId);
}
DiscoveryEnabledNIWSServerList discoveryServerList = new DiscoveryEnabledNIWSServerList(
config, eurekaClientProvider);
DomainExtractingServerList serverList = new DomainExtractingServerList(
discoveryServerList, config, this.approximateZoneFromHostname);
return serverList;
}
@Bean
public ServerIntrospector serverIntrospector() {
return new EurekaServerIntrospector();
}
@PostConstruct
public void preprocess() {
String zone = ConfigurationManager.getDeploymentContext()
.getValue(ContextKey.zone);
if (this.clientConfig != null && StringUtils.isEmpty(zone)) {
if (this.approximateZoneFromHostname && this.eurekaConfig != null) {
String approxZone = ZoneUtils
.extractApproximateZone(this.eurekaConfig.getHostName(false));
log.debug("Setting Zone To " + approxZone);
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone,
approxZone);
}
else {
String availabilityZone = this.eurekaConfig == null ? null
: this.eurekaConfig.getMetadataMap().get("zone");
if (availabilityZone == null) {
String[] zones = this.clientConfig
.getAvailabilityZones(this.clientConfig.getRegion());
// Pick the first one from the regions we want to connect to
availabilityZone = zones != null && zones.length > 0 ? zones[0]
: null;
}
if (availabilityZone != null) {
// You can set this with archaius.deployment.* (maybe requires
// custom deployment context)?
ConfigurationManager.getDeploymentContext().setValue(ContextKey.zone,
availabilityZone);
}
}
}
RibbonUtils.initializeRibbonDefaults(serviceId);
}
}
- 创建了NIWSDiscoveryPing、DomainExtractingServerList、EurekaServerIntrospector
- 初始化之后调用RibbonUtils.initializeRibbonDefaults(serviceId)
NIWSDiscoveryPing
ribbon-eureka-2.2.5-sources.jar!/com/netflix/niws/loadbalancer/NIWSDiscoveryPing.java
/**
* "Ping" Discovery Client
* i.e. we dont do a real "ping". We just assume that the server is up if Discovery Client says so
* @author stonse
*
*/
public class NIWSDiscoveryPing extends AbstractLoadBalancerPing {
BaseLoadBalancer lb = null;
public NIWSDiscoveryPing() {
}
public BaseLoadBalancer getLb() {
return lb;
}
/**
* Non IPing interface method - only set this if you care about the "newServers Feature"
* @param lb
*/
public void setLb(BaseLoadBalancer lb) {
this.lb = lb;
}
public boolean isAlive(Server server) {
boolean isAlive = true;
if (server!=null && server instanceof DiscoveryEnabledServer){
DiscoveryEnabledServer dServer = (DiscoveryEnabledServer)server;
InstanceInfo instanceInfo = dServer.getInstanceInfo();
if (instanceInfo!=null){
InstanceStatus status = instanceInfo.getStatus();
if (status!=null){
isAlive = status.equals(InstanceStatus.UP);
}
}
}
return isAlive;
}
@Override
public void initWithNiwsConfig(
IClientConfig clientConfig) {
}
}
- NIWSDiscoveryPing通过获取实例的eureka状态来判断是否健康
DomainExtractingServerList
spring-cloud-netflix-eureka-client-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/eureka/DomainExtractingServerList.java
public class DomainExtractingServerList implements ServerList {
private ServerList list;
private final RibbonProperties ribbon;
private boolean approximateZoneFromHostname;
public DomainExtractingServerList(ServerList list,
IClientConfig clientConfig, boolean approximateZoneFromHostname) {
this.list = list;
this.ribbon = RibbonProperties.from(clientConfig);
this.approximateZoneFromHostname = approximateZoneFromHostname;
}
@Override
public List getInitialListOfServers() {
List servers = setZones(this.list
.getInitialListOfServers());
return servers;
}
@Override
public List getUpdatedListOfServers() {
List servers = setZones(this.list
.getUpdatedListOfServers());
return servers;
}
private List setZones(List servers) {
List result = new ArrayList<>();
boolean isSecure = this.ribbon.isSecure(true);
boolean shouldUseIpAddr = this.ribbon.isUseIPAddrForServer();
for (DiscoveryEnabledServer server : servers) {
result.add(new DomainExtractingServer(server, isSecure, shouldUseIpAddr,
this.approximateZoneFromHostname));
}
return result;
}
}
class DomainExtractingServer extends DiscoveryEnabledServer {
private String id;
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
this.id = id;
}
public DomainExtractingServer(DiscoveryEnabledServer server, boolean useSecurePort,
boolean useIpAddr, boolean approximateZoneFromHostname) {
// host and port are set in super()
super(server.getInstanceInfo(), useSecurePort, useIpAddr);
if (server.getInstanceInfo().getMetadata().containsKey("zone")) {
setZone(server.getInstanceInfo().getMetadata().get("zone"));
}
else if (approximateZoneFromHostname) {
setZone(ZoneUtils.extractApproximateZone(server.getHost()));
}
else {
setZone(server.getZone());
}
setId(extractId(server));
setAlive(server.isAlive());
setReadyToServe(server.isReadyToServe());
}
private String extractId(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer enabled = (DiscoveryEnabledServer) server;
InstanceInfo instance = enabled.getInstanceInfo();
if (instance.getMetadata().containsKey("instanceId")) {
return instance.getHostName()+":"+instance.getMetadata().get("instanceId");
}
}
return super.getId();
}
}
- getInitialListOfServers及getUpdatedListOfServers都调用了setZones从eureka的metadata读取zone
EurekaServerIntrospector
spring-cloud-netflix-eureka-client-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/eureka/EurekaServerIntrospector.java
public class EurekaServerIntrospector extends DefaultServerIntrospector {
@Override
public boolean isSecure(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer discoveryServer = (DiscoveryEnabledServer) server;
return discoveryServer.getInstanceInfo().isPortEnabled(InstanceInfo.PortType.SECURE);
}
return super.isSecure(server);
}
@Override
public Map getMetadata(Server server) {
if (server instanceof DiscoveryEnabledServer) {
DiscoveryEnabledServer discoveryServer = (DiscoveryEnabledServer) server;
return discoveryServer.getInstanceInfo().getMetadata();
}
return super.getMetadata(server);
}
}
- 这里从eureka的instanceInfo获取metadata
小结
EurekaRibbonClientConfiguration主要是给ribbon配置eureka相关的特性,主要是NIWSDiscoveryPing、DomainExtractingServerList、EurekaServerIntrospector这几个:
- 其中NIWSDiscoveryPing通过eureka中instance的状态来判断是否ping的通
- DomainExtractingServerList提供getInitialListOfServers以及getUpdatedListOfServers方法
- EurekaServerIntrospector主要是通过instanceInfo获取metadata
doc
- 16.5 Using Ribbon with Eureka