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的架構圖如下所示。