基本概念
Route
路由器=ID+URI+Predicates+Filters
路由器決定如何處理請(qǐng)求, 當(dāng)一個(gè)請(qǐng)求到來(lái)的時(shí)候, 跟據(jù)匹配條件找到路由器, 再由路由器的過(guò)濾器來(lái)處理請(qǐng)求.
Predicate
匹配器, 是一個(gè)java8的函數(shù),輸入是ServerWebChange, 里面包含了ServerHttpRequest, 開(kāi)發(fā)者跟據(jù)輸入決定是否匹配路由.
Filter
過(guò)濾器, 處理請(qǐng)求, 可以修改請(qǐng)求前的數(shù)據(jù)和返回后的數(shù)據(jù), 類似于spring webmvc的web過(guò)濾器.
How it works
spring cloud gateway默認(rèn)有很多全局過(guò)濾器和普通過(guò)濾器, 可以通過(guò)配置文件配置發(fā)揮強(qiáng)大功效.
集成
spring cloud gateway 基于spring webflux, 而不是spring webmvc, 這一點(diǎn)要非常注意,如果classpath包含了spring webmvc那么啟動(dòng)后,網(wǎng)關(guān)路由不會(huì)生效.
dependencies {
compile('org.springframework.cloud:spring-cloud-starter')
compile('org.springframework.cloud:spring-cloud-starter-gateway')
compile('org.springframework.boot:spring-boot-starter-webflux')
}
configurations {
all*.exclude group: 'org.springframework','spring-webmvc'
}
啟動(dòng)成功后,應(yīng)該輸出:
INFO org.springframework.boot.web.embedded.netty.NettyWebServer - Netty started on port(s): ...
網(wǎng)關(guān)功能
微服務(wù)網(wǎng)關(guān)最重要的幾個(gè)功能分別是路由, 負(fù)載均衡,認(rèn)證授權(quán), 跨域配置, 日志, 失敗重試, 下來(lái)一一來(lái)配置.
動(dòng)態(tài)路由
通常微服務(wù)都是注冊(cè)中心, 服務(wù)都是自動(dòng)發(fā)現(xiàn)的,spring cloud gateway可以基于注冊(cè)小心動(dòng)態(tài)配置路由, 轉(zhuǎn)發(fā)的規(guī)則是:
/service_id/path->轉(zhuǎn)發(fā)到service_id對(duì)應(yīng)的服務(wù)
只需要添加配置:
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lowerCaseServiceId=true
就能動(dòng)態(tài)路由.
負(fù)載均衡
以lb://開(kāi)頭的請(qǐng)求, 會(huì)被全局過(guò)濾器RetryLoadBalancerClientFilter攔截并進(jìn)行負(fù)載均衡處理, 所有的動(dòng)態(tài)路由都會(huì)自動(dòng)負(fù)載均衡.
認(rèn)證授權(quán)
有一個(gè)專門用來(lái)做認(rèn)證授權(quán)的服務(wù), 網(wǎng)關(guān)需要做的就是自定義一個(gè)全局過(guò)濾器, 將每一個(gè)請(qǐng)求發(fā)到授權(quán)服務(wù)進(jìn)行認(rèn)證授權(quán).
@Component
public class AuthFilter implements GlobalFilter, Ordered {
@Override
public int getOrder() {
return Constants.PRE_FILTER_ORDER_AUTH;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
try {
//TODO 調(diào)用授權(quán)服務(wù)進(jìn)行認(rèn)證和授權(quán)
return chain.filter(exchange.mutate().request(request).build());
} catch (Exception e) {
log.error("auth failed: " + e.getMessage());
return exchange.getResponse()
.writeWith(Flux.just(exchange.getResponse().bufferFactory().wrap("授權(quán)失敗".getBytes())));
}
}
跨域設(shè)置
有時(shí)候前端需要支持跨域訪問(wèn), 這里簡(jiǎn)單配置允許所有域名訪問(wèn).
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowed-origins=*
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowed-methods=*
spring.cloud.gateway.globalcors.cors-configurations.[/**].allowed-headers=*
spring.cloud.gateway.globalcors.cors-configurations.[/**].allow-credentials=true
日志
日志功能同樣是自定義全局過(guò)濾器實(shí)現(xiàn), 在請(qǐng)求進(jìn)入時(shí)打印輸入日志,返回時(shí)打印輸出日志, 唯一的問(wèn)題是在打印請(qǐng)求或返回的body時(shí)要處理下,一般情況下請(qǐng)求和響應(yīng)的body都不能多次讀, 需要自定義裝飾器封裝實(shí)現(xiàn)多次讀的功能.
失敗重試
這個(gè)沒(méi)有全局過(guò)濾器, 需要自己實(shí)現(xiàn).