status":500,"error":"Internal Server Error" “message”:”GENERAL”
通過zuul閘道器請求服務有時候個別請求時候"timestamp":“2018-09-07 11:45:38”,“status”:500,“error”:“Internal Server Error” “message”:”GENERAL”
之前這個一開始問題分析是閘道器超時配置時間太短的原因,隨後開始調大閘道器時間:
閘道器的三種時間配置 由於zuul集成了hystrix和ribbon, 所以也就包含了這幾中的響應時間,ribbon當使用serviceId的方式配置使用這個,當服務使用url 的方式的話使用下面的zuul.host的配置方式,另外hystrix的時間必須大於ribbon所需要的時間和因為下面還包含重連時間(一次連線zuul失敗的二次重連可以是同一個例項也可以是下一個例項)
ribbon: ReadTimeout: 5000 ConnectTimeout: 5000 MaxAutoRetries: 0 MaxAutoRetriesNextServer: 1 hystrix: command: default: execution: timeout: enabled: false #Edgware.RELEASE中,timeoutInMilliseconds不起作用,暫時關掉 isolation: thread: timeoutInMilliseconds: 10000 zuul: host: socket-timeout-millis: 10000 connect-timeout-millis: 10000 上面的配置不成又換了 下面的配置 zuul重連機制好需要如下jar <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency> #retry #該引數用來開啟重試機制 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
我更新zuul配置後發現還是會出現同樣的問題,隨後找到資料說是因為集成了hystrix但是找不到可回退的方法fallback所以又查看了配置可回退的fallback功能功能通過繼承zuulFallbackProvider或者FallbackProvider 這裡還得注意SpringCloud版本的區別 並且下面註冊的bean能夠被掃描到
Dalston及更低版本
/** * 自定義Zuul回退機制處理器。 * * Provides fallback when a failure occurs on a route 英文意思就是說提供一個回退機制當路由後面的服務發生故障時。*/ @Component public class SrpingCLoudFallBack implements FallbackProvider { @Override public String getRoute() { // 表明是為哪個微服務提供回退,*表示為所有微服務提供回退 return "*"; } @Override public ClientHttpResponse fallbackResponse(Throwable cause) { if (cause instanceof HystrixTimeoutException) { return response(HttpStatus.GATEWAY_TIMEOUT); } else { return this.fallbackResponse(); } } @Override public ClientHttpResponse fallbackResponse() { return this.response(HttpStatus.INTERNAL_SERVER_ERROR); } private ClientHttpResponse response(final HttpStatus status) { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return status; } @Override public int getRawStatusCode() throws IOException { return status.value(); } @Override public String getStatusText() throws IOException { return status.getReasonPhrase(); } @Override public void close() { } @Override public InputStream getBody() throws IOException { /*返回json格式資料*/ com.alibaba.fastjson.JSONObject r=new com.alibaba.fastjson.JSONObject(); r.put("state", "501"); r.put("msg", "service is unavailable,請求失敗"); return new ByteArrayInputStream(r.toJSONString().getBytes("UTF-8")); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } }; } }
Edgware及更高版本
@Component
public class MyFallbackProvider implements FallbackProvider {
@Override
public String getRoute() {
// 表明是為哪個微服務提供回退,*表示為所有微服務提供回退
return "*";
}
@Override
public ClientHttpResponse fallbackResponse(Throwable cause) {
if (cause instanceof HystrixTimeoutException) {
return response(HttpStatus.GATEWAY_TIMEOUT);
} else {
return this.fallbackResponse();
}
}
@Override
public ClientHttpResponse fallbackResponse() {
return this.response(HttpStatus.INTERNAL_SERVER_ERROR);
}
private ClientHttpResponse response(final HttpStatus status) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return status;
}
@Override
public int getRawStatusCode() throws IOException {
return status.value();
}
@Override
public String getStatusText() throws IOException {
return status.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("服務不可用,請稍後再試。".getBytes());
}
@Override
public HttpHeaders getHeaders() {
// headers設定
HttpHeaders headers = new HttpHeaders();
MediaType mt = new MediaType("application", "json", Charset.forName("UTF-8"));
headers.setContentType(mt);
return headers;
}
};
}
}
• Dalston及更低版本通過實現ZuulFallbackProvider 介面,從而實現回退;
• Edgware及更高版本通過實現FallbackProvider 介面,從而實現回退。
• 在Edgware中:• FallbackProvider是ZuulFallbackProvider的子介面。
• ZuulFallbackProvider已經被標註Deprecated ,很可能在未來的版本中被刪除。
• FallbackProvider介面比ZuulFallbackProvider多了一個ClientHttpResponse fallbackResponse(Throwable cause); 方法,使用該方法,可獲得造成回退的原因。
通過上面的實現以為現在可以解決問題了,但是悲哀的是還是報同樣錯誤,後來想關閉hystrix設定結果還是不成
hystrix.command.default.execution.timeout.enabled=true
看來是思路不對,後來查詢hystrix有兩種策略方式一種是THREAD 以及SEMAPHORE ,預設是 SEMAPHORE 我更改成了後者並且設定了訊號量大小,問題解決
http://www.itmuch.com/spring-cloud-sum/spring-cloud-concurrent/
最後配置
#開啟重連機制
spring.cloud.loadbalancer.retry.enabled=true
zuul.retryable=true
#zuul超時配置
#zuul.host.socket-timeout-millis=800000
#zuul.host.connect-timeout-millis=300000
#hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000000
##hystrix.command.default.execution.timeout.enabled=true
##hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000000
##ribbon.ReadTimeout=8000
##ribbon.ConnectTimeout=2000
##ribbon.OkToRetryOnAllOperations=true
##ribbon.MaxAutoRetries=3
##ribbon.MaxAutoRetriesNextServer=3
##ribbon.eureka.enabled=true
#hystrix.command.default.execution.timeout.enabled=true 這個報錯 404和正常請求交替
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=200000000000
feign.hystrix.enabled=true
ribbon.ReadTimeout=80000
ribbon.ConnectTimeout=50000
zuul.semaphore.max-semaphores=2000
ribbon.OkToRetryOnAllOperations=true
ribbon.MaxAutoRetries=3
ribbon.MaxAutoRetriesNextServer=3
ribbon.eureka.enabled=true
zuul.ribbon-isolation-strategy=semaphore
參考:
http://www.itmuch.com/spring-cloud-sum/spring-cloud-concurrent/
https://liangzl.com/get-article-detail-19335.html