1.什么是服務網關
1.說明
-
網關統一服務入口,可方便實現對平台眾多服務接口進行管控,對訪問服務的身份認證、防報文重放與防數據篡改、功能調用的業務鑒權、響應數據的脫敏、流量與並發控制,甚至基於API調用的計量或者計費等等。
-
網關 = 路由轉發 + 過濾器
路由轉發:接收一切外界請求,轉發到后端的微服務上去;在服務網關中可以完成一系列的橫切功能,例如權限校驗、限流以及監控等,這些都可以通過過濾器完成
2.為什么需要網關
- 1.網關可以實現服務的統一管理
- 2.網關可以解決微服務中通用代碼的冗余問題(如權限控制,流量監控,限流等)
3.網關組件在微服務中架構

2.服務網關組件
1.zuul
Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security.
-
原文翻譯
- https://github.com/Netflix/zuul/wiki
- zul是從設備和網站到Netflix流媒體應用程序后端的所有請求的前門。作為一個邊緣服務應用程序,zul被構建為支持動態路由、監視、彈性和安全性。
-
zuul版本說明
- 目前zuul組件已經從1.0更新到2.0,但是作為springcloud官方不再推薦使用zuul2.0,但是依然支持zuul2.
-
springcloud 官方集成zuul文檔
2.gateway
This project provides a library for building an API Gateway on top of Spring MVC. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.
-
原文翻譯
- https://spring.io/projects/spring-cloud-gateway
- 這個項目提供了一個在springmvc之上構建API網關的庫。springcloudgateway旨在提供一種簡單而有效的方法來路由到api,並為api提供橫切關注點,比如:安全性、監控/度量和彈性。
-
特性
- 基於springboot2.x 和 spring webFlux 和 Reactor 構建 響應式異步非阻塞IO模型
- 動態路由
- 請求過濾
創建一個新的項目,根據之前寫的環境搭建方式
3.開發網關動態路由
- 網關配置有兩種方式一種是快捷方式,一種是完全展開方式
1.創建項目引入網關依賴
<!--引入gateway網關依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
完整的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.md</groupId>
<artifactId>05-gateway8989</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>05-gateway8989</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
</properties>
<dependencies>
<!--使用網關的時候web包需要移除掉-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--引入gateway網關依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--引入consul依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!-- 這個包是用做健康度監控的-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<!--全局管理springcloud版本,並不會引入具體依賴-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
快捷方式配置路由
2.編寫網關配置
spring:
application:
name: gateway
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
gateway:
routes:
- id: user_route # 指定路由的唯一標識
uri: http://localhost:9999/ # 指定路由服務的地址
predicates: # 指定路由的規則
- Path=/user/**
- id: product_route
uri: http://localhost:9998/
predicates:
- Path=/product/**
server:
port: 8989
3.啟動gateway網關項目
-
直接啟動報錯:

-
在啟動日志中發現,gateway為了效率使用webflux進行異步非阻塞模型的實現,因此和原來的web包沖突,去掉原來的web即可

- 再次啟動成功啟動

4.測試網關路由轉發
使用之前寫的寫的,可以看前面幾篇文章
- 測試通過網關訪問用戶服務: http://localhost:8989/user/findOne?productId=10001
- 測試通過網關訪問商品服務: http://localhost:8989/product/findOne?productId=10002

java方式配置路由(了解)
環境還是和上面的一樣
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("order_route", r -> r.path("/order/**")
.uri("http://localhost:9997/"))
.build();
}
}
4.查看網關路由規則列表
1.說明
- gateway提供路由訪問規則列表的web界面,但是默認是關閉的,如果想要查看服務路由規則可以在配置文件中開啟
management:
endpoints:
web:
exposure:
include: "*" #開啟所有web端點暴露
訪問路由管理列表地址

3.配置路由服務負載均衡
1.說明
- 現有路由配置方式,都是基於服務地址寫死的路由轉發,能不能根據服務名稱進行路由轉發同時實現負載均衡的呢?
2.動態路由以及負載均衡轉發配置
spring:
application:
name: gateway
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
gateway:
routes:
- id: user_route # 指定路由的唯一標識
# uri: http://localhost:9999/ # 指定路由服務的地址
# lb代表轉發后台服務使用負載均衡,users代表服務注冊中心上的服務名
uri: lb://users
predicates: # 指定路由的規則
- Path=/user/**
- id: product_route
# uri: http://localhost:9998/
# lb代表負載均衡轉發路由,products代表服務注冊中心上的服務名
uri: lb://products
predicates:
- Path=/product/**
# 開啟根據服務名動態獲取路由地址
discovery:
locator:
enabled: true
server:
port: 8989
#開啟所有web端點暴露
management:
endpoints:
web:
exposure:
include: "*"

此時訪問就實現了負載均衡的效果
4.常用路由predicate(斷言,驗證)
1.Gateway支持多種方式的predicate

After、Before、Between用於商城活動的時候指定日期才能訪問
-
After=2020-12-21T11:33:33.993+08:00[Asia/Shanghai] `指定日期之后的請求進行路由
-
Before=2020-12-21T11:33:33.993+08:00[Asia/Shanghai] `指定日期之前的請求進行路由
-
Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
-
Cookie=username,pony `基於指定cookie的請求進行路由
-
Cookie=username,[A-Za-z0-9]+
基於指定cookie的請求進行路由curl http://localhost:8989/user/findAll --cookie "username=zhangsan" -
Header=X-Request-Id, \d+ ``基於請求頭中的指定屬性的正則匹配路由(這里全是整數)
`curl http://localhost:8989/user/findAll -H "X-Request-Id:11" -
Method=GET,POST `基於指定的請求方式請求進行路由
2.使用predicate
spring:
application:
name: gateway
cloud:
consul:
host: localhost
port: 8500
gateway:
routes:
- id: user_route
#uri: http://localhost:9999/
uri: lb://users
predicates:
- Path=/user/**
- After=2020-12-21T11:39:33.993+08:00[Asia/Shanghai]
- Cookie=username,[A-Za-z0-9]+
- Header=X-Request-Id, \d+

5.常用的Filter以及自定義filter
-
路由過濾器允許以某種方式修改傳入的HTTP請求或傳出的HTTP響應。路由篩選器的作用域是特定路由。springcloudgateway包括許多內置的GatewayFilter工廠。
1.作用
- 當我們有很多個服務時,比如下圖中的user-service、order-service、product-service等服務,客戶端請求各個服務的Api時,每個服務都需要做相同的事情,比如鑒權、限流、日志輸出等。


2.使用內置過濾器

-
使用方式如下:
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: product_route
#uri: http://localhost:9998/
uri: lb://products # lb: 使用負載均衡策略 products代表注冊中心的具體服務名
predicates:
- Path=/product/**
#- After=2020-07-30T09:45:49.078+08:00[Asia/Shanghai]
filters:
# 為每個請求添加參數id=12
- AddRequestParameter=id,12
# 增加響應頭
- AddResponseHeader=username,chenyn
3.使用自定義filter
@Configuration
@Slf4j
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("進入自定義的filter");
if(exchange.getRequest().getQueryParams().get("username")!=null){
log.info("用戶身份信息合法,放行請求繼續執行!!!");
return chain.filter(exchange);
}
log.info("非法用戶,拒絕訪問!!!");
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() { //filter 數字越小filter越先執行
return -1; //-1 最先執行
}
}
自定義全局filter

