Eureka客戶端-服務消費者(Ribbon)
1、pom.xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!--restTemplate要用到--> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <!--客戶端只有當我們有了這個依賴之後,才能有那些狀態頁面的檢視,否則會報ErrorPage--> </dependency>
2、application.yml
spring:
application:
name: eureka-client-consumer-ribbon
server:
port: 8601
eureka:
instance:
prefer-ip-address: true
client:
service-url:
defaultZone: http://localhost:8761/eureka/
3、最基本的Ribbon訪問
(1)暴露的服務
@RestController public class BasicGetService { @Autowired RestTemplate restTemplate; @RequestMapping("/getProviderPort") public String getProviderPort(){ String s = restTemplate.getForObject("http://eureka-client-provider/getServerPort", String.class); System.out.println(s); return s; } }
(2)啟動類
@SpringBootApplication @EnableDiscoveryClient public class EurekaClientConsumerRibbonApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientConsumerRibbonApplication.class, args); } @Bean @LoadBalanced //通過這個註解,就是用到了ribbon RestTemplate restTemplate(){ return new RestTemplate(); } }
(3)訪問結果
將eureka-client-provider分別在兩個埠進行啟動,多次訪問發現返回值為輪詢規則,兩個埠輪詢呼叫
4、不使用預設的Ribbon,修改Ribbon的規則
(1)自定義一個Ribbon客戶端,客戶端的配置在FooConfiguration類中進行定義
@Configuration
@RibbonClient(name = "eureka-client-provider", configuration = FooConfiguration.class)
public class TestConfiguration {
}
(2)FooConfiguration 的定義
@Configuration
@ExcludeFromComponentScan
public class FooConfiguration {
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
(3)FooConfiguration
必須是@Configuration
,但請注意,它不在主應用程式上下文的@ComponentScan
中,否則將由所有@RibbonClients
共享。
因此有下面的解決方案,在FooConfiguration的同級目錄下,定義這個註釋
public @interface ExcludeFromComponentScan {
}
(4)並且在啟動類中
@SpringBootApplication
@EnableDiscoveryClient
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,value = ExcludeFromComponentScan.class)})
public class EurekaClientConsumerRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientConsumerRibbonApplication.class, args);
}
@Bean
@LoadBalanced
//通過這個註解,就是用到了ribbon
RestTemplate restTemplate(){
return new RestTemplate();
}
}
即可
這樣我們配置完成之後,我們所有的呼叫eureka-client-provider這個例項下的服務的時候,都會實現隨機呼叫。
5、我們還可以使用配置檔案進行更改Ribbon配置的操作
eureka-client-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
配置檔案配置的優先順序高於Java程式碼配置的優先順序
備註:Ribbon幾大重要的配置:
-
IClientConfig
ribbonClientConfig:DefaultClientConfigImpl
-
IRule
ribbonRule:ZoneAvoidanceRule
-
IPing
ribbonPing:NoOpPing
-
ServerList<Server>
ribbonServerList:ConfigurationBasedServerList
-
ServerListFilter<Server>
ribbonServerListFilter:ZonePreferenceServerListFilter
-
ILoadBalancer
ribbonLoadBalancer:ZoneAwareLoadBalancer
-
ServerListUpdater
ribbonServerListUpdater:PollingServerListUpdater
6、單獨使用Ribbon
示例:如何使用Ribbon不使用Eureka
Eureka是一種方便的方式來抽象遠端伺服器的發現,因此您不必在客戶端中對其URL進行硬編碼,但如果您不想使用它,Ribbon和Feign仍然是適用的。假設您已經為“商店”申請了@RibbonClient
,並且Eureka未被使用(甚至不在類路徑上)。Ribbon客戶端預設為已配置的伺服器列表,您可以提供這樣的配置
application.yml
<span style="color:rgba(0, 0, 0, 0.8)"><span style="color:rgba(0, 0, 0, 0.9)">stores:
ribbon:
listOfServers: example.com,google.com</span></span>
示例:在Ribbon中禁用Eureka使用
設定屬性ribbon.eureka.enabled = false
將明確禁用在Ribbon中使用Eureka。
application.yml
<span style="color:rgba(0, 0, 0, 0.8)"><span style="color:rgba(0, 0, 0, 0.9)">ribbon:
eureka:
enabled: false</span></span>
直接使用Ribbon API
您也可以直接使用LoadBalancerClient
。例:
<span style="color:rgba(0, 0, 0, 0.8)"><span style="color:rgba(0, 0, 0, 0.9)"><code class="language-java">public class MyClass {
@Autowired
private LoadBalancerClient loadBalancer;
public void doStuff() {
ServiceInstance instance = loadBalancer.choose("stores");
URI storesUri = URI.create(String.format("http://%s:%s", instance.getHost(), instance.getPort()));
// ... do something with the URI
}
}</code></span></span>