参考资料
https://blog.csdn.net/luanlouis/article/details/83060310
https://www.iocoder.cn/Spring-Cloud-Netflix/Ribbon/
https://www.cnblogs.com/trust-freedom/p/11216280.html
https://blog.51cto.com/u_8958931/2817488
https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-ribbon.html
概念
容器
- 创建客户端、负载均衡器和客户端配置实例的工厂。 它为每个客户端名称创建一个 Spring ApplicationContext,并从那里提取它需要的 bean。
org.springframework.cloud.netflix.ribbon.SpringClientFactory ```java public class SpringClientFactory extends NamedContextFactory
{ static final String NAMESPACE = “ribbon”;
public SpringClientFactory() {
super(RibbonClientConfiguration.class, NAMESPACE, "ribbon.client.name");
}
// 获取当前客户端关联的 Reset 客户端。 public
> C getClient(String name, Class clientClass) { return getInstance(name, clientClass);
}
// 获取当前客户端关联的 负载均衡器 public ILoadBalancer getLoadBalancer(String name) {
return getInstance(name, ILoadBalancer.class);
}
// 获取当前客户端关联的 客户端配置 public IClientConfig getClientConfig(String name) {
return getInstance(name, IClientConfig.class);
}
// 获取当前客户端关联的 负载均衡器上下文 public RibbonLoadBalancerContext getLoadBalancerContext(String serviceId) {
return getInstance(serviceId, RibbonLoadBalancerContext.class);
}
@Override protected AnnotationConfigApplicationContext getContext(String name) {
return super.getContext(name);
}
}
<a name="W2vmX"></a>
## 组件
![Ribbon-DefaultClientConfigImpl.png](https://cdn.nlark.com/yuque/0/2022/png/106112/1641455710573-504368d2-685f-4d8b-8fee-0449da0e9463.png#clientId=u26bde30d-d62e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=251&id=uac7b5047&margin=%5Bobject%20Object%5D&name=Ribbon-DefaultClientConfigImpl.png&originHeight=251&originWidth=487&originalType=binary&ratio=1&rotation=0&showTitle=false&size=7585&status=done&style=none&taskId=ub64cb3cf-a2f6-49d9-ae6b-da3e0c7986f&title=&width=487)<br />初始化 Ribbon 客户端和负载均衡器的配置的方法,配置Ribbon的相关设置
```java
@Import({ HttpClientConfiguration.class, OkHttpRibbonConfiguration.class,
RestClientRibbonConfiguration.class, HttpClientRibbonConfiguration.class })
public class RibbonClientConfiguration {
/**
* Ribbon client default connect timeout.
*/
public static final int DEFAULT_CONNECT_TIMEOUT = 1000;
/**
* Ribbon client default read timeout.
*/
public static final int DEFAULT_READ_TIMEOUT = 1000;
/**
* Ribbon client default Gzip Payload flag.
*/
public static final boolean DEFAULT_GZIP_PAYLOAD = true;
@RibbonClientName
private String name = "client";
// TODO: maybe re-instate autowired load balancers: identified by name they could be
// associated with ribbon clients
@Autowired
private PropertiesFactory propertiesFactory;
@Bean
@ConditionalOnMissingBean
public IClientConfig ribbonClientConfig() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.loadProperties(this.name);
config.set(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT);
config.set(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT);
config.set(CommonClientConfigKey.GZipPayload, DEFAULT_GZIP_PAYLOAD);
return config;
}
@Bean
@ConditionalOnMissingBean
public IRule ribbonRule(IClientConfig config) {
if (this.propertiesFactory.isSet(IRule.class, name)) {
return this.propertiesFactory.get(IRule.class, config, name);
}
ZoneAvoidanceRule rule = new ZoneAvoidanceRule();
rule.initWithNiwsConfig(config);
return rule;
}
@Bean
@ConditionalOnMissingBean
public IPing ribbonPing(IClientConfig config) {
if (this.propertiesFactory.isSet(IPing.class, name)) {
return this.propertiesFactory.get(IPing.class, config, name);
}
return new DummyPing();
}
@Bean
@ConditionalOnMissingBean
@SuppressWarnings("unchecked")
public ServerList<Server> ribbonServerList(IClientConfig config) {
if (this.propertiesFactory.isSet(ServerList.class, name)) {
return this.propertiesFactory.get(ServerList.class, config, name);
}
ConfigurationBasedServerList serverList = new ConfigurationBasedServerList();
serverList.initWithNiwsConfig(config);
return serverList;
}
@Bean
@ConditionalOnMissingBean
public ServerListUpdater ribbonServerListUpdater(IClientConfig config) {
return new PollingServerListUpdater(config);
}
@Bean
@ConditionalOnMissingBean
public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
ServerList<Server> serverList, ServerListFilter<Server> serverListFilter,
IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
if (this.propertiesFactory.isSet(ILoadBalancer.class, name)) {
return this.propertiesFactory.get(ILoadBalancer.class, config, name);
}
return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList,
serverListFilter, serverListUpdater);
}
@Bean
@ConditionalOnMissingBean
@SuppressWarnings("unchecked")
public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config) {
if (this.propertiesFactory.isSet(ServerListFilter.class, name)) {
return this.propertiesFactory.get(ServerListFilter.class, config, name);
}
ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
filter.initWithNiwsConfig(config);
return filter;
}
@Bean
@ConditionalOnMissingBean
public RibbonLoadBalancerContext ribbonLoadBalancerContext(ILoadBalancer loadBalancer,
IClientConfig config, RetryHandler retryHandler) {
return new RibbonLoadBalancerContext(loadBalancer, config, retryHandler);
}
@Bean
@ConditionalOnMissingBean
public RetryHandler retryHandler(IClientConfig config) {
return new DefaultLoadBalancerRetryHandler(config);
}
@Bean
@ConditionalOnMissingBean
public ServerIntrospector serverIntrospector() {
return new DefaultServerIntrospector();
}
@PostConstruct
public void preprocess() {
setRibbonProperty(name, DeploymentContextBasedVipAddresses.key(), name);
}
static class OverrideRestClient extends RestClient {
private IClientConfig config;
private ServerIntrospector serverIntrospector;
protected OverrideRestClient(IClientConfig config,
ServerIntrospector serverIntrospector) {
super();
this.config = config;
this.serverIntrospector = serverIntrospector;
initWithNiwsConfig(this.config);
}
@Override
public URI reconstructURIWithServer(Server server, URI original) {
URI uri = updateToSecureConnectionIfNeeded(original, this.config,
this.serverIntrospector, server);
return super.reconstructURIWithServer(server, uri);
}
@Override
protected Client apacheHttpClientSpecificInitialization() {
ApacheHttpClient4 apache = (ApacheHttpClient4) super.apacheHttpClientSpecificInitialization();
apache.getClientHandler().getHttpClient().getParams().setParameter(
ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES);
return apache;
}
}
}
主动 ping 服务实例的方法,判断其是否存活
负载均衡规则接口,定义了从服务中选择一个实例的方法
获得服务实例列表的方法
静态和动态的。如果是动态的,会有后台定时任务定时重新获取最新的服务实例列表
- com.netflix.loadbalancer.ConfigurationBasedServerList 从配置文件获取
- org.springframework.cloud.netflix.ribbon.StaticServerList 静态的实例列表
- com.alibaba.cloud.nacos.ribbon.NacosServerList Nacos实现客户端动态刷新的服务列表
过滤不符合条件的服务实例的方法
启动一个定时任务,定时重新获取最新的服务实例列表