2021-07-13

Ribbon负载均衡分析

Ribbon使用

ribbon在使用上非常简单,仅仅只需要在配置类上加入配置即可

 @Bean @LoadBalanced public RestTemplate restTemplate(){  return new RestTemplate(); }

调用时,直接使用在eureka中注册的服务名进行调用,就可以由ribbon来进行负载均衡了

 @GetMapping("/checkAndBegin/{userId}") public Integer findResumeOpenStateEureka(@PathVariable Long userId) {//  List<ServiceInstance> list = discoveryClient.getInstances("lagou-service-resume");//  ServiceInstance serviceInstance = list.get(0);//  String host = serviceInstance.getHost();//  int port = serviceInstance.getPort();  String url = "http://zhao-service-resume/resume/openstate/"+userId;  System.out.println("从eureka中获取了请求地址"+url);  Integer forObject =    restTemplate.getForObject(url, Integer.class);  return forObject; }

根据要求,zhao-service-resume项目开启多个,并打印请求信息,即可发现负载均衡已经实现
另外目前Ribbon的内置负载均衡策略
file
目前默认使用的是随机负载均衡RandomRule,默认全局生效,但是可以针对不同的调用服务设置不同的负载均衡策略

zhao-service-resume: ribbon: NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RandomRule #负载策略调整

同时,可以自定负载均衡策略并配置

Ribbon源码分析

一般而言,自动装配类就是加载配置的入口。

@Configuration@Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class)@RibbonClients@AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")@AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class})@EnableConfigurationProperties({RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class})public class RibbonAutoConfiguration {}

通过上述配置,我们可以先看看LoadBalancerAutoConfiguration的具体内容

	@LoadBalanced	@Autowired(required = false)	private List<RestTemplate> restTemplates = Collections.emptyList();

此处将自动注入添加了@LoadBalanced注解的RestTemplate对象
同时还注入了一个RestTemplate的定制器RestTemplateCustomizer

	@Bean	public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(			final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {		return () -> restTemplateCustomizers.ifAvailable(customizers -> {   for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {    for (RestTemplateCustomizer customizer : customizers) {     customizer.customize(restTemplate);    }   }  });	}

继续进入RestTemplateCustomizer的定制器代码,我们发现在定制器中加入了一个拦截器

@Configuration	@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")	static class LoadBalancerInterceptorConfig {		@Bean		public LoadBalancerInterceptor ribbonInterceptor(				LoadBalancerClient loadBalancerClient,				LoadBalancerRequestFactory requestFactory) {			return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);		}		@Bean		@ConditionalOnMissingBean		public RestTemplateCustomizer restTemplateCustomizer(				final LoadBalancerInterceptor loadBalancerInterceptor) {			return restTemplate -> {    List<ClientHttpRequestInterceptor> list = new ArrayList<>(      restTemplate.getInterceptors());    list.add(loadBalancerInterceptor);    restTemplate.setInterceptors(list);   };		}	}

ClientHttpRequestInterceptor的拦截具体内容为,根据获取到的请求路径和请求地址进行负载均衡

	@Override	public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,			final ClientHttpRequestExecution execution) throws IOException {		final URI originalUri = request.getURI();		String serviceName = originalUri.getHost();		Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);		return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));	}

执行负载均衡的代码

	public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {		ILoadBalancer loadBalancer = getLoadBalancer(serviceId);		Server server = getServer(loadBalancer, hint);		if (server == null) {			throw new IllegalStateException("No instances available for " + serviceId);		}		RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,				serviceId), serverIntrospector(serviceId).getMetadata(server));		return execute(serviceId, ribbonServer, request);	}

从这段代码可以看出,第一行根据配置,选出相应的负载均衡策略。第二行就是根据相应的负载均衡策略选择一个服务端进行服务请求,达到负载均衡的目的
最后在BaseLoadBalancer中执行了根据不同的策略选择服务的操作

 public Server chooseServer(Object key) {  if (counter == null) {   counter = createCounter();  }  counter.increment();  if (rule == null) {   return null;  } else {   try {    return rule.choose(key);   } catch (Exception e) {    logger.warn("LoadBalancer [{}]: Error choosing server for key {}", name, key, e);    return null;   }  } }

考虑完了上面的主逻辑之后,还有一个问题,就是服务列表是什么时候获取到的。
在RibbonAutoConfigration中注入了SpringClientFactory,而SpringClientFactory又注入了RibbonClientConfiguration

	public SpringClientFactory() {		super(RibbonClientConfiguration.class, NAMESPACE, "ribbon.client.name");	}

RibbonClientConfiguration中进行了注入客户端操作的相关操作,包括负载均衡策略,客户端配置,服务列表等,其中最重要的就是如何获取和更新服务列表

	@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,				serverListFilte......

原文转载:http://www.shaoqun.com/a/871412.html

跨境电商:https://www.ikjzd.com/

宝付:https://www.ikjzd.com/w/539

myshow:https://www.ikjzd.com/w/2235

cares:https://www.ikjzd.com/w/1302


Ribbon使用ribbon在使用上非常简单,仅仅只需要在配置类上加入配置即可@Bean@LoadBalancedpublicRestTemplaterestTemplate(){returnnewRestTemplate();}调用时,直接使用在eureka中注册的服务名进行调用,就可以由ribbon来进行负载均衡了@GetMapping("/checkAndBegin/{userId
海拍客:https://www.ikjzd.com/w/1742
美国遭地震飓风夹击:俄勒冈爆发6.2级地震佛州将被飓风多利安袭击:http://www.30bags.com/a/433461.html
美国这9个惊人景点让人难以置信:http://www.30bags.com/a/248740.html
美国真有这么香?如今"风景线"不断,大量华人却仍不愿回国?:http://www.30bags.com/a/245386.html
美国争议最大的景点:人像动物一样供游客观赏,引居民抗议:http://www.30bags.com/a/226374.html
人妻一边接电话一边被我干 人妻美妇疯狂迎合:http://lady.shaoqun.com/a/247062.html
男友扒了我的奶罩吻我的胸 男朋友摸进我内裤揉搓:http://lady.shaoqun.com/m/a/247552.html
我竟被老公骗进了换妻俱乐部(2/2):http://lady.shaoqun.com/m/a/66898.html
深圳海上田园水上乐园门票价格:http://www.30bags.com/a/495640.html
深圳海上田园老人门票有优惠吗/免费吗:http://www.30bags.com/a/495641.html
深圳海上田园60岁以上免费吗:http://www.30bags.com/a/495642.html
八款大大增加夫妻性趣的成人游戏:http://lady.shaoqun.com/a/418076.html

No comments:

Post a Comment