一 API 網(wǎng)關(guān)
API網(wǎng)關(guān)葫辐,就是指系統(tǒng)統(tǒng)一入口搜锰,它用來封裝應(yīng)用程序的內(nèi)部結(jié)構(gòu),為客戶端提供統(tǒng)一服務(wù)耿战。一些與業(yè)務(wù)本身功能無關(guān)的公共邏輯可以在這里實現(xiàn)蛋叼。比如:認(rèn)證、鑒權(quán)剂陡、監(jiān)控狈涮、路由轉(zhuǎn)發(fā) 等等。
二 業(yè)界流行的網(wǎng)關(guān)
- Nginx+lua: 使用nginx 的反向代理和負(fù)載均衡均可實現(xiàn)api服務(wù)器的負(fù)載均衡及高可用鸭栖。lua是一種腳本語言歌馍,可以編寫一些簡單的lua腳本來支持nginx。
- Kong:基于 nginx +lua 開發(fā)纤泵,性能高骆姐、穩(wěn)定,有多個可用的插件(鑒權(quán)捏题、限流)可以開箱即用玻褪。缺點:只支持http協(xié)議,二次開發(fā)公荧、自由拓展困難带射;提供管理API,缺乏更易用的管控循狰,配置方式窟社。
- Zuul :Netflix 開源網(wǎng)關(guān),功能豐富绪钥,使用java開發(fā)灿里,易于二次開發(fā)。缺點:缺乏管控程腹,無法動態(tài)配置匣吊;依賴組件較多;處理http請求依賴是web容器寸潦,性能不如nginx色鸳。
- Spring Cloud Gateway:Spring 公司為了替換zuul而開發(fā)的網(wǎng)關(guān)服務(wù)。
三SpringCloud Gateway 簡介
SpringCloud Gateway 是 Spring Cloud 的一個全新項目见转,該項目是基于 Spring 5.0命雀,Spring Boot 2.0 和 Project Reactor 等技術(shù)開發(fā)的網(wǎng)關(guān),它旨在為微服務(wù)架構(gòu)提供一種簡單有效的統(tǒng)一的 API 路由管理方式斩箫。
Spring Cloud Gateway 作為 Spring Cloud 生態(tài)系統(tǒng)中的網(wǎng)關(guān)吏砂,目標(biāo)是替代Netflix Zuul撵儿,其不僅提供統(tǒng)一的路由方式,而且基于Fliter鏈的方式提供了網(wǎng)關(guān)基本的功能赊抖,例如:安全统倒,監(jiān)控/指標(biāo)和限流。
(1)優(yōu)點:
性能強(qiáng)勁:是第一代網(wǎng)關(guān)Zuul的1.6倍
功能強(qiáng)大:內(nèi)置了很多使用的功能氛雪,例如轉(zhuǎn)發(fā),監(jiān)控耸成,限流等
設(shè)計優(yōu)雅报亩,容易擴(kuò)展
(2)缺點:
其實現(xiàn)依賴Netty與WebFlux,不是傳統(tǒng)的Servlet編程模型井氢,學(xué)習(xí)成本高
不能將其部署在tomcat弦追,jetty等Servlet容器里,只能打成jar包執(zhí)行
需要Spingboot2.0及以上的版本花竞,才支持劲件。
四 SpringCloud Gateway快速入門
- 創(chuàng)建新模塊,導(dǎo)入依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
- 創(chuàng)建主類
@SpringBootApplication
public class RuoYiGatewayApplication
{
public static void main(String[] args)
{
SpringApplication.run(RuoYiGatewayApplication.class, args);
}
}
- 添加配置文件application.yml
server:
port: 8080
spring:
application:
name: ruoyi-gateway
cloud:
gateway:
routes: #路由數(shù)組[路由就是指定當(dāng)請求滿足什么條件的時候轉(zhuǎn)到哪個微服務(wù)]
# 系統(tǒng)模塊
- id: ruoyi-system #當(dāng)前路有的標(biāo)示约急,要求唯一
uri: http://localhost:9201/ #請求要轉(zhuǎn)發(fā)到的地址
predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)
- Path=/system/** #當(dāng)前請求路徑滿足Path指定的規(guī)則時零远,才進(jìn)行路有轉(zhuǎn)發(fā)
filters: #過濾器,請求在傳遞過程中可以通過過濾器對其進(jìn)行一定的修改
- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑
- 運行效果
在地址欄輸入 localhost:8080/system/user/1就會自動跳轉(zhuǎn)到 localhost:9201/user/1
其中路徑中的system被過濾掉厌蔽,8080變成9201
- 使用nacos注冊中心配置方式進(jìn)行優(yōu)化
(1)現(xiàn)在在配置文件中寫死了轉(zhuǎn)發(fā)路徑的地址牵辣,我們需要使用nacos獲取此地址,
(2)并使用 uri: lb://ruoyi-system #請求要轉(zhuǎn)發(fā)到的地址 自動實現(xiàn)負(fù)載均衡
第1步,加入nacos依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
第2部:應(yīng)用加上注解@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class RuoYiGatewayApplication
{
public static void main(String[] args)
{
SpringApplication.run(RuoYiGatewayApplication.class, args);
}
}
第3部:修改配置文件
server:
port: 8080
spring:
application:
name: ruoyi-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true #讓gateway可以發(fā)現(xiàn)nacos的微服務(wù)
routes: #路由數(shù)組[路由就是指定當(dāng)請求滿足什么條件的時候轉(zhuǎn)到哪個微服務(wù)]
# 系統(tǒng)模塊
- id: ruoyi-system #當(dāng)前路有的標(biāo)示奴饮,要求唯一
uri: lb://ruoyi-system #請求要轉(zhuǎn)發(fā)到的地址
predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)
- Path=/system/** #當(dāng)前請求路徑滿足Path指定的規(guī)則時纬向,才進(jìn)行路有轉(zhuǎn)發(fā)
filters: #過濾器,請求在傳遞過程中可以通過過濾器對其進(jìn)行一定的修改
- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑
五 若依平臺—ruoyi-gateway網(wǎng)關(guān)
(1)若依平臺單獨建立ruoyi-gateway網(wǎng)關(guān)模塊戴卜,代碼里有4個過濾器:
AuthFilter(全局過濾器)逾条,
BlackListUrlFilter(黑名單過濾器)
CacheRequestFilter
ValidateCodeFilter (驗證碼過濾器)
(2)在nacos里配置了路由信息 和白名單
spring:
redis:
host: localhost
port: 6379
password:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
# 認(rèn)證中心
- id: ruoyi-auth
uri: lb://ruoyi-auth
predicates:
- Path=/auth/**
filters:
# 驗證碼處理
- CacheRequestFilter
- ValidateCodeFilter
- StripPrefix=1
# 代碼生成
- id: ruoyi-gen
uri: lb://ruoyi-gen
predicates:
- Path=/code/**
filters:
- StripPrefix=1
# 定時任務(wù)
- id: ruoyi-job
uri: lb://ruoyi-job
predicates:
- Path=/schedule/**
filters:
- StripPrefix=1
# 系統(tǒng)模塊
- id: ruoyi-system
uri: lb://ruoyi-system
predicates:
- Path=/system/**
filters:
- StripPrefix=1
# 文件服務(wù)
- id: ruoyi-file
uri: lb://ruoyi-file
predicates:
- Path=/file/**
filters:
- StripPrefix=1
# whaletest模塊
- id: ruoyi-whaletest
uri: lb://ruoyi-whaletest
predicates:
- Path=/whaletest/**
filters:
- StripPrefix=1
# 不校驗白名單
ignore:
whites:
- /auth/logout
- /auth/login
- /*/v2/api-docs
- /csrf
- /whaletest/test
六 重要功能配置——路由斷言和過濾器
我們看到每個路由主要對predicates 和filter進(jìn)行了配置。這兩個一個是斷言投剥,一個是過濾器师脂。接下來我們對這兩個重要功能進(jìn)行說明
打開nacos中的ruoyi-gateway-dev.yml ,顯示有路由的配置信息如下
系統(tǒng)模塊
- id: ruoyi-system #當(dāng)前路有的標(biāo)示,要求唯一
uri: lb://ruoyi-system #請求要轉(zhuǎn)發(fā)到的地址
predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)
- Path=/system/** #當(dāng)前請求路徑滿足Path指定的規(guī)則時薇缅,才進(jìn)行路有轉(zhuǎn)發(fā)
filters: #過濾器危彩,請求在傳遞過程中可以通過過濾器對其進(jìn)行一定的修改
- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑
一.predicates 斷言:路有需要滿足什么條件才能路由,是路由轉(zhuǎn)發(fā)的判斷條件泳桦,目前SpringCloud Gateway支持多種方式汤徽,常見如:Path、Query灸撰、Method谒府、Header等拼坎,寫法必須遵循 key=vlue的形式
Predicate 接受一個輸入?yún)?shù),返回一個布爾值結(jié)果完疫。
(1)系統(tǒng)內(nèi)置的斷言
規(guī)則 實例 說明
Path - Path=/gate/,/rule/ ## 當(dāng)請求的路徑為gate泰鸡、rule開頭的時,轉(zhuǎn)發(fā)到http://localhost:9023服務(wù)器上
Before - Before=2017-01-20T17:42:47.789-07:00[America/Denver] 在某個時間之前的請求才會被轉(zhuǎn)發(fā)到 http://localhost:9023服務(wù)器上
After - After=2017-01-20T17:42:47.789-07:00[America/Denver] 在某個時間之后的請求才會被轉(zhuǎn)發(fā)
Between - Between=2017-01-20T17:42:47.789-07:00[America/Denver],2017-01-21T17:42:47.789-07:00[America/Denver] 在某個時間段之間的才會被轉(zhuǎn)發(fā)
Cookie - Cookie=chocolate, ch.p 名為chocolate的表單或者滿足正則ch.p的表單才會被匹配到進(jìn)行請求轉(zhuǎn)發(fā)
Header - Header=X-Request-Id, \d+ 攜帶參數(shù)X-Request-Id或者滿足\d+的請求頭才會匹配
Host - Host=www.hd123.com 當(dāng)主機(jī)名為www.hd123.com的時候直接轉(zhuǎn)發(fā)到http://localhost:9023服務(wù)器上
Method - Method=GET 只有GET方法才會匹配轉(zhuǎn)發(fā)請求壳鹤,還可以限定POST盛龄、PUT等請求方式
(2)自定義斷言
二.filters過濾
- 局部過濾,是針對單個路有的過濾器
(1)內(nèi)置過濾規(guī)則
過濾規(guī)則 實例 說明
PrefixPath - PrefixPath=/app 在請求路徑前加上app
RewritePath - RewritePath=/test, /app/test 訪問localhost:9022/test,請求會轉(zhuǎn)發(fā)到localhost:8001/app/test
SetPath - SetPath=/{segment} 設(shè)置請求路徑芳誓,與RewritePath類似余舶。如/red/blue的請求被轉(zhuǎn)發(fā)到/blue。
SetStatus - SetStatus=401 設(shè)置回執(zhí)狀態(tài)碼锹淌。
StripPrefix - StripPrefix=2 跳過指定路徑匿值。請求/name/blue/red會轉(zhuǎn)發(fā)到/red。
(2)自定義過濾規(guī)則
若依平臺中nacos中ruoyi-gateway-dev.yml赂摆,有添加自定義過濾規(guī)則
filters:
# 驗證碼處理
- CacheRequestFilter
- ValidateCodeFilter
- StripPrefix=1
同時需要實現(xiàn)AbstractGatewayFilterFactory<>方法
- 全局過濾:全局過濾器作用于所有的路由挟憔,不需要單獨配置,我們可以用它來實現(xiàn)很多統(tǒng)一化處理的業(yè)務(wù)需求烟号,比如權(quán)限認(rèn)證绊谭,IP訪問限制等等。目前網(wǎng)關(guān)統(tǒng)一鑒權(quán)AuthFilter.java就是采用的全局過濾器褥符。
自定義全局過濾規(guī)則龙誊,只需要實現(xiàn)GlobalFilter, Ordered這兩個接口就可以了。
/**
* 網(wǎng)關(guān)鑒權(quán)
*
* @author ruoyi
*/
@Component
public class AuthFilter implements GlobalFilter, Ordered
{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
}
@Override
public int getOrder()
{
return -200;
}
}
七喷楣,高級配置——網(wǎng)關(guān)限流
網(wǎng)關(guān)是所有請求的公共入口趟大,所以可以在網(wǎng)關(guān)進(jìn)行限流,而且限流方式也很多铣焊。Sentinel支持對SpringCloud Gateway逊朽,Zuul等主流網(wǎng)關(guān)進(jìn)行限流。
Sentinel可以提供兩種資源的限流
- 路由route限流:即在Spring配置文件中配置的路由條目曲伊,資源名為對應(yīng)的ruoteId
2.自定義API維度:用戶可以利用sentinel提供的API來自定義一些API分組
需要添加如下依賴
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel Gateway -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>