【開發技巧/經驗分享】使用zuul構建服務網關ApiGetaway

1. 什麼是服務網關?

服務網關就好比是一個請求的轉發者,它能夠根據相關的請求規則調用對應的服務提供者,它有點像nginx起到了一個代理的作用,使用服務網關可以實現限流、服務鑑權、請求處理、請求參數驗證等操作。
在這裏插入圖片描述

2. 什麼是zuul?

zuul是服務網關的實現之一,zuul作爲一個邊界性質的應用程序,它提供了動態路由、監控、彈性負載和安全功能。Zuul底層利用各種filter實現如下功能:

  • 認證和安全 識別每個需要認證的資源,拒絕不符合要求的請求。
  • 性能監測 在服務邊界追蹤並統計數據,提供精確的生產視圖。
  • 動態路由 根據需要將請求動態路由到後端集羣。
  • 壓力測試 逐漸增加對集羣的流量以瞭解其性能。
  • 負載卸載 預先爲每種類型的請求分配容量,當請求超過容量時自動丟棄。
  • 靜態資源處理 直接在邊界返回某些響應。

在這裏插入圖片描述

3. 爲什麼選擇zuul?

zuul提供了許多過濾器對請求進行處理,它能夠實現認證安全、動態路由、以及性能監測,zuul的生命週期如下圖所示
在這裏插入圖片描述

4. 如何使用zuul構建APIGetaway?

4.1 創建一個工程,導入相關maven依賴
<dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-config</artifactId>
     </dependency>
     <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>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
     </dependency>
 </dependencies>
4.2 在啓動類上添加註解@EnableZullProxy
package com.qingyun.apigetaway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@SpringBootApplication
@EnableZuulProxy
public class ApiGetawayApplication {

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

}
4.3 這時我們就可以通過服務名(小寫)/uri訪問我們的相關資源了在這裏插入圖片描述
4.4 定製路由名稱,將服務名映射成指定名稱

要實現路由映射名稱定製只需要添加配置信息就好了,如下有三種配置方式

zuul:
  routes:
    orderService: #第一種方式 zuul.服務名.path: /定製化路徑/**
      path: /myOrder1/**
    productService: /myProduct/** #第二種方式 直接 zuul.服務名: /定製化路徑/**
    hello:
     path: /myHello/**
     serviceId: configService #第三種方式 zuul.隨便填.path: /定製化路徑/** serviceId: 指定的服務名稱

我們開啓所有端點查看所有的zuul路由映射

management:
  endpoints:
    web:
      exposure:
        include: "*"

訪問/actuator/router
在這裏插入圖片描述
可以看到裏邊有我們寫的映射,第三種方式沒有顯示是因爲這是我在程序啓動之後添加的。

雖然現在實現了路由映射,但是這個配置不夠靈活,每次配置的更改都需要進行項目重新啓動,不過這個問題也是有解決方案的,那就是通過SpringCloudBus來動態更新配置信息,如果對於動態配置更新不夠理解可以看我的另一篇博客(下面部分實現在該博文中可以找到比如服務端):通過SpringCloudBus實現配置更新

5. 使用SpringCloudBus+Zuul實現動態路由

5.1 在工程中引入SpringCloudBus相關maven依賴
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-bus-amqp</artifactId>
 </dependency>
5.1 編寫相關配置信息
spring:
  cloud:
    config:
      discovery:
        enabled: true #開啓配置中心發現
        service-id: config-server #配置中心的名稱
      profile: dev
    bus:
      id: ${spring.application.name}:${spring.cloud.config.profile}:${random.value}
  profiles:
    active: dev
5.2 在遠程git倉庫中添加配置文件,比如apiGetaway-dev.yml
server:
  port: 8002
zuul:
  routes:
    orderService:
      path: /myOrder1/**
      sensitiveHeaders:
    productService: /myProduct/**
spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
5.3 編寫一個配置類,用於動態刷新zuul配置
package com.qingyun.apigetaway.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.context.annotation.Configuration;

/**
 * Created with IntelliJ IDEA.
 * User: 李敷斌.
 * Date: 2020-02-17
 * Time: 19:23
 * Explain: Zuul配置類
 */
@Configuration
public class ZuulConfig {

    //實現動態配置
    @ConfigurationProperties(prefix = "zuul")
    @RefreshScope
    public ZuulProperties zuulProperties(){
        return new ZuulProperties();
    }
}

編寫完畢後就可以實現動態路由更新了,只要我們在遠程git中修改了配置,本地配置都會實時更新。

6. 解決zuul中cookie無法傳遞的問題

在zuul中之所以cookie不可以傳遞是因爲zuul將cookie視爲敏感頭,如下源碼所示

/**
	 * List of sensitive headers that are not passed to downstream requests. Defaults to a
	 * "safe" set of headers that commonly contain user credentials. It's OK to remove
	 * those from the list if the downstream service is part of the same system as the
	 * proxy, so they are sharing authentication data. If using a physical URL outside
	 * your own domain, then generally it would be a bad idea to leak user credentials.
	 */
private Set<String> sensitiveHeaders = new LinkedHashSet<>(
		Arrays.asList("Cookie", "Set-Cookie", "Authorization"));

所以我們只需要將sensitiveHeaders設置爲空就好了,配置如下所示

zuul:
  routes:
    orderService:
      path: /myOrder1/**
      sensitiveHeaders:

7. 如何實現zuul高可用?

高可用是爲了保障我們程序運行的可靠性,因爲服務網關用於連接其他服務,要是服務網關都宕機了那麼整個程序也就不可用了,也就是出現了我們常說的單點故障。爲了解決這個問題我們可以通過nginx映射多個zuul服務網關實例的方式保證程序的可用性。

衆所周知,nginx是一個高性能的反向代理、負載均衡服務器,它相對而言是比較可靠的,nginx+zuul的架構圖如下所示。
在這裏插入圖片描述

發佈了97 篇原創文章 · 獲贊 36 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章