1、什麼是網關
網關是一個服務,是訪問內部系統的唯一入口,提供內部服務的路由中轉,額外還可以在此基礎上提供身份認證、監控、負載均衡,限流、降級與應用檢測等功能
spring cloud Gateway 底層使用了高性能的通信框架netty
2、Spring Cloud Gateway 與Zuul對比
nginx+lua 高性能反向代理伺服器,通常做為負載均衡入口後端
Zuul是第一代網關,spring瀏覽器
cloud是第二代網關,基於Netty\Reactor\WebFLux構建緩存
- 性能強勁,zuul1.6倍安全
- 功能強大,內置轉發,監控,限流等功能
缺點
- 不能再servlet容器下功能,不能使用war包
2.1 基礎說明
- spring cloud gateway基於springBoot2.x系列,webflux,reactor等技術,傳統的同步庫都是不能使用的
- gateway底層依賴netty,不接受servlet容器或者war包
2.2 zuul1.x 與zuul2.x
ZUUL1.x是基於同步IO
Zuul2.x 基於異步IO
3、Gateway基本使用
3.1predicate 斷言
參考的是java8的java.util.function.predicate 開發人員可以匹配http請求中的所有內容(例如請求頭或請求參數),如果請求與斷言相匹配則進行路由
path斷言
predicates:
- path=/mg/**
Query斷言
參數值可以寫正則,也可以只寫參數名
predicates:
- query=foo,ba.
Method斷言
predicates:
- Method=get
Host斷言
predicates:
- Host=wzx.cool
Cookie斷言
predicates:
- cookie=name.wuzhixuan
3.2 route 路由
構建網關的基本模塊,它由id,目標uri,一系列的斷言和過濾器組成,如果斷言為true則匹配該路由
3.3filter 過濾
指的是spring框架中gatewayfilter的實例,使用過濾器,可以在請求被路由前或者之後對請求進行修改。
3.4、總體
- web請求,通過一些匹配條件,定位到真正的服務節點。並在這個轉發過程的前後,進行一些精細化控制。
- predicate就是我們的匹配條件;
- 而filter,就可以理解為一個無所不能的攔截器。有了這兩個元素,再加上目標uri,就可以實現一個具體的路由了
4、原理
5、通過微服務名實現動態路由
默認情況下gateway會根據註冊中心註冊的服務列表以註冊中心上微服務名為路徑創建動態路由進行轉發,從而實現動態路由的功能
server:
port: 80
spring:
application:
name: wuzx-gateway
profiles:
active: sit
cloud:
nacos:
discovery:
server-addr: wuzx.cool:30000
config:
server-addr: wuzx.cool:30000
file-extension: yaml
gateway:
discovery:
locator:
enabled: true # 開啟從註冊中心動態創建路由的功能,利用微服務名進行路由
loadbalancer:
retry:
enabled: true
routes:
- id: payment_routh #路由的id,沒有固定規則但要求唯一,建議配合服務名
# uri: http://localhost:8001 #匹配後提供服務的路由地址
uri: lb://cloud-payment-service
predicates:
- path=/payment/get/** #斷言,路徑相匹配的進行路由
- id: payment_routh2
#uri: http://localhost:8001
uri: lb://cloud-payment-service
predicates:
- path=/payment/lb/** #斷言,路徑相匹配的進行路由
6、自定義過濾器
兩個接口介紹:globalfilter,ordered
功能:
- 全局日誌記錄
- 統一網關鑒權
/**
* 鑒權認證
*
* @author 吳志旋
* 自定義filter 需要實現Ordered 和GlobalFilter
* Ordered 優先級 越小優先級越大
*/
@Slf4j
@Component
@AllArgsConstructor
public class AuthFilter implements GlobalFilter, Ordered {
private final AuthProperties authProperties;
private final ObjectMapper objectMapper;
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getURI().getPath();
if (isSkip(path)) {
return chain.filter(exchange);
}
ServerHttpResponse resp = exchange.getResponse();
String headerToken = "";
String paramToken ="";
if (StringUtils.isAllBlank(headerToken, paramToken)) {
return unAuth(resp, "缺失令牌,鑒權失敗");
}
String auth = StringUtils.isBlank(headerToken) ? paramToken : headerToken;
String token = JwtUtil.getToken(auth);
Claims claims = JwtUtil.parseJWT(token);
if (claims == null) {
return unAuth(resp, "請求未授權");
}
return chain.filter(exchange);
}
private boolean isSkip(String path) {
}
@Override
public int getOrder() {
return -100;
}
}