序
本文主要研究一下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 */@Configurationpublic 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, ProvidereurekaClientProvider) { 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 MapgetMetadata(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