開啓重試在某些狀況下是有問題的,好比當壓力過大,一個實例中止響應時,路由將流量轉到另外一個實例,頗有可能致使最終全部的實例全被壓垮。
說到底,斷路器的其中一個做用就是防止故障或者壓力擴散。用了retry,斷路器就只有在該服務的全部實例都沒法運做的狀況下才能起做用。這種時候,斷路器的形式更像是提供一種友好的錯誤信息,或者僞裝服務正常運行的假象給使用者。html
不用retry,僅使用負載均衡和熔斷,就必須考慮到是否可以接受單個服務實例關閉和eureka刷新服務列表之間帶來的短期的熔斷。若是能夠接受,就無需使用retry。
java
#retry
#該參數用來開啓重試機制 。只設置這個開關,肯定好用。 TODO : 瞭解下實現原理
spring.cloud.loadbalancer.retry.enabled=true
#斷路器的超時時間,斷路器的超時時間須要大於ribbon的超時時間,否則不會觸發重試。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
#ribbon請求鏈接的超時時間
ribbon.ConnectTimeout=250
#請求處理的超時時間
ribbon.ReadTimeout=1000
#對全部操做請求都進行重試
ribbon.OkToRetryOnAllOperations=true
#對當前實例的重試次數
ribbon.MaxAutoRetries=1
#對下個實例的重試次數
ribbon.MaxAutoRetriesNextServer=1
https://blog.csdn.net/zl1zl2zl3/article/details/67636901git
版本1.5.6
使用Ribbon zuul hystrix程序員
引入重試jar包github
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
參考 LoadBalancerAutoConfiguration 以及RibbonAutoConfiguration
實現原理: RetryLoadBalancerInterceptor 實現 ClientHttpRequestInterceptor 經過攔截器實現
配置spring
注意:
- ribbon.ConnectTimeout+ribbon.ReadTimeout<hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
- 鏈接失敗的意思是服務宕機,請求不可到達, 並非服務報錯apache
http://www.javashuo.com/article/p-zrlynohr-mp.html
Springcloud實踐(二)之api網關:zuulsegmentfault
zuul是什麼?
front door. API Gateway.Zuul is a JVM based router and server side load balancer by Netflix.全部請求的入口。
As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. 做爲邊界應用服務,zuul能實現動態路由、監控、彈性與安全性。
用groovy編寫。
Netflix uses Zuul for the following:後端
Authentication 認證 Insights 洞察力 Stress Testing 壓力測試 Canary Testing 金絲雀測試 Dynamic Routing 動態路由 Service Migration 服務遷移 Load Shedding 減載 Security 安全 Static Response handling 靜態響應處理 Active/Active traffic management
若是之後想設計網關,可按照上面進行對標設計。api
zuul 請求處理過程:
https://www.cnblogs.com/small-k/p/8137943.html
Spring Cloud之Feign、ribbon設置超時時間和重試機制的總結
1、 Feign設置超時時間
使用Feign調用接口分兩層,ribbon的調用和hystrix的調用,因此ribbon的超時時間和Hystrix的超時時間的結合就是Feign的超時時間
#hystrix的超時時間 hystrix: command: default: execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 9000 #ribbon的超時時間 ribbon: ReadTimeout: 3000 ConnectTimeout: 3000
通常狀況下 都是 ribbon 的超時時間(<)hystrix的超時時間(由於涉及到ribbon的重試機制)
由於ribbon的重試機制和Feign的重試機制有衝突,因此源碼中默認關閉Feign的重試機制,源碼以下
要開啓Feign的重試機制以下:(Feign默認重試五次 源碼中有)
@Bean Retryer feignRetryer() { return new Retryer.Default(); }
2、ribbon的重試機制
設置重試次數:
ribbon: ReadTimeout: 3000 ConnectTimeout: 3000 MaxAutoRetries: 1 #同一臺實例最大重試次數,不包括首次調用 MaxAutoRetriesNextServer: 1 #重試負載均衡其餘的實例最大重試次數,不包括首次調用 OkToRetryOnAllOperations: false #是否全部操做都重試
根據上面的參數計算重試的次數:MaxAutoRetries+MaxAutoRetriesNextServer+(MaxAutoRetries *MaxAutoRetriesNextServer) 即重試3次 則一共產生4次調用
若是在重試期間,時間超過了hystrix的超時時間,便會當即執行熔斷,fallback。因此要根據上面配置的參數計算hystrix的超時時間,使得在重試期間不能達到hystrix的超時時間,否則重試機制就會沒有意義
hystrix超時時間的計算: (1 + MaxAutoRetries + MaxAutoRetriesNextServer) * ReadTimeout 即按照以上的配置 hystrix的超時時間應該配置爲 (1+1+1)*3=9秒
當ribbon超時後且hystrix沒有超時,便會採起重試機制。當OkToRetryOnAllOperations設置爲false時,只會對get請求進行重試。若是設置爲true,便會對全部的請求進行重試,若是是put或post等寫操做,若是服務器接口沒作冪等性,會產生很差的結果,因此OkToRetryOnAllOperations慎用。
若是不配置ribbon的重試次數,默認會重試一次
注意:
默認狀況下,GET方式請求不管是鏈接異常仍是讀取異常,都會進行重試
非GET方式請求,只有鏈接異常時,纔會進行重試
原文:https://blog.csdn.net/east123321/article/details/82385816
SpringCloud重試機制配置
SpringCloud重試retry是一個很讚的功能,可以有效的處理單點故障的問題。主要功能是當請求一個服務的某個實例時,譬如你的User服務啓動了2個,它們都在eureka裏註冊了,那麼正常狀況下當請求User服務時,ribbon默認會輪詢這兩個實例。此時若是其中一個實例故障了,發生了宕機或者超時等,若是沒有配置啓用重試retry策略,那麼調用方就會獲得錯誤信息或者超時無響應或者是熔斷返回的信息。咱們但願的天然是一個故障了,會自動切換到另外一個去訪問。
最簡單的方法就是retry。
須要先在pom.xml里加入
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
Ribbon、zuul、feign均可以配置各自的retry方式。
1 ribbon配置以下
@Bean @LoadBalanced RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setReadTimeout(5000); httpRequestFactory.setConnectTimeout(5000); return new RestTemplate(httpRequestFactory); }
2 zuul配置以下
zuul的重試比較簡單,不須要任何代碼,直接在yml裏配置便可。
注意,配置時,ribbon開頭的在yml裏是不給提示的,不要覺得不提示就是沒效果,實際上是能夠用的。
這個ReadTimeout和ConnectTimeout區別是很大的,ConnectTimeout是指創建鏈接的時間,若是目標服務宕機或網絡故障,那麼響應的就是ConnectTimeout,沒法鏈接。而ReadTimeout則是鏈接創建後,等待目標服務返回響應的時間,譬如目標服務作了一個複雜操做致使耗時較長,那麼會觸發ReadTimeout。
譬如zuul路由了/user路徑到user服務上,若是User1實例宕機了,那麼配置了retry的zuul就會在重試MaxAutoRetries次數後,切換到另外一個實例User2上。若是User2也故障了,那麼返回404.
retryableStatusCodes裏面有幾個錯誤碼,意思就是遇到哪些錯誤碼時觸發重試。默認是404,我多配了幾個,僅供參考。
3 feign配置以下
feign默認是經過本身包下的Retryer進行重試配置,默認是5次
import static java.util.concurrent.TimeUnit.SECONDS; /** * Cloned for each invocation to {@link Client#execute(Request, feign.Request.Options)}. * Implementations may keep state to determine if retry operations should continue or not. */ public interface Retryer extends Cloneable { /** * if retry is permitted, return (possibly after sleeping). Otherwise propagate the exception. */ void continueOrPropagate(RetryableException e); Retryer clone(); public static class Default implements Retryer { private final int maxAttempts; private final long period; private final long maxPeriod; int attempt; long sleptForMillis; public Default() { this(100, SECONDS.toMillis(1), 5); } public Default(long period, long maxPeriod, int maxAttempts) { this.period = period; this.maxPeriod = maxPeriod; this.maxAttempts = maxAttempts; this.attempt = 1; }
feign取消重試
@Bean Retryer feignRetryer() { return Retryer.NEVER_RETRY; }
feign請求超時設置
@Bean Request.Options requestOptions(ConfigurableEnvironment env){ int ribbonReadTimeout = env.getProperty("ribbon.ReadTimeout", int.class, 6000); int ribbonConnectionTimeout = env.getProperty("ribbon.ConnectTimeout", int.class, 3000); return new Request.Options(ribbonConnectionTimeout, ribbonReadTimeout); }
Spring Cloud Zuul網關 Filter、熔斷、重試、高可用的使用方式。
時間過的很快,寫springcloud(十):服務網關zuul初級篇還在半年前,如今已是2018年了,咱們繼續探討Zuul更高級的使用方式。
上篇文章主要介紹了Zuul網關使用模式,以及自動轉發機制,但其實Zuul還有更多的應用場景,好比:鑑權、流量轉發、請求統計等等,這些功能均可以使用Zuul來實現。
Zuul的核心
Filter是Zuul的核心,用來實現對外服務的控制。Filter的生命週期有4個,分別是「PRE」、「ROUTING」、「POST」、「ERROR」,整個生命週期能夠用下圖來表示。
Zuul大部分功能都是經過過濾器來實現的,這些過濾器類型對應於請求的典型生命週期。
PRE: 這種過濾器在請求被路由以前調用。咱們可利用這種過濾器實現身份驗證、在集羣中選擇請求的微服務、記錄調試信息等。
ROUTING:這種過濾器將請求路由到微服務。這種過濾器用於構建發送給微服務的請求,並使用Apache HttpClient或Netfilx Ribbon請求微服務。
POST:這種過濾器在路由到微服務之後執行。這種過濾器可用來爲響應添加標準的HTTP Header、收集統計信息和指標、將響應從微服務發送給客戶端等。
ERROR:在其餘階段發生錯誤時執行該過濾器。
除了默認的過濾器類型,Zuul還容許咱們建立自定義的過濾器類型。例如,咱們能夠定製一種STATIC類型的過濾器,直接在Zuul中生成響應,而不將請求轉發到後端的微服務。
Zuul中默認實現的Filter
禁用指定的Filter
能夠在application.yml中配置須要禁用的filter,格式:
zuul: FormBodyWrapperFilter: pre: disable: true
http://www.javashuo.com/article/p-oxnrponr-ct.html
spring cloud各類超時時間及重試設置
https://blog.csdn.net/wudiyong22/article/details/84937648
配置實例
##timeout config hystrix: command: default: execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 60000 ribbon: ReadTimeout: 60000 ConnectTimeout: 60000 MaxAutoRetries: 0 MaxAutoRetriesNextServer: 1 eureka: enabled: false zuul: max: host: connections: 500 host: socket-timeout-millis: 60000 connect-timeout-millis: 60000
MaxAutoRetries
Max number of retries on the same server (excluding the first try)
MaxAutoRetriesNextServer
Max number of next servers to retry (excluding the first server)
docs
ribbon-Getting-Started
https://segmentfault.com/a/1190000007290888
聊聊ribbon的超時時間設置
序
本文主要研究一下ribbon的超時時間設置
配置
實例
ribbon:
ReadTimeout: 10000
ConnectTimeout: 10000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 1
eureka:
enabled: true
RibbonClientConfiguration
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonClientConfiguration.java
@SuppressWarnings("deprecation") @Configuration @EnableConfigurationProperties //Order is important here, last should be the default, first should be optional // see https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653 @Import({HttpClientConfiguration.class, OkHttpRibbonConfiguration.class, RestClientRibbonConfiguration.class, HttpClientRibbonConfiguration.class}) public class RibbonClientConfiguration { public static final int DEFAULT_CONNECT_TIMEOUT = 1000; public static final int DEFAULT_READ_TIMEOUT = 1000; @RibbonClientName private String name = "client"; // TODO: maybe re-instate autowired load balancers: identified by name they could be // associated with ribbon clients @Autowired private PropertiesFactory propertiesFactory; @Bean @ConditionalOnMissingBean public IClientConfig ribbonClientConfig() { DefaultClientConfigImpl config = new DefaultClientConfigImpl(); config.loadProperties(this.name); config.set(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT); config.set(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT); return config; } //...... }
- 這裏設置默認的超時值,都是1000毫秒,設置在DefaultClientConfigImpl
AbstractLoadBalancingClient
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/support/AbstractLoadBalancingClient.java
public abstract class AbstractLoadBalancingClient<S extends ContextAwareRequest, T extends IResponse, D> extends AbstractLoadBalancerAwareClient<S, T> implements ServiceInstanceChooser { protected int connectTimeout; protected int readTimeout; //...... @Override public void initWithNiwsConfig(IClientConfig clientConfig) { super.initWithNiwsConfig(clientConfig); RibbonProperties ribbon = RibbonProperties.from(clientConfig); this.connectTimeout = ribbon.connectTimeout(DEFAULT_CONNECT_TIMEOUT); this.readTimeout = ribbon.readTimeout(DEFAULT_READ_TIMEOUT); this.secure = ribbon.isSecure(); this.followRedirects = ribbon.isFollowRedirects(); this.okToRetryOnAllOperations = ribbon.isOkToRetryOnAllOperations(); } //...... }
- 這裏從RibbonProperties讀取超時參數,而後放到類成員變量connectTimeout及readTimeout
- RibbonProperties就最後是從IClientConfig讀取
RibbonLoadBalancingHttpClient
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/apache/RibbonLoadBalancingHttpClient.java
// TODO: rename (ie new class that extends this in Dalston) to ApacheHttpLoadBalancingClient public class RibbonLoadBalancingHttpClient extends AbstractLoadBalancingClient<RibbonApacheHttpRequest, RibbonApacheHttpResponse, CloseableHttpClient> { //...... @Override public RibbonApacheHttpResponse execute(RibbonApacheHttpRequest request, final IClientConfig configOverride) throws Exception { IClientConfig config = configOverride != null ? configOverride : this.config; RibbonProperties ribbon = RibbonProperties.from(config); RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(ribbon.connectTimeout(this.connectTimeout)) .setSocketTimeout(ribbon.readTimeout(this.readTimeout)) .setRedirectsEnabled(ribbon.isFollowRedirects(this.followRedirects)) .build(); request = getSecureRequest(request, configOverride); final HttpUriRequest httpUriRequest = request.toRequest(requestConfig); final HttpResponse httpResponse = this.delegate.execute(httpUriRequest); return new RibbonApacheHttpResponse(httpResponse, httpUriRequest.getURI()); } //...... }
- 這裏execute方法從IClientConfig構造RequestConfig,會設置connectTimeout及socketTimeout
- 若是configOverride爲null,則使用抽象類的默認配置
OkHttpLoadBalancingClient
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpLoadBalancingClient.java
public class OkHttpLoadBalancingClient extends AbstractLoadBalancingClient<OkHttpRibbonRequest, OkHttpRibbonResponse, OkHttpClient> { //...... @Override public OkHttpRibbonResponse execute(OkHttpRibbonRequest ribbonRequest, final IClientConfig configOverride) throws Exception { boolean secure = isSecure(configOverride); if (secure) { final URI secureUri = UriComponentsBuilder.fromUri(ribbonRequest.getUri()) .scheme("https").build().toUri(); ribbonRequest = ribbonRequest.withNewUri(secureUri); } OkHttpClient httpClient = getOkHttpClient(configOverride, secure); final Request request = ribbonRequest.toRequest(); Response response = httpClient.newCall(request).execute(); return new OkHttpRibbonResponse(response, ribbonRequest.getUri()); } OkHttpClient getOkHttpClient(IClientConfig configOverride, boolean secure) { IClientConfig config = configOverride != null ? configOverride : this.config; RibbonProperties ribbon = RibbonProperties.from(config); OkHttpClient.Builder builder = this.delegate.newBuilder() .connectTimeout(ribbon.connectTimeout(this.connectTimeout), TimeUnit.MILLISECONDS) .readTimeout(ribbon.readTimeout(this.readTimeout), TimeUnit.MILLISECONDS) .followRedirects(ribbon.isFollowRedirects(this.followRedirects)); if (secure) { builder.followSslRedirects(ribbon.isFollowRedirects(this.followRedirects)); } return builder.build(); } //...... }
- 這裏是經過configOverride或默認的config來構建指定超時參數的OkHttpClient
- 相比較於apache httpclient經過request config來設置超時時間,OkHttpClient是經過client來設置的,這樣可能存在一個問題,就是OkHttpClient無法用單例,每次都得new一個
clientConfig傳遞
RibbonHttpRequest
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonHttpRequest.java
public class RibbonHttpRequest extends AbstractClientHttpRequest { //...... @Override protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException { try { addHeaders(headers); if (outputStream != null) { outputStream.close(); builder.entity(outputStream.toByteArray()); } HttpRequest request = builder.build(); HttpResponse response = client.executeWithLoadBalancer(request, config); return new RibbonHttpResponse(response); } catch (Exception e) { throw new IOException(e); } } //...... }
- 這裏client.executeWithLoadBalancer(request, config)使用的是RibbonHttpRequest的config配置
RibbonClientHttpRequestFactory
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonClientHttpRequestFactory.java
public class RibbonClientHttpRequestFactory implements ClientHttpRequestFactory { private final SpringClientFactory clientFactory; public RibbonClientHttpRequestFactory(SpringClientFactory clientFactory) { this.clientFactory = clientFactory; } @Override @SuppressWarnings("deprecation") public ClientHttpRequest createRequest(URI originalUri, HttpMethod httpMethod) throws IOException { String serviceId = originalUri.getHost(); if (serviceId == null) { throw new IOException( "Invalid hostname in the URI [" + originalUri.toASCIIString() + "]"); } IClientConfig clientConfig = this.clientFactory.getClientConfig(serviceId); RestClient client = this.clientFactory.getClient(serviceId, RestClient.class); HttpRequest.Verb verb = HttpRequest.Verb.valueOf(httpMethod.name()); return new RibbonHttpRequest(originalUri, verb, client, clientConfig); } }
- ClientHttpRequest是經過RibbonClientHttpRequestFactory這個工廠建立的
- clientConfig是RibbonClientHttpRequestFactory這個工廠根據serviceId獲取的,默認是DefaultClientConfigImpl,從配置文件讀取,serviceId本身的個性化配置參數會覆蓋默認值,讀取不到的就是默認的參數。
小結
spring cloud netflix的ribbon,其超時時間配置有ReadTimeout以及ConnectTimeout,分別是設置的socketTimeout以及connectTimeout,建立請求的時候,會讀取指定配置,沒有的話,就取默認的配置,設置超時時間。
doc
做者:go4it
連接:https://www.jianshu.com/p/eb63697adca8
來源:簡書
簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
Spring cloud 微服務架構之Ribbon/Fegin鏈接超時ReadTimeout問題
問題描述:
近期用Spring cloud 開發微服務架構時候,在服務與服務之間調用調試代碼時候,出現連接超時。
錯誤信息:
Read timed out executing GET http://service-batch/batchmanagement/datatransfer/querybyplanid?planid=PL00000102。
發生緣由:
用IDE開發Debug模式調試代碼時候,在處理該服務與其餘服務調用時候,因爲debug模式調試代碼花費一些時間,結果出現Fegin 鏈接超時問題。
解決辦法:
在application.properice屬性文件中添加
#Fegin 鏈接超時
ribbon.ReadTimeout=60000
ribbon.ConnectTimeout=60000
ribbon.MaxAutoRetries=0
ribbon.MaxAutoRetriesNextServer=1
技術講解:
微服務間調用其實走的是http請求,debug了一下默認的ReadTimeout時間爲5s,ConnectTimeout時間爲2s,
我使用的是Fegin進行微服務間調用,底層用的仍是Ribbon。
---------------------
做者:喜歡健身的程序員
來源:CSDN
原文:https://blog.csdn.net/m0_38016299/article/details/78391461
版權聲明:本文爲博主原創文章,轉載請附上博文連接!
springcloud2.x 設置feign、ribbon和hystrix的超時問題(配置文件)
#ribbon的超時時間 (通常狀況下 都是 ribbon 的超時時間(<)hystrix的超時時間(由於涉及到ribbon的重試機制) )
ribbon:
ReadTimeout: 6000
ConnectTimeout: 6000
MaxAutoRetries: 1 #同一臺實例最大重試次數,不包括首次調用
MaxAutoRetriesNextServer: 1 #重試負載均衡其餘的實例最大重試次數,不包括首次調用
OkToRetryOnAllOperations: false #是否全部操做都重試
#hystrix的超時時間 (通常狀況下 都是 ribbon 的超時時間(<)hystrix的超時時間(由於涉及到ribbon的重試機制) )
#這種寫法是把默認的超時時間改爲8秒,而把另一個自定義的 Feign 客戶端中的某方法超時時間定成10秒(格式是類名#方法名()
hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 8000
"***FeignClient#***method()": #格式是 類名#方法名()
execution:
isolation:
thread:
timeoutInMilliseconds: 10000
---------------------
做者:執意丨
來源:CSDN
原文:https://blog.csdn.net/ab52262879/article/details/84100596
版權聲明:本文爲博主原創文章,轉載請附上博文連接!
Zuul、Ribbon、Feign、Hystrix使用時的超時時間(timeout)設置問題
寫在前面
由於測試 Feign + Hystrix 搭配模式下的降級(fallback)超時時間自定義問題,算是踩了個坑,而後就順便查+測試了下 Zuul、Ribbon + Hystrix 模式下分別怎麼設置
測試這些東西費了很多力氣,由於這幾個模塊要麼搭配使用、要麼有內部依賴別的模塊、要麼對其餘模塊作了封裝,這個配置項就變得千奇百怪,並且網上的東西,一直以爲有個很"嚴重"的問題,就是版本不明,版本號都不同,解決方案或者說配置方式可能徹底不一樣,而不少的文章中也沒有說起他們用的是哪一個版本,搞得我是暈頭轉向(畢竟我不是這些服務模塊的開發者或者長期的使用者,不是很是瞭解這些東西的版本演進過程)
因此這裏是查了很多的資料,測試經過了一些方案,也算是本身總結記錄一下
注意!
這裏都是基於有 Eureka 作服務中心爲前提的
工具
Eclipse Oxygen
Spring Boot 2.0.5.RELEASE
Spring Cloud Finchley.SR1
Eureka 1.9.3
Zuul 1.3.1
Ribbon 2.2.5
Feign 9.5.1
Hystrix 1.5.12
Feign + Hystrix
這個栗子的源碼看這裏
0. 默認基本配置
最基本的配置,是 Hystrix 本身的一長串配置:hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds,但在 Feign 模塊中,單獨設置這個超時時間不行,還要額外設置 Ribbon 的超時時間,好比:
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 5000 ribbon: ReadTimeout: 5000 ConnectTimeout: 5000
關於 Hystrix 的配置,這裏有官方的說明:
能夠看到實例配置中,替代 default 的,是 HystrixCommandKey,這個值在下面會說到
1. 不一樣實例分別配置
若是更進一步,想把超時時間細分到不一樣的 service 實例上也能夠實現,好比:
@FeignClient( value = "hello-service", fallback = MyFeignClientHystric.class) public interface MyFeignClient { @RequestMapping("/hello") String sayHelloByFeign(); @RequestMapping("/why") String sayWhyByFeign(); }
hystrix: command: "MyFeignClient#sayWhyByFeign()": execution: isolation: thread: timeoutInMilliseconds: 9000 default: execution: isolation: thread: timeoutInMilliseconds: 2000 ribbon: ReadTimeout: 5000 ConnectTimeout: 5000
這種寫法是把默認的超時時間改爲2秒,而把另一個自定義的 Feign 客戶端中的某方法超時時間定成9秒(格式是類名#方法名(),若是方法有入參,也要把入參的類型拼上),這裏的 MyFeignClient#sayWhyByFeign() 就表明了上面說到的 commandKey,而這種寫法,則是 Feign 模塊中特殊的:
ryanjbaxter commented on 26 Jul
If you had a Feign client called MyClient and it had a method called search that took in a single String parameter than you would use the following property
hystrix.command.MyClient#search(String).execution.isolation.thread.timeoutInMilliseconds
看 issue 裏 Spring Cloud 的官方人員的說法,這種格式是他們進行的封裝,因此咱們要設置,就只能這麼寫
Ribbon + Hystrix
這個栗子的源碼看這裏
0. 默認基本配置
在使用 Ribbon 時,只須要配置 Hystrix 的超時時間就能夠生效,不須要額外配置 Ribbon 的超時時間,好比:
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 9000
1. 不一樣實例分別配置
想細分服務超時時間時:
若是是同一個服務實例下的不一樣接口,想使用不一樣的超時時間,能夠把 @HystrixCommand 中的 commandKey 定義成不一樣的值,而後在 yml 中分別設置
@HystrixCommand( commandKey = "helloService-sayHello", fallbackMethod = "sayHelloDefault") public String sayHelloByRibbon() { return restTemplate.getForObject("http://HELLO-SERVICE/hello", String.class); } public String sayHelloDefault() { return "hello service error, this is default say hello method"; } @HystrixCommand( commandKey = "helloService-sayWhy", fallbackMethod = "sayWhyDefault") public String sayWhyByRibbon() { return restTemplate.getForObject("http://HELLO-SERVICE/why", String.class); } public String sayWhyDefault() { return "hello service error, this is default say why method"; }
hystrix: command: helloService-sayWhy: execution: isolation: thread: timeoutInMilliseconds: 5000 default: execution: isolation: thread: timeoutInMilliseconds: 1500
若是想統一設置同一個服務實例中各方法的超時時間,經測試,能夠把不一樣方法上的 commandKey 設置成相同的值,這樣在 yml 中對該 key 作超時配置就能同時生效了:
@HystrixCommand( commandKey = "helloService", fallbackMethod = "sayHelloDefault") public String sayHelloByRibbon() { return restTemplate.getForObject("http://HELLO-SERVICE/hello", String.class); } public String sayHelloDefault() { return "hello service error, this is default say hello method"; } @HystrixCommand( commandKey = "helloService", fallbackMethod = "sayWhyDefault") public String sayWhyByRibbon() { return restTemplate.getForObject("http://HELLO-SERVICE/why", String.class); } public String sayWhyDefault() { return "hello service error, this is default say why method"; }
hystrix: command: helloService: execution: isolation: thread: timeoutInMilliseconds: 5000 default: execution: isolation: thread: timeoutInMilliseconds: 1000
Zuul
這個栗子的源碼看這裏,Zuul 中的降級是用了 FallbackProvider,簡單的使用能夠看我源碼中的 HelloFallbackProvider.java 和 HiFallbackProvider.java,我也是參考了官方的文檔說明和例子
0. 默認基本配置
zuul 中配置超時時間,據官方的介紹,分兩種狀況:
用 serviceId 進行路由時,使用 ribbon.ReadTimeout 和 ribbon.SocketTimeout 設置
用指定 url 進行路由時,使用 zuul.host.connect-timeout-millis 和 zuul.host.socket-timeout-millis 設置
由於個人代碼中是用 serviceId 的方式,因此參考了第一種配置,好比:
zuul: routes: helloService: path: /hello-service/** serviceId: hello-service hiService: path: /hi-service/** serviceId: hi-service ribbon: ConnectTimeout: 5000 ReadTimeout: 5000
1. 不一樣實例分別配置
Ribbon 的配置項還能夠加一個 ClientName 爲前綴(這個方法的出處在官方的 wiki),區分不一樣客戶端下的配置,這個 ClientName 我是直接用了 serviceId,測試了正常,但還能夠用或者說應該用什麼值,這個我尚未找到官方的說明。。
zuul: routes: helloService: path: /hello-service/** serviceId: hello-service hiService: path: /hi-service/** serviceId: hi-service hello-service: ribbon: ConnectTimeout: 5000 ReadTimeout: 5000 hi-service: ribbon: ConnectTimeout: 500 ReadTimeout: 500 hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 3000
另外還作了測試,若是同時配置了 Ribbon 和 Hystrix 的超時時間,則以最小的爲準,好比上述的配置中,若是 hi-service 的接口調用超過了 0.5 秒,則就會觸發超時
總結
目前的學習和測試結果來看:
單純的 Ribbon + Hystrix 搭配使用時,配置是最靈活的,二者沒有相互干涉,能夠自由定義 commandKey 來實現超時時間的配置
Feign + Hystrix 搭配時,因爲 Feign 封裝了 Hystrix 所需的 commandKey,咱們不能自定義,因此同一個 FeignClient 下的服務接口不能方便的統一配置,若是有相應的業務需求,或許只能對每一個特殊的接口方法作獨立的超時配置(找到新方法的話再回來更新)