本篇文章是springcloud微服务实战书和工作实际使用的笔记。
配置详解
自动化配置
由于Ribbon中定义的每一个接口都有多种不同的策略实现,同时这些之间又有一定的依赖关系。
com.netflix.client.config.IClientConfig
:Ribbon
的客户端配置,默认采用com.netflix.client.config.DefaultClientConfigImpl
实现。com.netflix.loadbalancer.IRule
:Ribbon
的负载均衡策略,默认采用com.netflix.loadbalancer.ZoneAvoidanceRule
实现,该策略能够在多区域环境下选出最佳区域的实例进行访问。com.netflix.loadbalancer.IPing
:Ribbon
的实例检查策略,默认采用com.netflix.loadbalancer.NoOpPing
实现,该检查策略是一个特殊的实现,实际上它并不会检查实例是否可用,而是始终返回true,默认认为所有服务实例都是可用的。com.netflix.loadbalancer.ServerList
:服务实例清单的维护机制,默认采用com.netflix.loadbalancer.ConfigurationBasedServerList
实现。com.netflix.loadbalancer.ServerListFilter
:服务实例清单过滤机制,默认采org.springframework.cloud.netflix.ribbon.ZonePreferenceServerListFilter
,该策略能够优先过滤出与请求方处于同区域的服务实例。com.netflix.loadbalancer.ILoadBalancer
:负载均衡器,默认采用com.netflix.loadbalancer.ZoneAwareLoadBalancer
实现,它具备了区域感知的能力。
上面的配置是在项目中没有引入spring Cloud Eureka
,如果引入了Eureka
和Ribbon
依赖时,自动化配置会有一些不同。
通过自动化配置的实现,可以轻松的实现客户端的负载均衡。同时,针对一些个性化需求,我们可以方便的替换上面的这些默认实现,只需要在springboot应用中创建对应的实现实例就能覆盖这些默认的配置实现。
@Configuration
public class MyRibbonConfiguration {
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
这样就会使用P使用了RandomRule实例替代了默认的com.netflix.loadbalancer.ZoneAvoidanceRule
。
也可以使用@RibbonClient
注解实现更细粒度的客户端配置
Camden版本对RabbitClient配置的优化
上面的方式主要是通过独立创建一个Configuration
类来定义IPing
,IRule
等接口的具体实现Bean,然后通过RabbonClient
时指定要使用的具体Configuration
类来覆盖自动化配置的默认实现。在spring Cloud Ribbon Camden
版本中对RibbonClient
定义个性化配置的方法做出进一步优化。可以直接使用
的形式进行配置。
user-service.ribbon.NFLoadBalancerPingClassName=com.netfix.loadbalancer.PingUrl
user-service
是服务名,NFLoadBalancerPingClassName
参数是用来指定IPing
接口实现类。在Camden
版本中,Spring Cloud Ribbon
新增了一个org.springframework.cloud.netflix.ribbon.PropertiesFactory
类动态的为RibbonClient
创建这些接口实现。
在Camden
版本中我们可以通过配置的方式,更加方便的为RibbonClient
指定ILoadBalancer
,IPing
,IRule
,ServerList
,ServerListFilter
的定制化实现。
参数配置
对于Ribbon的参数通常有二种方式:全局配置以及指定客户端配置
- 全局配置的方式很简单
只需要使用ribbon.
格式进行配置即可。其中,=
代表了Ribbon
客户端配置的参数名,
则代表了对应参数的值。比如,我们可以想下面这样配置Ribbon
的超时时间
ribbon.ConnectTimeout=250
全局配置可以作为默认值进行设置,当指定客户端配置了相应的key的值时,将覆盖全局配置的内容
- 指定客户端的配置方式
的格式进行配置.ribbon. = .
表示服务名,比如没有服务治理框架的时候(如Eureka),我们需要指定实例清单,可以指定服务名来做详细的配置,
user-service.ribbon.listOfServers=localhost:8080,localhost:8081,localhost:8082
对于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
结合使用的时候,不需要再去指定类似的user-service.ribbon.listOfServers
的参数来指定具体的服务实例清单,因为Eureka
将会为我们维护所有服务的实例清单,而对于Ribbon
的参数配置,我们依然可以采用之前的两种配置方式来实现。
此外,由于spring Cloud Ribbon
默认实现了区域亲和策略,所以,可以通过Eureka
实例的元数据配置来实现区域化的实例配置方案。比如可以将不同机房的实例配置成不同的区域值,作为跨区域的容器机制实现。而实现也非常简单,只需要服务实例的元数据中增加zone参数来指定自己所在的区域,比如:
eureka.instance.metadataMap.zone=shanghai
在Spring Cloud Ribbon与Spring Cloud Eureka
结合的工程中,我们可以通过参数禁用Eureka
对Ribbon
服务实例的维护实现。这时又需要自己去维护服务实例列表了。
ribbon.eureka.enabled=false.
重试机制
由于Spring Cloud Eureka
实现的服务治理机制强调了cap
原理的ap
机制(即可用性和可靠性),与zookeeper
这类强调cp
(一致性,可靠性)服务质量框架最大的区别就是,Eureka
为了实现更高的服务可用性,牺牲了一定的一致性,在极端情况下宁愿接受故障实例也不要丢弃"健康"实例。
比如说,当服务注册中心的网络发生故障断开时候,由于所有的服务实例无法维护续约心跳,在强调ap的服务治理中将会把所有服务实例剔除掉,而Eureka
则会因为超过85%的实例丢失心跳而触发保护机制,注册中心将会保留此时的所有节点,以实现服务间依然可以进行互相调用的场景,即使其中有部分故障节点,但这样做可以继续保障大多数服务的正常消费。
在Camden
版本,整合了spring retry
来增强RestTemplate
的重试能力,对于我们开发者来说,只需要简单配置,即可完成重试策略。
spring.cloud.loadbalancer.retry.enabled=true
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
user-service.ribbon.ConnectTimeout=250
user-service.ribbon.ReadTimeout=1000
user-service.ribbon.OkToRetryOnAllOperations=true
user-service.ribbon.MaxAutoRetriesNextServer=2
user-service.ribbon.maxAutoRetries=1
spring.cloud.loadbalancer.retry.enabled
:该参数用来开启重试机制,它默认是关闭的。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
:断路器的超时时间需要大于Ribbon的超时时间,不然不会触发重试。
user-service.ribbon.ConnectTimeout
:请求连接超时时间。
user-service.ribbon.ReadTimeout
:请求处理的超时时间
user-service.ribbon.OkToRetryOnAllOperations
:对所有操作请求都进行重试。
user-service.ribbon.MaxAutoRetriesNextServer
:切换实例的重试次数。
user-service.ribbon.maxAutoRetries
:对当前实例的重试次数。
根据以上配置,当访问到故障请求的时候,它会再尝试访问一次当前实例(次数由maxAutoRetries
配置),如果不行,就换一个实例进行访问,如果还是不行,再换一个实例访问(更换次数由MaxAutoRetriesNextServer
配置),如果依然不行,返回失败。