Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension points for subclassing and some perf optimizations #371

Merged
merged 7 commits into from
Apr 27, 2018

Conversation

kerumai
Copy link
Contributor

@kerumai kerumai commented Mar 30, 2018

I've been experimenting with some different load-balancing mechanisms, and had to initially copy-paste some of the ribbon code to allow overriding and extending. Now thats complete, I'd like to get these changes pushed down into ribbon so that I can remove the duplication.

As part of the experimenting, load-testing and profiling, a couple of hotspots came up around the use of DynamicIntProperty and java.util.Random, so I'm submitting those small changes too.

Extension points:

  • Allow the LoadBalancerStats implementation to be chosen using a new ClientConfigKey in BaseLoadBalancer.
  • Change some methods in LoadBalancerStats from private to protected so they can be overridden in subclasses.
  • Allow subclasses of DiscoveryEnabledNIWSServerList to override the type of DiscoveryEnabledServer instances created by adding a protected createServer() method.

Optimizations:

  • Change RandomRule to use a ThreadLocalRandom instead of Random, as a perf optimization.
  • Change ServerStats and LoadBalancerStats to use CachedDynamicIntProperty instead of DynamicIntProperty as a perf optimization.

@@ -198,6 +198,12 @@ public void initWithNiwsConfig(IClientConfig clientConfig) {
return serverList;
}

protected DiscoveryEnabledServer createServer(final InstanceInfo instanceInfo, boolean useSecurePort, boolean useIpAddr) {
DiscoveryEnabledServer server = new DiscoveryEnabledServer(instanceInfo, useSecurePort, useIpAddr);
server.setZone(DiscoveryClient.getZone(instanceInfo));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should improve the API, but for now, can you change from the deprecated DiscoveryClient.getZone to the following?
First, get hold of EurekaClient (there is already an instance), then

EurekaClientConfig clientConfig = eurekaClient.getEurekaClientConfig();
String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion());
String instanceZone = InstanceInfo.getZone(availZones, myInstanceInfo);
server.setZone(instanceZone);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely. Although it looks like getEurekaClientConfig() only exists on DiscoveryClient, not EurekaClient - so is it ok for me to cast to DiscoveryClient if it is an instanceof?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, looks like ribbon still depends on a really ancient version of eureka, that method was added to the interface from 1.6.0 onwards. Do you mind also updating the eureka dependency to 1.7.2? (1.7.2 is the current latest Java7 compatible version). Thanks.

}

void initWithConfig(IClientConfig clientConfig, IRule rule, IPing ping) {
void initWithConfig(IClientConfig clientConfig, IRule rule, IPing ping, LoadBalancerStats stats) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this is package private so 'should' be safe to do, but just in case since Ribbon is such an old library, can you do an additional overload method to be compatible? Thanks.

void initWithConfig(IClientConfig clientConfig, IRule rule, IPing ping) {
    initWithConfig(IClientConfig clientConfig, IRule rule, IPing ping, createLoadBalancerStatsFromConfig(config));
}

return (LoadBalancerStats) ClientFactory.instantiateInstanceWithClientConfig(
loadBalancerStatsClassName, clientConfig);
} catch (Exception e) {
throw new RuntimeException("Error initializing LoadBalancerStats", e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of throwing a RuntimeException, it may be more compatible if we fallback to emitting a WARN log and create the stats class with the existing new LoadBalancerStats(clientName).

Also:
* As had to change the mocking of DiscoveryClient and InstanceInfo in some tests, refactored out that mock code into 2 static methods on LoadBalancerTestUtils.
* Upgraded eureka-client dependency version from 1.4.6 to 1.7.2 to get the EurekaClient.getEurekaClientConfig() interface.
@kerumai
Copy link
Contributor Author

kerumai commented Apr 27, 2018

@qiangdavidliu How does that look?

@qiangdavidliu
Copy link
Contributor

Looks great. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants