【SpringCloud】(七):自定義Ribbon

00潤物無聲00發表於2017-08-13

  上篇文章,我們已經使用Ribbon解決了服務地址硬編碼和負載均衡,負載均衡預設使用的是輪詢方式。

  本篇文章,我們來描述Ribbon的自定義配置,以配置它的負載均衡演算法的方式為例。

  自定義配置有2中方式,通過程式碼或配置檔案


一.通過程式碼的方式




對WARNING內容的理解:

這個配置類必須加上@Configuration註解,但是要注意,它不是一個主要的應用元件在@ComponetScan 中。否則會被所有的@RibbonClient共享。
因此如果你使用@ComponetScan,你需要採取措施避免它被掃描。
使configuration只作用於指定的RibbonClient,解決方案:
  1.把它放在一個獨立的,非重疊的包,
  2.或指定掃描明確的元件包,不掃描它


對Ribbon配置的類,要加上@Configuration註解,但是不能被@ComponetScan 掃描。


配置類TestConfiguration,配置負載均衡演算法為隨機

package com.dynamic.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.dynamic.cloud.ExcludeFromComponentScan;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;

@Configuration
@ExcludeFromComponentScan
public class TestConfiguration {

	@Bean
	public IRule ribbonRule()
	{
		return new RandomRule();
	}
}

啟動類

package com.dynamic.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.client.RestTemplate;

import com.dynamic.config.TestConfiguration;

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "microservice-provider-user", configuration = TestConfiguration.class)
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,value = ExcludeFromComponentScan.class)})
public class ComsumerMovieRibbonApplication {

	@Bean
	@LoadBalanced//讓restTemplate具備Ribbon負載均衡的能力。
	public RestTemplate restTemplate()
	{
		return new RestTemplate();
	}
	
	public static void main(String[] args) {
		SpringApplication.run(ComsumerMovieRibbonApplication.class, args);
	}
}


Controller

package com.dynamic.cloud.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.dynamic.cloud.entity.User;

@RestController
public class MovieController {
	@Autowired
	private RestTemplate restTemplate;

	@Autowired
	private LoadBalancerClient loadBalancerClient;

	@GetMapping("/movie/{id}")
	public User findById(@PathVariable Long id) {
		// http://localhost:7900/simple/
		// VIP Virtual IP:虛擬IP,使用的是服務提供者的ServiceId,也就是application.name
		// HAProxy HeartBeat
		// microservice-provider-user:7900
		return this.restTemplate.getForObject("http://microservice-provider-user/simple/" + id, User.class);
	}

	@GetMapping("/test")
	public String test() {
		ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
		System.out.println("111"+ ":" + serviceInstance.getServiceId() +":"+serviceInstance.getHost() + ":"+ serviceInstance.getPort() );
		
		ServiceInstance serviceInstance2 = this.loadBalancerClient.choose("microservice-provider-user2");
		System.out.println("222" + ":" + serviceInstance2.getServiceId()+":"+ serviceInstance2.getHost() + ":"+ serviceInstance2.getPort() );
		return "1";
	}

}

解決@Configuration和@ComponetScan衝突

1.讓配置類不在啟動的包或者子包下。解決。

2.加入註解


(1)註解:

package com.dynamic.cloud;

public @interface ExcludeFromComponentScan {

}

(2)如上述程式碼,在配置類上加上該註解@ExcludeFromComponentScan

(3)在啟動類加上,@ComponentScan(excludeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,value = ExcludeFromComponentScan.class)})


在啟動類上的註解:

@RibbonClient(name = "microservice-provider-user", configuration = TestConfiguration.class)。如果解決了@Configuration和@ComponetScan的衝突。則只有服務ID為microservice-provider-user的負載均衡演算法,才是自定義配置的隨機。而其他的服務還是預設的輪詢。




請求結果:

111:microservice-provider-user:192.168.21.60:7900
222:microservice-provider-user2:192.168.21.60:7903
111:microservice-provider-user:192.168.21.60:7900
222:microservice-provider-user2:192.168.21.60:7904
111:microservice-provider-user:192.168.21.60:7901
222:microservice-provider-user2:192.168.21.60:7903
111:microservice-provider-user:192.168.21.60:7901
222:microservice-provider-user2:192.168.21.60:7904
111:microservice-provider-user:192.168.21.60:7901
222:microservice-provider-user2:192.168.21.60:7903
111:microservice-provider-user:192.168.21.60:7901
222:microservice-provider-user2:192.168.21.60:7904


可以看出,microservice-provider-user的負載均衡策略是隨機,microservice-provider-user2的策略是輪詢


二.配置檔案配置Ribbon

  我們把所有程式碼配置的全部去掉,使用配置檔案進行配置。



在電影微服務的配置檔案中加上:

microservice-provider-user: #服務id
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule



服務ID為microservice-provider-user的負載均衡為隨機。而microservice-provider-user為輪詢。

111:microservice-provider-user:192.168.21.60:7900

222:microservice-provider-user2:192.168.21.60:7903

111:microservice-provider-user:192.168.21.60:7901

222:microservice-provider-user2:192.168.21.60:7902

111:microservice-provider-user:192.168.21.60:7900

222:microservice-provider-user2:192.168.21.60:7903

111:microservice-provider-user:192.168.21.60:7900

222:microservice-provider-user2:192.168.21.60:7902


相比Java程式碼配置,使用配置檔案

1.優先順序高

2.簡潔






相關文章