Spring Cloud學習:04路由網關(Zuul)

1 Zuul介紹

經過前幾個核心組件,能夠構建一個簡略(不完善)的微服務架構:html

在該架構中,咱們的服務集羣包含:內部服務Service A和Service B,他們都會註冊與訂閱服務至Eureka Server,而Open Service是一個對外的服務,經過均衡負載公開至服務調用方。前端

當前架構存在的不足:java

  • 首先,破壞了服務無狀態特色。爲了保證對外服務的安全性,咱們須要實現對服務訪問的權限控制,而開放服務的權限控制機制將會貫穿並污染整個開放服務的業務邏輯,這會帶來的最直接問題是,破壞了服務集羣中REST API無狀態的特色。從具體開發和測試的角度來講,在工做中除了要考慮實際的業務邏輯以外,還須要額外可續對接口訪問的控制處理。
  • 其次,沒法直接複用既有接口。當咱們須要對一個即有的集羣內訪問接口,實現外部服務訪問時,咱們不得不經過在原有接口上增長校驗邏輯,或增長一個代理調用來實現權限控制,沒法直接複用原有的接口。

解決思路:laravel

須要將權限控制這樣的東西從咱們的服務單元中抽離出去,而最適合這些邏輯的地方就是處於對外訪問最前端的地方,咱們須要一個更強大一些的均衡負載器,也就是服務網關。git

服務網關是微服務架構中一個不可或缺的部分。經過服務網關統一貫外系統提供REST API的過程當中,除了具有服務路由、均衡負載功能以外,它還具有了權限控制等功能。Spring Cloud Netflix中的Zuul就擔任了這樣的一個角色,爲微服務架構提供了前門保護的做用,同時將權限控制這些較重的非業務邏輯內容遷移到服務路由層面,使得服務集羣主體可以具有更高的可複用性和可測試性。github

2 Zuul路由測試

2.1 基於以前工程,建立新模塊zuul-service,選擇Spring Initializr->Cloud Discovery->Eureka Discovery,並添加如下依賴:web

<dependencies>
   <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka</artifactId>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
   </dependency>
   <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-zuul</artifactId>
   </dependency>
   <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
</dependencies>

2.2 啓動類上添加@EnableZuulProxy開啓Zuul功能spring

@SpringBootApplication
@EnableZuulProxy
public class ZuulServiceApplication {

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

2.3 配置文件添加相關配置api

server:
    port: 8769

eureka:
    client:
      serviceUrl:
        defaultZone: http://localhost:8761/eureka/

spring:
    application:
      name: zuul-service #指明應用名稱(服務與服務相互調用根據name屬性)

zuul:
  routes:
    api-a:
      path: /api-ribbon-service/**
      serviceId: ribbon-service
    api-b:
      path: /api-feign-service/**
      serviceId: feign-service

配置服務端口爲8769,應用名稱爲 zuul-service;配置以/api-ribbon-service/開頭的請求轉發到ribbion-service服務,以/api-feign-service/開頭的請求轉發到feign-service服務。瀏覽器

2.4 依次啓動服務註冊中心、one-service、ribbon-service、feign-service、zuul-service

瀏覽器請求 http://localhost:8769/api-ribbon-service/one 結果:

瀏覽器請求http://localhost:8769/api-feign-service/one 結果:

說明zuul起到了路由功能。

3 Zuul服務過濾測試

添加自定義的受權過濾器,繼承ZuulFilter

@Component
public class MyAuthFilter extends ZuulFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyAuthFilter.class);

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        LOGGER.info("{}--->{}", request.getMethod(), request.getRequestURL().toString());
        Object token = request.getParameter("token");
        if (token == null) {
            LOGGER.info("token is empty");
            context.setSendZuulResponse(false);
            context.setResponseStatusCode(401);
            try {
                context.getResponse().getWriter().write("token is empty");
            } catch (Exception e) {

            }
            return null;
        }
        LOGGER.info("ok");
        return null;
    }
}

① filterType定義:

  • PRE 路由前
  • ROUTING 路由中
  • POST 路由後
  • ERROR 發生錯誤調用

Zuul Request Lifecycle

② filterOrder:過濾順序

③ shouldFilter:是否須要過濾,返回boolean值

④ run:過濾邏輯

瀏覽器訪問 http://localhost:8769/api-feign-service/one 結果:

添加token參數請求 http://localhost:8769/api-feign-service/one?token=haha 結果:

本文源碼下載地址:

https://github.com/laravelshao/spring-cloud-learning/tree/master/setion04-zuul

4 參考資料

翟永超->Spring Cloud構建微服務架構:服務網關(基礎)

Spring->Router and Filter: Zuul

GitHub->Netflix Zuul Filter

方誌朋->史上最簡單的SpringCloud教程

相關文章
相關標籤/搜索