返回介绍

配置详解

发布于 2024-08-18 11:12:34 字数 7148 浏览 0 评论 0 收藏 0

通过上一节对Spring Cloud Ribbon的源码分析,相信读者对于Ribbon的几个重要接口都已经有所了解。下面,我们将详细介绍Ribbon在使用时的各种配置方式。

自动化配置

由于Ribbon中定义的每一个接口都有多种不同的策略实现,同时这些接口之间又有一定的依赖关系,这使得第一次使用Ribbon的开发者很难上手,不知道如何选择具体的实现策略以及如何组织它们的关系。Spring Cloud Ribbon中的自动化配置恰恰能够解决这样的痛点,在引入Spring Cloud Ribbon的依赖之后,就能够自动化构建下面这些接口的实现。

- IClientConfig:Ribbon 的客户端配置,默认采用 com.netflix.client.config.DefaultClientConfigImpl实现。

- IRule:Ribbon 的负载均衡策略,默认采用 com.netflix.loadbalancer.ZoneAvoidanceRule实现,该策略能够在多区域环境下选出最佳区域的实例进行访问。

- IPing:Ribbon的实例检查策略,默认采用com.netflix.loadbalancer.NoOpPing实现,该检查策略是一个特殊的实现,实际上它并不会检查实例是否可用,而是始终返回true,默认认为所有服务实例都是可用的。

- ServerList<Server>:服务实例清单的维护机制,默认采用 com.netflix.loadbalancer.ConfigurationBasedServerList实现。

- ServerListFilter<Server>:服务实例清单过滤机制,默认采用 org.springframework.cloud.netflix.ribbon.ZonePreferenceServerLis tFilter实现,该策略能够优先过滤出与请求调用方处于同区域的服务实例。

- ILoadBalancer:负载均衡器,默认采用 com.netflix.loadbalancer.ZoneAwareLoadBalancer实现,它具备了区域感知的能力。

上面这些自动化配置内容仅在没有引入Spring Cloud Eureka等服务治理框架时如此,在同时引入Eureka和Ribbon依赖时,自动化配置会有一些不同,后续我们会做详细的介绍。

通过自动化配置的实现,我们可以轻松地实现客户端负载均衡。同时,针对一些个性化需求,我们也可以方便地替换上面的这些默认实现。只需在Spring Boot应用中创建对应的实现实例就能覆盖这些默认的配置实现。比如下面的配置内容,由于创建了 PingUrl实例,所以默认的NoOpPing就不会被创建。

@Configuration

public class MyRibbonConfiguration {

@Bean

public IPing ribbonPing(IClientConfig config){

return new PingUrl();

}

}

另外,也可以通过使用@RibbonClient注解来实现更细粒度的客户端配置,比如下面的代码实现了为hello-service服务使用HelloServiceConfiguration中的配置。

@Configuration

@RibbonClient(name="hello-service",configuration=HelloServiceConfiguration.class)

public class RibbonConfiguration {

}

Camden版本对RibbonClient配置的优化

上面我们介绍了在Brixton版本中对RibbonClient的IPing、IRule等接口实现进行个性化定制的方法,主要通过独立创建一个Configuration类来定义IPing、IRule等接口的具体实现Bean,然后在创建RibbonClient时指定要使用的具体Configuration类来覆盖自动化配置的默认实现。虽然这种方式已经能够实现个性化的定义,但是当有大量这类配置的时候,对于各个 RibbonClient 的指定配置信息都将分散在这些配置类的注解定义中,这使得管理和修改都变得非常不方便。所以,在Camden版本中,Spring Cloud Ribbon对 RibbonClient 定义个性化配置的方法做了进一步优化。可以直接通过<clientName>.ribbon.<key>=<value>的形式进行配置。比如我们要实现与上面例子一样的配置(将hello-service服务客户端的IPing接口实现替换为PingUrl),只需在application.properties配置中增加下面的内容即可:

hello-service.ribbon.NFLoadBalancerPingClassName=com.netflix.loadbalancer.PingUrl

其中 hello-service 为服务名,NFLoadBalancerPingClassName 参数用来指定具体的 IPing 接口实现类。在 Camden 版本中,Spring Cloud Ribbon 新增了一个org.springframework.cloud.netflix.ribbon.PropertiesFactory类来动态地为RibbonClient创建这些接口实现。

public class PropertiesFactory {

@Autowired

private Environment environment;

private Map<Class,String> classToProperty=new HashMap<>();

public PropertiesFactory(){

classToProperty.put(ILoadBalancer.class,"NFLoadBalancerClassName");

classToProperty.put(IPing.class,"NFLoadBalancerPingClassName");

classToProperty.put(IRule.class,"NFLoadBalancerRuleClassName");

classToProperty.put(ServerList.class,"NIWSServerListClassName");

classToProperty.put(ServerListFilter.class,"NIWSServerListFilterClassName");

}

public boolean isSet(Class clazz,String name){

return StringUtils.hasText(getClassName(clazz,name));

}

public String getClassName(Class clazz,String name){

if(this.classToProperty.containsKey(clazz)){

String classNameProperty=this.classToProperty.get(clazz);

String className=environment.getProperty(name+"."+NAMESPACE+"."+classNameProperty);

return className;

}

return null;

}

@SuppressWarnings("unchecked")

public <C> C get(Class<C> clazz,IClientConfig config,String name){

String className=getClassName(clazz,name);

if(StringUtils.hasText(className)){

try {

Class<? > toInstantiate=Class.forName(className);

return(C)instantiateWithConfig(toInstantiate,config);

} catch(ClassNotFoundException e){

throw new IllegalArgumentException("Unknown class to load"+className+" for class "+clazz+" named "+name);

}

}

return null;

}

}

从上述源码定义中可以看到,除了 NFLoadBalancerPingClassName 参数之外,还提供了其他几个接口的动态配置实现,具体如下所述。

- NFLoadBalancerClassName:配置ILoadBalancer接口的实现。

- NFLoadBalancerPingClassName:配置IPing接口的实现。

- NFLoadBalancerRuleClassName:配置IRule接口的实现。

- NIWSServerListClassName:配置ServerList接口的实现。

- NIWSServerListFilterClassName:配置ServerListFilter接口的实现。

所以,在Camden版本中我们可以通过配置的方式,更加方便地为RibbonClient指定ILoadBalancer、IPing、IRule、ServerList和ServerListFilter的定制化实现。

参数配置

对于Ribbon的参数配置通常有两种方式:全局配置以及指定客户端配置。

- 全局配置的方式很简单,只需使用ribbon.<key>=<value>格式进行配置即可。

其中,<key>代表了 Ribbon 客户端配置的参数名,<value>则代表了对应参数的值。比如,我们可以像下面这样全局配置Ribbon创建连接的超时时间:

ribbon.ConnectTimeout=250

全局配置可以作为默认值进行设置,当指定客户端配置了相应key的值时,将覆盖全局配置的内容。

- 指定客户端的配置方式采用<client>.ribbon.<key>=<value>的格式进行配置。其中,<key>和<value>的含义同全局配置相同,而<client>代表了客户端的名称,如上文中我们在@RibbonClient中指定的名称,也可以将它理解为是一个服务名。为了方便理解这种配置方式,我们举一个具体的例子:假设,有一个服务消费者通过RestTemplate来访问hello-service服务的/hello接口,这时我们会这样调用restTemplate.getForEntity("http://helloservice/hello",String.class).getBody();。如果没有服务治理框架的帮助,我们需要为该客户端指定具体的实例清单,可以指定服务名来做详细的配置,具体如下:

hello-service.ribbon.listOfServers=localhost:8001,localhost:8002,localhost:8003

对于Ribbon参数的key以及value类型的定义,可以通过查看com.netflix.client.config.CommonClientConfigKey类获得更为详细的配置内容,在本书中不进行详细介绍。

与Eureka结合

当在Spring Cloud的应用中同时引入Spring Cloud Ribbon和Spring Cloud Eureka依赖时,会触发Eureka中实现的对Ribbon的自动化配置。这时ServerList的维护机制实现将被com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList 的实例所覆盖,该实现会将服务清单列表交给Eureka的服务治理机制来进行维护;IPing的实现将被 com.netflix.niws.loadbalancer.NIWSDiscoveryPing 的实例所覆盖,该实现也将实例检查的任务交给了服务治理框架来进行维护。默认情况下,用于获取实例请求的ServerList接口实现将采用Spring Cloud Eureka中封装的org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList,其目的是为了让实例维护策略更加通用,所以将使用物理元数据来进行负载均衡,而不是使用原生的AWS AMI元数据。

在与Spring Cloud Eureka结合使用的时候,我们的配置将会变得更加简单。不再需要通过类似 hello-service.ribbon.listOfServers 的参数来指定具体的服务实例清单,因为Eureka将会为我们维护所有服务的实例清单。而对于Ribbon的参数配置,我们依然可以采用之前的两种配置方式来实现,而指定客户端的配置方式可以直接使用Eureka中的服务名作为<client>来完成针对各个微服务的个性化配置。

此外,由于Spring Cloud Ribbon默认实现了区域亲和策略,所以,我们可以通过Eureka实例的元数据配置来实现区域化的实例配置方案。比如,可以将处于不同机房的实例配置成不同的区域值,以作为跨区域的容错机制实现。而实现的方式非常简单,只需在服务实例的元数据中增加zone参数来指定自己所在的区域,比如:

eureka.instance.metadataMap.zone=shanghai

在Spring Cloud Ribbon与Spring Cloud Eureka结合的工程中,我们也可以通过参数配置的方式来禁用Eureka对Ribbon服务实例的维护实现。只需在配置文件中加入如下参数,这时我们对于服务实例的维护就又将回归到使用<client>.ribbon.listOfServers 参数配置的方式来实现了。

ribbon.eureka.enabled=false

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文