三、SpringCloud使用Ribbon+RestTemplate實現負載均衡
阿新 • • 發佈:2019-01-08
一、Ribbon簡介
Ribbon是Netflix公司開源的使用在客戶端的一個負載均衡的專案。是SpringCloud Finchley.M8版本結合使用Consul時使用預設負載均衡客戶端。
負載均衡策略有以下,當然我們一可以更具實際需求,來自定義負載均衡策略。
SpringCloud中預設使用ZoneAvoidanceRule策略
類(策略) | 說明 | 實現簡介 |
---|---|---|
ZoneAvoidanceRule | 複合判斷server所在區域的效能和server的可用性選擇server | 使用ZoneAvoidancePredicate和AvailabilityPredicate來判斷是否選擇某個server,前一個判斷判定一個zone的執行效能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用於過濾掉連線數過多的Server |
RandomRule | 隨機選擇一個server | 在index上隨機,選擇index對應位置的server |
RoundRobinRule | roundRobin方式輪詢選擇server | 輪詢index,選擇index對應位置的server |
RetryRule | 對選定的負載均衡策略機上重試機制 | 在一個配置時間段內當選擇server不成功,則一直嘗試使用subRule的方式選擇一個可用的server |
WeightedResponseTimeRule | 根據響應時間分配一個weight,響應時間越長,weight越小,被選中的可能性越低 | 一個後臺執行緒定期的從status裡面讀取評價響應時間,為每個server計算一個weight。Weight的計算也比較簡單responsetime 減去每個server自己平均的responsetime是server的權重。當剛開始執行,沒有形成status時,使用roubine策略選擇server |
AvailabilityFilteringRule | 過濾掉那些因為一直連線失敗的被標記為circuit tripped的後端server,並過濾掉那些高併發的的後端server(active connections 超過配置的閾值) | 使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就就是檢查status裡記錄的各個server的執行狀態 |
BestAvailableRule | 選擇一個最小的併發請求的server | 逐個考察Server,如果Server被tripped了,則忽略,在選擇其中ActiveRequestsCount最小的server |
二、RestTemplate的原理
原理簡介:使用RestTemplate作為負載均衡模版,必須要使用@LoadBalance註解。
通過該註解,將RestTemplate被標記為使用RibbonLoadBalancerClient的作為負載均衡模版。使用restTmeplate發起http請求,請求被Spring攔截器攔截,然後處理攔截的請求,首先ConsulClient通過serviceId獲取所有ServiceInstance,在使用RibbonLoadBalancerClient選擇一個滿足負載策略的ServiceInstance作為請求的service,最後通過RestTemplate請求service。
三、建立服務consulservice3
1、引入依賴
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--用於監控與管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--config server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul</artifactId>
</dependency>
<!--服務發現依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--用於consul配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
</dependencies>
2、簡單的配置
spring.application.name=consulservice3
spring.cloud.consul.discovery.instance-id=${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
3、建立程式啟動入口
@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class ConsulService3App {
@Value("${spring.application.name}")
private String serviceName;
@Value("${server.port}")
private int servicePort;
@RequestMapping("/say")
public String say(){
return "hello world! I'm '" + serviceName + ":" + servicePort + "'";
}
public static void main(String[] args){
SpringApplication.run(ConsulService3App.class, args);
}
}
4、分別以埠8001和8002啟動consulservice3
可以看到服務已經註冊到ConsulServer了,一個偽叢集
三、建立客戶端consulclient3
1、引入依賴
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--用於監控與管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--config server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul</artifactId>
</dependency>
<!--服務發現依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--用於consul配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
</dependencies>
2、簡單配置
spring.application.name=consulclient3
3、建立啟動引用程式入口
說明:由於簡單教程,所以介面和配置都放在一起了,實際應用中決不允許這麼做
@SpringBootApplication
@EnableDiscoveryClient
@RestController
@Configuration
public class ConsulClient3App {
@Bean
@LoadBalanced//此註解必須存在
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Autowired
private RestTemplate restTemplate;
//serviceId獲取service
private static final String SERVICE_ID = "consulservice3";
@RequestMapping("/say")
public String sayService() {
//使用restTemplate作為模版,serviceId會被ribbonClient替換為服務的地址
return restTemplate.getForObject("http://"+SERVICE_ID+"/say",String.class);
}
public static void main(String[] args){
SpringApplication.run(ConsulClient3App.class, args);
}
}
4、以埠9999啟動consulclient3,呼叫介面,證明負載均衡成功