Ribbon
server.port=8081
spring.application.name=consumer-service
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
#ribbon,制定服務配置,默認配置類爲DefaultClientConfigImpl
ribbon.ConnectTimeout=500
# 這個參數配置要小於熔斷超時的配置,否則直接熔斷沒機會重試
ribbon.ReadTimeout=2000
# 這個請求建議設置爲false, 這樣的話只有get請求會重試而其它類型的請求不會重試,默認爲false
ribbon.OkToRetryOnAllOperations=false
#重試策略先嚐試訪問首選實例一次
ribbon.MaxAutoRetries=2
#嘗試更換兩次實例進行重試
ribbon.MaxAutoRetriesNextServer=0
# 不作爲eureka客戶端
eureka.client.enabled=false
eureka.client.fetch-registry=false
# 使用okhttp
feign.httpclient.enabled=false
feign.okhttp.enabled=true
# 禁用ribbon從eureka中獲取服務地址,並配置特定服務的地址
ribbon.eureka.enabled=false
hello-service.ribbon.listOfServers= http://localhost:8080,http://localhost:8082
# 開啓ribbon上下文的飢餓加載,默認是懶加載,第一次請求的時候才加載ribbon上下文,可以避免第一次請求超時導致熔斷
ribbon.eager-load.enabled=true
# 開啓服務熔斷
feign.hystrix.enabled=true
# 全局熔斷超時時間配置,默認是1秒有點短了
hystrix.command.execution.isolation.thread.timeoutinMilliseconds=50OO
#爲 hello方法單獨配置超時時間,所有的hello方法都會使用這個配置
hystrix.command.hello.execution.isolation.thread.timeoutinMilliseconds=5OOO
# 斷路器休眠時間,默認5秒
hystrix.command.defaul七.circuitBreaker.sleepWindowinMilliseconds=20000
# 時間窗口內錯誤率超過這個值才斷開,默認50%
hystrix.command.default.circuitBreaker.errorThresholdPercentage=90
package com.example.springcloudprovider;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.discovery.converters.Auto;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.nio.charset.Charset;
import java.util.*;
/**
* 用於處理feign的get請求傳遞pojo參數的攔截器
*/
@Component
public class FeignRequestInterceptor implements RequestInterceptor {
@Autowired
private ObjectMapper objectMapper;
@Override
public void apply(RequestTemplate template) {
if (template.method().equals("GET") && template.body() != null){
try {
JsonNode jsonNode = objectMapper.readTree(template.body());
template.body(null , Charset.defaultCharset());
Map<String, Collection<String>> querys = new HashMap<>();
buildQuery(jsonNode, "", querys);
template.queries(querys);
} catch (Exception ex){};
}
}
private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
// 葉子節點
if (!jsonNode.isContainerNode()) {
if (jsonNode.isNull()) {
return;
}
Collection<String> values = queries.get(path);
if (null == values) {
values = new ArrayList<>();
queries.put(path, values);
}
values.add(jsonNode.asText());
return;
}
// 數組節點
if (jsonNode.isArray()) {
Iterator<JsonNode> it = jsonNode.elements();
while (it.hasNext()) {
buildQuery(it.next(), path, queries);
}
} else {
Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
while (it.hasNext()) {
Map.Entry<String, JsonNode> entry = it.next();
if (StringUtils.hasText(path)) {
buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
} else { // 根節點
buildQuery(entry.getValue(), entry.getKey(), queries);
}
}
}
}
}
Hystrix
原生用法
使用feign快速使用
服務降級
異常處理
工作流程
- 每次調用遠程服務方法時,會先把調用邏輯包裝在HystrixCommand對象中,這個command對象中包含一個斷路器,每次調用完成後,Hystrix會把失敗、成功、拒絕、超時等信息報告給斷路器。
斷路器斷開的觸發條件,如果10秒窗口統計信息中,該方法的QPS大於20並且錯誤百分比大於50%則設置短路器爲打開狀態,則設置斷開斷路器。
判斷一個請求是否被允許有兩個標準,第一個是斷路器是否是閉合的。如果是斷開的,但是斷開的時間到現在已經過了一段時間了,默認是5秒,則可以允許這個請求。如果這個請求成功了,則立即閉合斷路器,並重置統計數據,如果失敗了則重置斷路器斷開時間,這樣一段時間內就不會有請求進來了。
線程池劃分
配置詳解
優化配置
請求緩存
請求合併
線程池調整