频道
bg

ribbon with eureka

coding五月 23, 20171mins
Spring Cloud

Spring Cloud中使用ribbon(配合eureka)来访问service时,只需要使用http://service-name/xxx这样格式的URL即可访问对应的service的注册的服务,这具体是如何实现的呢?

Netflix ribbonH2

Netflix OSS中ribbon配合eureka来自动配置serverlist时,是需要做如下配置的

bash

myClient.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
# the server must register itself with Eureka server with VipAddress "myservice"
myClient.ribbon.DeploymentContextBasedVipAddresses=myservice

DeploymentContextBasedVipAddresses 需要配置为需要访问的service的VipAddress的值。

Spring CloudH2

Spring Cloud中自动配置ribbon时会注册LoadBalancerInterceptorLoadBalancerInterceptor会在拦截请求时,获取请求的Host来作为serviceName来获取ILoadBalancer的实例

bash

LoadBalancerInterceptor
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
return (ClientHttpResponse)this.loadBalancer.execute(serviceName, new LoadBalancerRequest<ClientHttpResponse>() {
public ClientHttpResponse apply(ServiceInstance instance) throws Exception {
HttpRequest serviceRequest = LoadBalancerInterceptor.this.new ServiceRequestWrapper(request, instance);
return execution.execute(serviceRequest, body);
}
});
}
RibbonLoadBalancerClient
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
...
}

而获取ILoadBalancer实例会单独的ApplicationContext中进行,这个ApplicationContext则会注册EurekaRibbonClientConfiguration类配置ribbonServerList等参数。

EurekaRibbonClientConfiguration返回ribbonServerList的逻辑是优先读取配置文件中xxx.ribbon.listOfServers设置的serverList。如果没有设置则返回DiscoveryEnabledNIWSServerList的包装类DomainExtractingServerList

bash

EurekaRibbonClientConfiguration
@Bean
@ConditionalOnMissingBean
public ServerList<?> ribbonServerList(IClientConfig config, Provider<EurekaClient> 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;
}

DiscoveryEnabledNIWSServerList则需要配合DeploymentContextBasedVipAddresses参数的 ,而EurekaRibbonClientConfiguration的@PostConstruct方法恰巧最终还是会配置DeploymentContextBasedVipAddresses参数

bash

EurekaRibbonClientConfiguration
@PostConstruct
public void preprocess() {
setRibbonProperty(this.serviceId, DeploymentContextBasedVipAddresses.key(),
this.serviceId);
setRibbonProperty(this.serviceId, EnableZoneAffinity.key(), "true");
}

评论


新的评论

匹配您的Gravatar头像

Joen Yu

@2022 JoenYu, all rights reserved. Made with love.