網(wǎng)站自然排名這么做北京網(wǎng)站建設(shè)制作公司
核心部分:routes(路由), predicates(斷言),filters(過濾器)
id:可以理解為是這組配置的一個(gè)id值,請(qǐng)保證他的唯一的,可以設(shè)置為和服務(wù)名一致
uri:可以理解為是通過條件匹配之后需要路由到(跳轉(zhuǎn),重定向)到的新的服務(wù)地址
predicates:可以理解為是編寫條件,滿足條件才進(jìn)行uri
filters:可以理解為是在路由前對(duì)請(qǐng)求的地址進(jìn)行額外的其他操作,例如拼接或者裁減等
pom依賴
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
yml配置網(wǎng)關(guān)
server:port: 8087
spring:application:name: gateway-nacoscloud:gateway:routes: #路由數(shù)組[路由 就是指定當(dāng)請(qǐng)求滿足什么條件的時(shí)候轉(zhuǎn)到哪個(gè)微服務(wù)]- id: product_route #當(dāng)前路由的標(biāo)識(shí),要求唯-uri: http://localhost:8086 #請(qǐng)求要轉(zhuǎn)發(fā)到的地址order: 1 #路由的優(yōu)先級(jí),數(shù)字越小級(jí)別越高predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)- Path=/product-service/** #當(dāng)請(qǐng)求路徑滿足Path指定的規(guī)則時(shí),才進(jìn)行路由轉(zhuǎn)發(fā)#http://localhost:8087/product-service/product/9 路由器到?#http://localhost:8086/product-service/product/9filters: #過濾器,請(qǐng)求在傳遞過程中可以通過過濾器對(duì)其進(jìn)行一定的修改- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑##http://localhost:8086/product/9
yml注冊(cè)到nacos配置網(wǎng)關(guān)
server:port: 8087
spring:application:name: gateway-nacoscloud:nacos:discovery:server-addr: 192.168.11.47:18848username: nacospassword: nacosgateway:routes: #路由數(shù)組[路由 就是指定當(dāng)請(qǐng)求滿足什么條件的時(shí)候轉(zhuǎn)到哪個(gè)微服務(wù)]- id: product_route #當(dāng)前路由的標(biāo)識(shí),要求唯-uri: lb://product_naocs #lb指的是從nacos中按名稱獲取微服務(wù),并遵循負(fù)載均衡策略order: 1 #路由的優(yōu)先級(jí),數(shù)字越小級(jí)別越高predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)- Path=/product-service/** #當(dāng)請(qǐng)求路徑滿足Path指定的規(guī)則時(shí),才進(jìn)行路由轉(zhuǎn)發(fā)filters: #過濾器,請(qǐng)求在傳遞過程中可以通過過濾器對(duì)其進(jìn)行一定的修改- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑,
yml配置網(wǎng)關(guān)(約定大于配置的方式,一般不用這樣的配置),例如訪問http://localhost:8087/product-service/product/9 ,中的product-service為服務(wù)的名字
server:port: 8087
spring:application:name: gateway-nacoscloud:nacos:discovery:server-addr: 192.168.11.47:18848username: nacospassword: nacosgateway:discovery:locator:enabled: true #是否啟動(dòng)自動(dòng)識(shí)別nacos服務(wù)(約定大于配置)
注意:若要使用自定義配置,則“不能開啟注冊(cè)中心的路由功能”,否則自定義的策略會(huì)失,設(shè)置中心路由功能為false
server:port: 8087
spring:application:name: gateway-nacoscloud:nacos:discovery:server-addr: 192.168.11.47:18848username: nacospassword: nacosgateway:discovery:locator:enabled: false #是否啟動(dòng)自動(dòng)識(shí)別nacos服務(wù)(約定大于配置)
查看網(wǎng)關(guān)內(nèi)置斷言官網(wǎng)文檔,如果用上時(shí)間可以設(shè)置獲取使用方法:ZonedDateTime.now(),獲取
內(nèi)置斷言例子,日期2024-01-20T17:42:47都可以訪問,超過時(shí)間訪問返回404
server:port: 8087
spring:application:name: gateway-nacoscloud:nacos:discovery:server-addr: 192.168.11.47:18848username: nacospassword: nacosgateway:routes: #路由數(shù)組[路由 就是指定當(dāng)請(qǐng)求滿足什么條件的時(shí)候轉(zhuǎn)到哪個(gè)微服務(wù)]- id: product_route #當(dāng)前路由的標(biāo)識(shí),要求唯-uri: http://localhost:8086 #請(qǐng)求要轉(zhuǎn)發(fā)到的地址order: 1 #路由的優(yōu)先級(jí),數(shù)字越小級(jí)別越高predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)- Path=/product-service/** #當(dāng)請(qǐng)求路徑滿足Path指定的規(guī)則時(shí),才進(jìn)行路由轉(zhuǎn)發(fā)- Before=2024-08-20T17:42:47.789-07:00[America/Denver]filters: #過濾器,請(qǐng)求在傳遞過程中可以通過過濾器對(duì)其進(jìn)行一定的修改- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑,- id: stock-nacos #當(dāng)前路由的標(biāo)識(shí),要求唯-uri: http://localhost:8085 #請(qǐng)求要轉(zhuǎn)發(fā)到的地址order: 1 #路由的優(yōu)先級(jí),數(shù)字越小級(jí)別越高predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)- Path=/stock-nacos/** #當(dāng)請(qǐng)求路徑滿足Path指定的規(guī)則時(shí),才進(jìn)行路由轉(zhuǎn)發(fā)- Before=2024-08-20T17:42:47.789-07:00[America/Denver]filters: #過濾器,請(qǐng)求在傳遞過程中可以通過過濾器對(duì)其進(jìn)行一定的修改- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑,
內(nèi)部斷言的類名是有斷言前綴和后綴組成如下
Path+RoutePredicateFactory
RemoteAddr+RoutePredicateFactory
RemoteAddr+RoutePredicateFactory
Header+RoutePredicateFactory
…
- RemoteAddr=192.168.1.1/24
-
基于Cookie的斷言工廠
- CookieRoutePredicateFactory:接收兩個(gè)參數(shù),cookie 名字和一個(gè)正則表達(dá)式。 判斷請(qǐng)求cookie是否具有給定名稱且值與正則表達(dá)式匹配。
- RemoteAddr=chocolate, ch.
-
基于Header的斷言工廠
- HeaderRoutePredicateFactory:接收兩個(gè)參數(shù),標(biāo)題名稱和正則表達(dá)式,判斷請(qǐng)求Header是否具有給定名稱且值與正則表達(dá)式匹配。
- Header=X-Request-Id,\d+
- Host=**.testhost.org
基于Method請(qǐng)求方法的
- Method=GET
#多個(gè)路徑使用逗號(hào),隔開
- Path=/foo/{segment}1 , /product/add
-
基于Query請(qǐng)求參數(shù)的斷言工廠
- QueryRoutePredicateFactory:接收兩個(gè)參數(shù),請(qǐng)求param和正則表達(dá)式,判斷請(qǐng)求參數(shù)是否具有給定名稱且值與正則表達(dá)式匹配,
- Query=baz, ba.
基于Path請(qǐng)求路徑的斷言工廠
自定義路由斷言工廠
可以查看路徑路由的斷言工廠,選擇AbstractRoutePredicateFactory按Ctrl+H既可以顯示出全部的路由斷言工廠,可以復(fù)制一份修改成自定義的斷言工廠
自定義路由斷言工廠需要繼承 AbstadRoutepredicatefacdoy類,重寫 ap)y方法的透輯,在apy方法中可以通過 excthange.geiequest) 拿到 serneiHpReque 對(duì)象,從而可以獲取到清求的參數(shù)、請(qǐng)求方式、請(qǐng)求頭等信息
1. 必須spring組件 bean
2. 類必須加上RoutePredicateFactory作為結(jié)尾(底層的處理的約定大于配置自定會(huì)讀取到的)
3. 必須繼承AbstractRoutePredicateFactory
4. 必須聲明靜態(tài)內(nèi)部類 聲明屬性來接收 配置文件中對(duì)應(yīng)的斷言的信息
5. 需要結(jié)合shortcutFieldOrder進(jìn)行綁定
6. 通過apply進(jìn)行邏輯判斷 true就是匹配成功 false匹配失敗
自定義路由斷言工廠類
package com.test.gate.config;import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;/*** @Description:* @Author: xu* @Data: 2024-2024/4/11-21* @Version: V1.0*/
@Component
public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {public CheckAuthRoutePredicateFactory() {super(Config.class);}public List<String> shortcutFieldOrder() {return Arrays.asList("param");}public Predicate<ServerWebExchange> apply(final Config config) {return new GatewayPredicate() {public boolean test(ServerWebExchange exchange) {if (config.getParam().equals("zhangSan")) {return true;}return false;}public Object getConfig() {return config;}public String toString() {return String.format("Query: param=%s regexp=%s", config.getParam());}};}@Validatedpublic static class Config {private String param;public Config() {}public String getParam() {return this.param;}public void setParam(String param) {this.param = param;}}
}
yml配置(如果一個(gè)路由里面有多個(gè)斷言條件是且的關(guān)系,都需要滿足才跳轉(zhuǎn)uri)
server:port: 8087
spring:application:name: gateway-nacoscloud:nacos:discovery:server-addr: 192.168.11.47:18848username: nacospassword: nacosgateway:
# discovery:
# locator:
# enabled: true #是否啟動(dòng)自動(dòng)識(shí)別nacos服務(wù)(約定大于配置)routes: #路由數(shù)組[路由 就是指定當(dāng)請(qǐng)求滿足什么條件的時(shí)候轉(zhuǎn)到哪個(gè)微服務(wù)]- id: product_route #當(dāng)前路由的標(biāo)識(shí),要求唯-uri: http://localhost:8086 #請(qǐng)求要轉(zhuǎn)發(fā)到的地址order: 1 #路由的優(yōu)先級(jí),數(shù)字越小級(jí)別越高predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)- Path=/product-service/**,/ddd/s #當(dāng)請(qǐng)求路徑滿足Path指定的規(guī)則時(shí),才進(jìn)行路由轉(zhuǎn)發(fā)- Before=2024-08-20T17:42:47.789-07:00[America/Denver]- CheckAuth=zhangSan1filters: #過濾器,請(qǐng)求在傳遞過程中可以通過過濾器對(duì)其進(jìn)行一定的修改- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑,
查看網(wǎng)關(guān)各種局部過濾器官網(wǎng)
自定義網(wǎng)關(guān)過濾器和自定義斷言都全部類似
繼承AbstractNameValueGatewavFilterFactory日我們的自定義名稱必須要以GatewavFiterFactorv結(jié)尾并交給spring管理
package com.test.gate.config;import com.alibaba.nacos.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;import java.util.Arrays;
import java.util.List;/*** @Description:* @Author: xu* @Data: 2024-2024/4/12-11* @Version: V1.0*/
@Componentpublic class CheckAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<CheckAuthGatewayFilterFactory.Config> {private static Logger log = LoggerFactory.getLogger(CheckAuthGatewayFilterFactory.class);public List<String> shortcutFieldOrder() {return Arrays.asList("name");}@Overridepublic GatewayFilter apply(Config config) {return (exchange, chain) -> {log.info("調(diào)用checkAuthGatewayFilterFactory==="+ config.getName());String name = exchange.getRequest().getQueryParams().getFirst("name");if (StringUtils.isNotBlank(name)) {if (config.getName().equals(name)) {chain.filter(exchange);} else {//返回404exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);exchange.getResponse().setComplete();}//1 正常請(qǐng)求chain.filter(exchange);}return null;};}public static class Config {private String name;public Config() {}public String getName() {return this.name;}public void setName(String prefix) {this.name = name;}}
}
server:port: 8087
spring:application:name: gateway-nacoscloud:nacos:discovery:server-addr: 192.168.11.47:18848username: nacospassword: nacosgateway:
# discovery:
# locator:
# enabled: true #是否啟動(dòng)自動(dòng)識(shí)別nacos服務(wù)(約定大于配置)routes: #路由數(shù)組[路由 就是指定當(dāng)請(qǐng)求滿足什么條件的時(shí)候轉(zhuǎn)到哪個(gè)微服務(wù)]- id: product_route #當(dāng)前路由的標(biāo)識(shí),要求唯-uri: http://localhost:8086 #請(qǐng)求要轉(zhuǎn)發(fā)到的地址order: 1 #路由的優(yōu)先級(jí),數(shù)字越小級(jí)別越高predicates: #斷言(就是路由轉(zhuǎn)發(fā)要滿足的條件)- Path=/product-service/**,/ddd/s #當(dāng)請(qǐng)求路徑滿足Path指定的規(guī)則時(shí),才進(jìn)行路由轉(zhuǎn)發(fā)- Before=2024-08-20T17:42:47.789-07:00[America/Denver]- CheckAuth=zhangSan1filters: #過濾器,請(qǐng)求在傳遞過程中可以通過過濾器對(duì)其進(jìn)行一定的修改- StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉1層路徑,- CheckAuth=lisi
全局過濾器(Global Filters)配置
自定義全局過濾器(Global Filters)配置類(一般都是實(shí)現(xiàn)認(rèn)證或者授權(quán),或者做日記記錄,不需要在配置文件做任何配置)
package com.test.gate.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** @Description:* @Author: xu* @Data: 2024-2024/4/12-20* @Version: V1.0*/
@Component
public class LogGlobalFilter implements GlobalFilter {private static Logger log = LoggerFactory.getLogger(LogGlobalFilter.class);@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//做業(yè)務(wù)處理,授權(quán)或者日記記錄log.info(exchange.getRequest().getPath().value());return chain.filter(exchange);}
}
要啟用 Reactor Netty 訪問日志,請(qǐng)?jiān)O(shè)置-Dreactor,netty.http,server.accessLogEnabled=true,它必須是 Java 系統(tǒng)屬性,而不是 Spring Boot 屬性。如果是jar包啟動(dòng),就將網(wǎng)關(guān)打包成jar包,如下運(yùn)行
java -jar gateway.jar -Dreactor,netty.http,server.accessLogEnabled=true
idea配置網(wǎng)關(guān)日記打印,在vm配置 -Dreactor.netty.http.server.accessLogEnabled=true
將網(wǎng)關(guān)日志記錄全部輸出到日志文件。以下示例創(chuàng)建一個(gè)Logback.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration><!-- 控制臺(tái)輸出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 按天滾動(dòng)的文件輸出 --><appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>G:\temptemptemp\gatewaylog\logfile.log</file> <!-- 修改為你想要保存日志文件的路徑 --><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>G:\temptemptemp\gatewaylog\logfile.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- 指定按日期滾動(dòng)的文件名格式 --><maxHistory>30</maxHistory> <!-- 保留最多30天的歷史日志文件 --></rollingPolicy><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 異步日志輸出 --><appender name="async" class="ch.qos.logback.classic.AsyncAppender"><appender-ref ref="ROLLING_FILE"/> <!-- 將異步 appender 鏈接到文件輸出 --></appender><!-- 記錄器配置 --><logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false"><appender-ref ref="async"/> <!-- 將異步 appender 應(yīng)用于特定的日志記錄器 --><appender-ref ref="STDOUT"/> <!-- 控制臺(tái)輸出 --></logger><!-- 根日志級(jí)別設(shè)置 --><root level="info"><appender-ref ref="STDOUT"/> <!-- 控制臺(tái)輸出 --><appender-ref ref="ROLLING_FILE"/> <!-- 將按天滾動(dòng)的文件輸出器添加到根輸出器中 --></root></configuration>
Gateway跨域配置(CORS Configuration),網(wǎng)關(guān)官網(wǎng)跨域配置
方法一:yml配置文件配置跨域
spring:cloud:gateway:globalcors:cors-configurations:'[/**]': #運(yùn)行跨域訪問的資源allowedOrigins: "https://docs.spring.io" #跨域允許來源allowedMethods:- GET- POST
方法二:通過配置類設(shè)置跨域(注意UrlBasedCorsConfigurationSource 導(dǎo)入的包是import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource)
package com.test.gate.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;/*** @Description:* @Author: xu* @Data: 2024-2024/4/12-22* @Version: V1.0*/
@Configuration
public class CorsConfig {@Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();config.addAllowedMethod("*");config.addAllowedOrigin("*");config.addAllowedHeader("*");UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration("/**", config);return new CorsWebFilter(source);}
}
網(wǎng)關(guān)限流整合sentinel官網(wǎng)
pom.xml添加依賴整合sentinel,和官網(wǎng)配置的有以下不一樣是因?yàn)閟pring-cloud-alibaba-sentinel-gateway這個(gè)依賴比adapter依賴多了SentinelSCGAutoConfiguration自定注入例如很多需要的bean
<!--sentinel整臺(tái)gateway 以前版本使用adapter-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<!--sentinel的依賴-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置文件配置sentinel
# 配置sentinelsentinel:transport:dashboard: 127.0.0.1:8858 #sentiel的dashboard地址