SpringCloud-Ribbon Client-初始化

loadbalancerclient

使用場景
    @GetMapping("testChoose")
    public ServiceInstance testChoose() {
     // 與Feign或RestTemplate均衡機制相同,都是基於ILoadBalancer&Rule來進行的
        return loadBalancerClient.choose("provider-app");
    }

本次基於RibbonLoadBalancerClient(在自動裝配過程中,它的優先級比較高)來分析

初始化LoadBalancerClient
  // org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration

 // 用來創建Client Context, 每個ClientContext都是一個獨立的上下文 
	@Bean
	public SpringClientFactory springClientFactory() {
		SpringClientFactory factory = new SpringClientFactory();
		factory.setConfigurations(this.configurations);
		return factory;
	}

 // 客戶端負載均衡的入口
	@Bean
	@ConditionalOnMissingBean(LoadBalancerClient.class)
	public LoadBalancerClient loadBalancerClient() {
		return new RibbonLoadBalancerClient(springClientFactory());
	}

LoadBalancerClient的底層選擇邏輯基於如下兩個操作完成

       //loadbalancer init, 這是關鍵邏輯,超時,規則,重試都是基於此對象完成的
		ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
		// 根據LoadBalancer選擇匹配的Server
		Server server = getServer(loadBalancer, hint);
ILoadBalancer的初始化
 // org.springframework.cloud.netflix.ribbon.SpringClientFactory
	/**
	 * Get the load balancer associated with the name.
	 * @param name name to search by
	 * @return {@link ILoadBalancer} instance
	 * @throws RuntimeException if any error occurs
	 */
	public ILoadBalancer getLoadBalancer(String name) {
		return getInstance(name, ILoadBalancer.class);
	}

	public SpringClientFactory() {
	   // 生成ILoadBalancer過程中會基於RibbonClientConfiguration來配置
		super(RibbonClientConfiguration.class, NAMESPACE, "ribbon.client.name");
	}
	protected AnnotationConfigApplicationContext createContext(String name) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		// 基於註解的Ribbon配置
		if (this.configurations.containsKey(name)) {
			for (Class<?> configuration : this.configurations.get(name)
					.getConfiguration()) {
				context.register(configuration);
			}
		}
		//全局 默認配置
		for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
			if (entry.getKey().startsWith("default.")) {
				for (Class<?> configuration : entry.getValue().getConfiguration()) {
					context.register(configuration);
				}
			}
		}
		
		
		context.register(PropertyPlaceholderAutoConfiguration.class,
				// 默認配置模板
				this.defaultConfigType);
		context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
				this.propertySourceName,
				// 添加客戶端名稱
				//@Value("${ribbon.client.name}")public @interface RibbonClientName 
				// this.propertyName = ribbon.client.name
				Collections.<String, Object>singletonMap(this.propertyName, name)));
		if (this.parent != null) {
			// Uses Environment from parent as well as beans
			context.setParent(this.parent);
			// jdk11 issue
			// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
			context.setClassLoader(this.parent.getClassLoader());
		}
		context.setDisplayName(generateDisplayName(name));
		context.refresh();
		return context;
	}
基於配置文件的初始化
 // 配置讀取源
	@Bean
	@ConditionalOnMissingBean
	public PropertiesFactory propertiesFactory() {
		return new PropertiesFactory();
	}

// org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration#ribbonLoadBalancer
	@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);
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章