1. 程式人生 > >Spring Cloud eureka註冊中心例項不可用,ribbon配置請求重試

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
開啟區域性微服務重試機制 必須加上指定的微服務

 還有更多功能沒有挖掘,學習的道路還有很長