1. 程式人生 > >status":500,"error":"Internal Server Error" “message”:”GENERAL”

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