SpringCloud 基礎教程(十)-Zuul 服務網關

個人博客:程序員笑笑生,歡迎瀏覽博客!,搜索博客可添加微信公衆號。前端

   上一章 SpringCloud 基礎教程(九)-Hystrix服務監控(下)當中,咱們深刻了解Hystrix的服務監控。實現了分佈式環境下,監控多個服務的信息,本章節將探索微服務的另外一個組件,網關。java

前言

 什麼是Zuul,Zuul能夠說是一個大門,全部的來自前端的請求,通過Zuul時,可以實現動態路由轉發,監控、安全的等邊緣服務應用程序。好比能夠做爲統一資源的訪問入口、負載均衡等。爲何須要須要這樣的一個組件呢?Netflix開發這樣的產品是考慮到了如下的緣由:api的多樣性和訪問量大可以致使不少的問題,沒法預警。因此咱們須要這樣的系統組件應付這些狀況。程序員

1、Zuul 提供的功能

  • 身份認證和安全-能夠識別訪問資源的每個請求,拒毫不知足的請求spring

  • 洞察和監控,跟蹤有意義的數據並統計,以便生成有意義的生產視圖apache

  • 動態路由,根據須要將請求動態的路由到不一樣的後端集羣,(最主要的功能)json

  • 壓力測試,逐漸增長集羣的流量,評估性能後端

  • 限流,爲每個請求分配容量,並丟棄超過限制的請求api

  • 處理靜態響應,直接在邊緣處構建響應,而不是轉發給內部集羣安全

2、Zuul 快速入門

 新建Maven項目,引入Zuul的依賴和Eureka的依賴,咱們轉發請求是須要從Eureka中獲取服務的信息。Zuul的依賴默認集成了hystrix和ribbon微信

<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>

 新建GateWayApplication啓動類,添加@EnableZuulProxy註解,@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker三個註解:表示是一個SpringBoot程序,啓動服務發現功能和服務熔斷功能,

import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringCloudApplication
@EnableZuulProxy
public class GateWayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GateWayApplication.class);
    }
}

 固然咱們可使用@SpringCloudApplication一個註解,從源碼上能夠看出@SpringCloudApplication包含了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker三個註解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

 配置applicaiton.yml,配置端口號,配置鏈接Eureka的url,配置zuul相關配置:

server:
  port: 9876
  
eureka:
  instance:
    instance-id: gateway1
    hostname: eureka7001.com  #服務端的實例名稱
  client:
    service-url:
       defaultZone: http://eureka7001.com:7001/eureka/
zuul:
  ignored-services: "*"
  routes:
     server-provider:
        path:   /server-provider/*

 在routes下有如下幾種的配置

第一種:

zuul:
  ignored-services: "*"
  routes:
     server-provider:   #配置服註冊在Eureka的服務名稱,指的是服務中spring.application.name的配置
         #將/server-provider/開頭的都轉發到服務名爲server-provider的服務上,
      path:   /server-provider/*

第二種:

zuul:
  ignored-services: "*"
  routes:
     server-a:   #名稱隨便起
         #將/server-provider/開頭的都轉發到服務名爲server-provider的服務上,
      path:   /server-provider/*  
       #配置服註冊在Eureka的服務名稱,指的是服務中spring.application.name的配置
      serviceId:  server-provider

第三種:

zuul:
  ignored-services: "*"
  routes:
     server-b:   #名稱隨便起
         #將/server-provider/開頭的都轉發到url爲 http://localhost:5168/  #的服務上,
      path:   /server-provider/*  
       #配置服註冊在Eureka的服務名稱,指的是服務中spring.application.name的配置
      url:  http://localhost:5168/  #不經過Eureka

 接下來,咱們啓動Eureka中心,2個服務提供者: server-provider,啓動Zuul網關服務,查看Eureka監控頁面:

file

而後咱們經過如下的URL訪問:http://localhost:9876/server-provider/sayHello?name=1 ,能夠看到咱們經過了Zuul網關實現了路由,服務提供方也能返回請求的結果,並實現了負載均衡:

file

3、Zuul過濾器

3.1 過濾器簡介

 上文咱們實現了簡單的路由轉發,除了路由轉發,在實際的企業應用中,須要結合不一樣的需求實現不一樣的功能,Zuul能夠經過過濾器來實現接口權限驗證、限流、統計等。Zuul定義了4種不一樣的過濾器類型:

file

咱們能夠理解爲在請求的不一樣時間分別調用:

  • pre:這種過濾器在請求被轉發以前調用,通常用來實現身份驗證等
  • routing:這種路由是用來路由到不一樣的後端服務的,底層可使用httpclient或者ribbon請求微服務
  • post:當請求轉發到微服務之後,會調用當前類型的過濾器。一般用來爲響應天啊及標椎的HTTP Header、收集統計信息,等
  • error:當發生錯誤是執行的過濾器

3.2 自定義過濾器實現Token驗證

 自定義過濾器須要集成com.netflix.zuul.ZuulFilter類,並實現其抽象的方法達到所須要的目的,這裏咱們簡單的實現經過Token的驗證:

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *驗證token
 */
@Component
public class TokenFilter extends ZuulFilter {
    private Logger logger=LoggerFactory.getLogger(TokenFilter.class);
    /**
     * 返回過濾器類型   "pre" / "route" / "post"  / 「 error」
     *
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }
    /**
     * 過濾器的順序,不一樣的過濾器順序能夠相同
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 判斷是否要執行  true表示執行 run方法
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 當 shouldFilter() 返回true時候
     * 執行run中的具體邏輯、返回值在當前的版本中沒有意義
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
         RequestContext context = RequestContext.getCurrentContext();
         HttpServletRequest request = context.getRequest();
         HttpServletResponse response = context.getResponse();
        //獲取header中的token
        String token = request.getHeader("token");
        JSONObject jsonObject=new JSONObject();
      //若是token爲空,設置返回狀態爲401,返回json的信息
        if (StringUtils.isEmpty(token)) {
            context.setSendZuulResponse(false);
            context.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            jsonObject.put("code",401);
            jsonObject.put("msg","UNAUTHORIZED");
            context.setResponseBody(jsonObject.toJSONString());
            logger.info("msg:{}",jsonObject);
        } else {
            //不然執行請求
            logger.info("msg:{}","ok");
            return null;
        }
        return null;
    }
}
  • filterType:返回過濾器類型 "pre" / "route" / "post" / 「 error」
  • filterOrder:過濾器的順序
  • shouldFilter:爲true時候,執行run方法
  • run:具體的邏輯,在方法中咱們能夠獲取到RequestContext對象,經過該對象獲取請求頭的信息,並設置返回信息

 接下來,咱們啓動相應的服務,併發送請求,若是沒有token,則返回以下的信息:

file

這樣咱們就能實現一個簡單的經過Token的過濾驗證了。

 對於啓用/禁用過濾器,咱們不可能去修改過濾器的代碼,咱們能夠經過配置文件配置進行過濾的控制,在applicaiton.yml中咱們能夠這樣配置:

zuul:
   #過濾器的名稱
  TokenFilter:
     pre :
     #true表示禁用
       disable : true

3.3 請求重試

 當Zuul轉發失敗時,能夠經過配置使Ribbon的客戶端進行重試,默認是false

zuul:
  retryable: true

3.4 敏感Header的過濾

 在請求的轉發過程當中,默認會轉發HTTP的Header信息,有時候咱們不但願這些信息被轉發,好比Cookie,token,咱們能夠經過sensitiveHeaders配置,多項之間用逗號隔開:

zuul:
  sensitive-headers: Cookie,token

3.5 設置統一的前綴

zuul:
  prefix: /api

4、總結

 本章分享了Zuul組件在微服務架構中擔任的角色,並經過示例的方式實現了經過Token簡單的過濾請求,固然Zuul的功能不知於此,Zuul經歷過各大互聯網公司的檢驗,可以和Spring Cloud生態完美的融合,是微服務不可或缺的一個關鍵節點。

----END----

以就是本期的分享,你還能夠關注公衆號: 程序員笑笑生,關注更多精彩內容!

file

file

SpringCloud基礎教程(一)-微服務與SpringCloud

SpringCloud基礎教程(二)-服務發現 Eureka

SpringCloud基礎教程(三)-Eureka進階

SpringCloud 基礎教程(四)-配置中心入門

SpringCloud基礎教程(五)-配置中心熱生效和高可用

SpringCloud 基礎教程(六)-負載均衡Ribbon

SpringCloud 基礎教程(七)-Feign聲明式服務調用

SpringCloud 基礎教程(八)-Hystrix熔斷器(上)

SpringCloud 基礎教程(九)-Hystrix服務監控(下)

SpringCloud 基礎教程(十)-Zull服務網關

更多精彩內容,請期待...

本文由博客一文多發平臺 OpenWrite 發佈!

個人博客地址蘭陵笑笑生,歡迎瀏覽!

相關文章
相關標籤/搜索