Spring Cloud eureka註冊中心例項不可用,ribbon配置請求重試
今天 在開發的時候,開發環境都 註冊到服務中心,但是有些開發同事服務是不可用的,但是又設定了服務保護機制,例項仍然是up 的,在本地進行開發的時候,可以使用eureka.server.enable-self-preservation=false引數來關閉保護機制,以確保註冊中心可以將不可用的例項正確剔除,因為有同事不關心這個,直接預設配置都是true,導致線上問題,就需要改變一下,如果發現服務例項不可用,或者異常自動轉發其它例項上再執行,
首生要加包 springooot 依賴的其它包就不貼出來了,主要容斷器的包要新增上去
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
在啟動服務類裡面,需要加些引數 SpringApplication.run(YitaiTMSApplication.class, args);
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) @Import(FdfsClientConfig.class)//可以擁有帶有連線池的FastDFS Java客戶端 @EnableTransactionManagement @ServletComponentScan @MapperScan("com.yitai.tms.*.dao") @SpringBootApplication @EnableEurekaClient @EnableScheduling @EnableDiscoveryClient @EnableHystrix public class YitaiTMSApplication { public static void main(String[] args) { SpringApplication.run(YitaiTMSApplication.class, args); } //@EnableHystrix 這個是必須的, 開戶容斷器 // @Primary 這個不是必須的,這個注入是如果注入相同例項,有這個關鍵字就優先注入 @Bean @LoadBalanced public RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setReadTimeout(4000); httpRequestFactory.setConnectTimeout(4000); return new RestTemplate(httpRequestFactory); } // 設定訪問時間和連線超時時間,預設的時間太長,配置後可以有效時間內轉發服務註冊例項請求
接下來是配置檔案 application.yml
#開啟hystrix功能 這個功能是 feign方式呼叫祕,ribbon的配置與feign整合後配置設定引數一樣 feign: hystrix: enabled: true #tms-mrg: 如果加上這個配置,說明指定的微服務開啟重試功能,不是自己的微服務名稱,相當如區域性服務重試 ribbon: # 同一例項最大重試次數,不包括首次呼叫,配置後本例項至少會執行兩次 MaxAutoRetries: 1 # 重試其他例項的最大重試次數,不包括首次所選的server,配置後本例項和其它服務註冊例項至少會執行兩次 MaxAutoRetriesNextServer: 2 # 是否所有操作都進行重試 OkToRetryOnAllOperations: false #預設為false,則只允許GET請求被重試 #如果此設定關閉, 所有重試機制都失效,注意:全域性重試如區域性重試開啟,是本服務呼叫的所有微服務都開啟重試,配置區域性微服務名稱才啟作用此稱為區域性重試機制 #下面兩個時間我是指定在服務啟動時設定的,如果不指定就在這裡設定 ReadTimeout: 5000 #請求時間,這個配置容斷器的時間,必須小於容斷器設定的時間才能觸發重試 ConnectTimeout: 2000 # 服務連線時間 對時間有特殊要求可以配置下面兩個, #開戶服務重試機制,預設是關閉,但是,開啟OkToRetryOnAllOperations後,不配也行 cloud: loadbalancer: retry: enabled: true #這是容斷器的時間 必須大於請求時間才能觸發重試,容斷器沒有超時肯定不會去重試 hystrix: command: default: execution: # timeout: # enabled:true isolation: thread: timeoutInMilliseconds:1000 配置超時時間,預設是開啟超時時間,這裡有設定超時時間是1秒觸發容斷,預設是5秒
下面是配置的程式碼
/**
*
* @param post請求方式, 直接封裝json傳遞引數
* @return 特別說明 ,容斷器的回撥函式必須與注入的容斷函式保持一致,返回引數必須一致
*/
@HystrixCommand(fallbackMethod="postDataFallback")
private JSONObject postData(JSONObject jsonObj,String urls){
if (StringUtils.isBlank(urls)) {
return null;
}
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
HttpEntity<String> formEntity = new HttpEntity<String>(jsonObj.toString(), headers);
String result = restTemplate.postForObject(urls, formEntity, String.class);
JSONObject results = JSONObject.parseObject(result);
/*if (results.getIntValue("code") == 0){
results.getString("data");
}else{
results.put("code", 1);
}*/
return results;
}
//呼叫超時和不可用的時候執行的方法,返回引數與 提交引數一致儘可,無引數也可行
//返回引數必須和注入的方法一致 所以下面方法這樣寫是不會回撥的
public void postDataFallback(JSONObject jsonObj,String url) {
logger.debug("服務註冊中心返回失敗"+url.toString());
//return "fallback";
}
正確方法應該如下
public JSONObject postDataFallback(JSONObject jsonObj, String url) {
logger.debug("服務註冊中心返回失敗" + url.toString());
System.out.println("**************************** "+url.toString());
return new JSONObject();
}
GET請求方式的熔斷返回
@HystrixCommand(fallbackMethod = "getDataFallback")
private JSONObject getData(String url) {
// String url = "http://tms-mgr-ssss/jhb/waybill/updateStatus?vin=" + urls+
// "&fromTime=" + urls;
if (StringUtils.isBlank(url)) {
return null;
}
JSONObject result = JSONObject.parseObject(restTemplate.getForObject(url, String.class));
if (result.getIntValue("code") == 0) {
result.getString("data");
} else {
result = new JSONObject();
result.put("code", 1);
}
return result;
}
正確方法應該如下
JSONObject getDataFallback(String urls) {
System.out.println("____________________________________");
logger.debug("服務註冊中心返回失敗"+url.toString());
return new JSONObject();
}
服務請求這裡後面再研究了下,配置有很大關係 重點 OkToRetryOnAllOperations 開啟所有請求重試
基於HTTP響應碼重試
clientName:
ribbon:
retryableStatusCodes: 404,502
注意點:
一般來說,不建議將ribbon.OkToRetryOnAllOperations 設為true。
因為一旦啟用該配置,則表示重試任何操作,包括POST請求,而由於快取了請求體,此時可能會影響伺服器的資源。
此結論有待驗證,之前結論裡是說重試 GET請求
方法引數可以知道呼叫哪個服務不可用,會打印出IP地址,進行排查,當然不會丟擲異常,相當能 try catch處理過,顯示不可用的服務例項IP 如 192.168.11.88:3020 等詳細資訊。
下面容斷的玩意,必須一致 其它配置都預設就可以,只需要改變一下配置容斷超時時間就OK,被坑過
@GetMapping("/getelf")
@HystrixCommand(fallbackMethod="fallbackTest")
public JSONObject elfste(String urls){
urls="http://microservice-elefdata-service/getelefdata/test";
JSONObject result = JSONObject.parseObject(restTemplate.getForObject(url, String.class));
return result;
}
JSONObject fallbackTest(String urls) {
System.out.println("____________________________________");
logger.debug("服務註冊中心返回失敗"+url.toString());
return new JSONObject();
}
服務註冊中心的服務例項轉發,並不能保證全部都會轉發到正常服務例項中去,偶爾會去不可用的服務例項,可能這是為了容錯性的而做的策略,嘗試去執行一次,如果服務可用下次請求就可能會自動落到此例項,
今天重試和容斷器總結
啟動微服務時 注入的方法
1 @EnableHystrix 與 @EnableCircuitBreaker 效果一樣, 前者包含後者
2 @HystrixCommand(fallbackMethod="fallbackTest") 裡面的方法返回型別必須一致, 程式碼如上
3 配置重試機制 關鍵點 OkToRetryOnAllOperations: false 預設關閉,true開啟就會自動重試,引數配置如上,下面是再次強調
tms-mgr:
ribbon:
# 同一例項最大重試次數,不包括首次呼叫,配置後本例項至少會執行兩次
MaxAutoRetries: 1
開啟區域性微服務重試機制 必須加上指定的微服務
還有更多功能沒有挖掘,學習的道路還有很長