05.Spring Cloud 之 Zuul

1. 概述

1.1 Zuul 是什麼
  • Zuul 包含了對請求的路由和過濾兩個最主要的功能

  • 其中路由功能負責將外部請求轉發到具體的微服務實例上,是實現外部訪問統一入口的基礎而過濾器功能則負責對請求的處理過程進行干預,是實現請求校驗、服務聚合等功能的基礎。

  • Zuul 和 Eureka 進行整合,將 Zuul 自身註冊爲 Eureka 服務治理下的應用,同時從 Eureka 中獲得其他微服務的消息,也即以後的訪問微服務都是通過 Zuul 跳轉後獲得。

  • Zuul 服務最終還是會註冊進 Eureka

2. Zuul 使用

  • 項目已上傳至 https://github.com/masteryourself/study-spring-cloud.git
2.1 配置文件
1. pom.xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
2. application.properties
# 此實例註冊到eureka服務端的 name
spring.application.name=masteryourself-zuul
# 端口號
server.port=9001

# 與 eureka server 交互的地址
eureka.client.service-url.defaultZone=http://masteryourself-eureka-7001.com:7001/eureka
# 此實例註冊到 eureka 服務端的唯一的實例 ID
eureka.instance.instance-id=masteryourself-zuul-9001
# 是否顯示 IP 地址
eureka.instance.prefer-ip-address=true
# eureka 客戶需要多長時間發送心跳給 eureka 服務器,表明它仍然活着,默認爲 30 秒
eureka.instance.lease-renewal-interval-in-seconds=10
# eureka 服務器在接收到實例的最後一次發出的心跳後,需要等待多久纔可以將此實例刪除,默認爲 90 秒
eureka.instance.lease-expiration-duration-in-seconds=30

# 請求連接的超時時間,默認的時間爲 1000 ms
ribbon.ConnectTimeout=5000
# 請求處理的超時時間
ribbon.ReadTimeout=5000

# 命令執行超時時間,默認1000 ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000

# 配置 user 微服務地址的路由信息,將 /user 開頭的請求轉發到 MASTERYOURSELF-USER 微服務上
zuul.routes.user.service-id=MASTERYOURSELF-USER
zuul.routes.user.path=/user/**
# 禁用微服務名方式調用
zuul.ignored-services=MASTERYOURSELF-USER
# http 超時時間
zuul.host.connect-timeout-millis=10000
# socket 超時時間
zuul.host.socket-timeout-millis=10000
2.2 代碼
1. ZuulApplication9001
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulApplication9001 {

    public static void main(String [] args){
        SpringApplication.run(ZuulApplication9001.class, args);
    }

}
2.3 效果演示
  • 通過 zuul 的路由轉發,我們可以直接用 zuul 來訪問微服務,比如說之前的地址是 http://192.168.20.1:5001/doOrderByFeignAndHystrix ,那麼通過 zuul 訪問地址就變成了 http://192.168.20.1:9001/user/doOrderByFeignAndHystrix

在這裏插入圖片描述

3. Zuul 使用自定義過濾器

  • 過濾器(filter)是 zuul 的核心組件 zuul 大部分功能都是通過過濾器來實現的。

  • zuul 中定義了 4 種標準過濾器類型,這些過濾器類型對應於請求的典型生命週期。

    • PRE:這種過濾器在請求被路由之前調用。可利用這種過濾器實現身份驗證、在 集羣中選擇請求的微服務、記錄調試信息等。

    • ROUTING:這種過濾器將請求路由到微服務。這種過濾器用於構建發送給微服 務的請求,並使用 Apache HttpCIient 或 Netfilx Ribbon 請求微服務

    • POST:這種過濾器在路由到微服務以後執行。這種過濾器可用來爲響應添加標準 的 HTTP Header、收集統計信息和指標、將響應從微服務發送給客戶端等。

    • ERROR:在其他階段發生錯誤時執行該過濾器。

3.1 代碼
1. LogFilter
@Component
public class LogFilter extends ZuulFilter {

    private AtomicInteger count = new AtomicInteger(0);

    /**
     * 返回過濾器的類型。有 pre、 route、 post、 error 等幾種取值,分別對應上文的幾種過濾器
     *
     * @return
     */
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    /**
     * 返回一個 int 值來指定過濾器的執行順序,不同的過濾器允許返回相同的數字
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER;
    }

    /**
     * 返回一個 boolean 值來判斷該過濾器是否要執行, true 表示執行, false 表示不執行
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        if (count.getAndIncrement() % 3 == 0) {
            // 不會繼續往下執行 不會調用服務接口了 網關直接響應給客戶了
            currentContext.setSendZuulResponse(false);
            currentContext.setResponseBody("{\"code\": \"400\",\"mg\": \"you were denied\"}");
            currentContext.setResponseStatusCode(401);
            return null;
        }
        HttpServletRequest request = currentContext.getRequest();
        String remoteAddr = request.getRemoteAddr();
        System.out.println("訪問者IP:【" + remoteAddr + "】訪問地址:【" + request.getRequestURI() + "】");
        return null;
    }
}
3.2 禁用 Filter
  • 禁用 zuul 過濾器,Spring Cloud 默認爲 Zuul 編寫並啓用了一些過濾器,例如 DebugFilter、 FormBodyWrapperFilter 等,這些過濾器都存放在 spring-cloud-netflix-core 這個 jar 包 裏,一些場景下,想要禁用掉部分過濾器,該怎麼辦呢? 只需在 application.properties 裏設置 zuul...disable=true,例如禁用上面的 LogFilter:zuul.LogFilter.pre.disable=true

4. Zuul 容錯與回退

4.1 代碼
1. MyFallbackProvider
@Component
public class MyFallbackProvider implements FallbackProvider {

    @Override
    public String getRoute() {
        //指定爲哪個微服務提供回退(這裏寫微服務名 寫 * 代表所有微服務)
        return "MASTERYOURSELF-USER";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        //這裏可以判斷根據不同的異常來做不同的處理, 也可以不判斷
        //完了之後調用response方法並根據異常類型傳入HttpStatus
        if (cause instanceof HystrixTimeoutException) {
            return response(HttpStatus.GATEWAY_TIMEOUT);
        } else {
            return response(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private ClientHttpResponse response(final HttpStatus status) {
        //這裏返回一個ClientHttpResponse對象 並實現其中的方法,關於回退邏輯的詳細,便在下面的方法中
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                //返回一個HttpStatus對象 這個對象是個枚舉對象, 裏面包含了一個status code 和reasonPhrase信息
                return status;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                //返回status的code  比如 404,500等
                return status.value();
            }

            @Override
            public String getStatusText() throws IOException {
                //返回一個HttpStatus對象的reasonPhrase信息
                return status.getReasonPhrase();
            }

            @Override
            public void close() {
                //close的時候調用的方法, 講白了就是當降級信息全部響應完了之後調用的方法
            }

            @Override
            public InputStream getBody() throws IOException {
                //吧降級信息響應回前端
                return new ByteArrayInputStream("降級信息".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                //需要對響應報頭設置的話可以在此設置
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }

}
4.2 效果展示
  • 把 masteryourself-user 微服務關掉,然後調用 http://192.168.20.1:9001/user/doOrderByFeignAndHystrix ,可看到瀏覽器顯示如下內容

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章