Spring Cloud學習筆記(九)-閘道器Zuul使用熔斷器和過濾器
阿新 • • 發佈:2019-02-01
說明:本文僅作為本人學習<<深入理解Spring Cloud與微服務構建>>一書的學習筆記,所有程式碼案例及文字描述均參考該書,不足之處,請留言指正,不勝感激.
一.在Zuul上配置熔斷器
上一篇提到zuul的起步依賴集成了ribbon和hystrix,接下來我們來看看如何在閘道器上實現熔斷功能.
首先我們需要了解在Zuul中實現熔斷功能需要實現ZuulFallbackProvider的介面.實現該介面有兩個方法,一個是getRoute()方法,用於指定熔斷功能應用於哪個路由服務;另一個方法fallbackResponse()為進入熔斷功能時執行的邏輯.具體實現可以參看如下程式碼:
/**
* 閘道器熔斷配置
*
* @author zhyu
* @version v1.0
* @date 2018年07月03日 19:54:28
*/
@Component
public class MyZuulFallbackProvider implements ZuulFallbackProvider {
@Override
public String getRoute() {
//實現對producer-server服務的熔斷
return "producer-server";
//return "*"; 實現對所有的路由服務的熔斷
}
@Override
public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return 200;
}
@Override
public String getStatusText() throws IOException {
return "OK";
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("{\"status\":500,\"message\":\"sorry,the system goes to sleep,please try again later!\"}".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
接著我們啟動eureka-server,zuul-server服務,不啟動producer-server服務,然後通過閘道器訪問producer-server的介面,結果如下:
可見,熔斷器配置起了作用,如果我們將getRoute()方法的返回改為”*”,那麼將對所有的路由服務都加熔斷功能.
二.在Zuul中使用過濾器
在Zuul中自定義過濾器很簡單,只需要繼承ZuulFilter,並實現它的抽象方法就好,最後將其注入到IoC容器,如下:
package com.example.zuulserver.Filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* 自定義過濾器
* 實現起來很簡單,只需要繼承ZuulFilter,並實現它的抽象方法
* @author zhyu
* @version v1.0
* @date 2018年07月05日 19:11:49
*/
@Component
public class MyZuulFilter extends ZuulFilter {
/**
* 返回過濾器的型別
* @return
*/
@Override
public String filterType() {
/**
* Zuul有一下四種過濾器
* "pre":是在請求路由到具體的服務之前執行,這種型別的過濾器可以做安全校驗,例如身份校驗,引數校驗等
* "routing":它用於將請求路由到具體的微服務例項,在預設情況下,它使用Http Client進行網路請求
* "post":它是在請求已被路由到微服務後執行,一般情況下,用作收集統計資訊,指標,以及將響應傳輸到客戶端
* "error":它是在其他過濾器發生錯誤時執行
*/
return "pre";
}
/**
* 過濾順序,值越小,越早執行該過濾器
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* 表示該過濾器是否過濾邏輯,如果是ture,則執行run()方法;如果是false,則不執行run()方法.
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 具體的過濾邏輯
* 本例中,檢查請求的引數中是否傳了token這個引數,如果沒傳,則請求不被路由到具體的服務例項,
* 直接返回響應,狀態碼為401
* @return
*/
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String token = request.getParameter("token");
if(token == null){
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try{
ctx.getResponse().getWriter().write("token is empty");
}catch(Exception e){
}
}
return null;
}
}
然後我們啟動服務,當我們不帶token時,瀏覽器顯示如下:
這次我們帶上token,再訪問: