亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

基于SpringCloudGateway實(shí)現(xiàn)微服務(wù)網(wǎng)關(guān)的方式

 更新時(shí)間:2021年12月23日 09:36:32   作者:Java架構(gòu)設(shè)計(jì)  
Spring?Cloud?Gateway是Spring?官方基于Spring?5.0,Spring?Boot?2.0和Project?Reactor?等技術(shù)開(kāi)發(fā)的網(wǎng)關(guān),旨在為微服務(wù)架構(gòu)提供一種簡(jiǎn)單而有效的統(tǒng)一的API路由管理方式,對(duì)SpringCloudGateway實(shí)現(xiàn)微服務(wù)網(wǎng)關(guān)相關(guān)知識(shí)感興趣的朋友一起看看吧

(一)什么是微服務(wù)網(wǎng)關(guān)

后端寫完所有的微服務(wù)之后,最終是要交給前端去調(diào)用。我們都知道每個(gè)微服務(wù)都有各自的端口號(hào),如果前端直接通過(guò)IP加端口的方式去調(diào)用微服務(wù)會(huì)很麻煩。如果想對(duì)請(qǐng)求增加限制也會(huì)變得十分困難。這個(gè)時(shí)候微服務(wù)網(wǎng)關(guān)就出現(xiàn)了。

微服務(wù)網(wǎng)關(guān)又成為API網(wǎng)關(guān),它是系統(tǒng)對(duì)外的唯一入口。APl網(wǎng)關(guān)封裝了系統(tǒng)內(nèi)部架構(gòu),為每個(gè)客戶端提供一個(gè)定制的APl。API網(wǎng)關(guān)方式的核心要點(diǎn)是,所有的客戶端和消費(fèi)端都通過(guò)統(tǒng)一的網(wǎng)關(guān)接入微服務(wù),在網(wǎng)關(guān)層處理所有的非業(yè)務(wù)功能。通常,網(wǎng)關(guān)也是提供REST/HTTP的訪問(wèn)API。服務(wù)端通過(guò)API-GW注冊(cè)和管理服務(wù)。

聽(tīng)起來(lái)有些抽象,下面就做一張圖給大家展示一下:前端的請(qǐng)求統(tǒng)一由微服務(wù)網(wǎng)關(guān)進(jìn)行管理,微服務(wù)網(wǎng)關(guān)可以調(diào)用各個(gè)微服務(wù),同時(shí)自身還有多種功能。

API網(wǎng)關(guān)的職責(zé)有身份驗(yàn)證、監(jiān)控、負(fù)載均衡、緩存、請(qǐng)求分片與管理、靜態(tài)響應(yīng)處理,最重要的功能是和外界聯(lián)系。

常見(jiàn)的API網(wǎng)關(guān)實(shí)現(xiàn)方式有Zuul,traefix,Spring Cloud Gateway等等。目前主流的微服務(wù)網(wǎng)關(guān)是Spring Cloud Gateway。

(二)Spring Cloud Gateway網(wǎng)關(guān)

Spring Cloud Gateway是Spring 官方基于Spring 5.0,Spring Boot 2.0和Project Reactor 等技術(shù)開(kāi)發(fā)的網(wǎng)關(guān),旨在為微服務(wù)架構(gòu)提供一種簡(jiǎn)單而有效的統(tǒng)一的API路由管理方式,統(tǒng)一訪問(wèn)接口。Spring Cloud Gateway作為Spring Cloud 生態(tài)系中的網(wǎng)關(guān),目標(biāo)是替代Netflix ZUUL,其不僅提供統(tǒng)一的路由方式,并且基于Filter鏈的方式提供了網(wǎng)關(guān)基本的功能,例如:安全,監(jiān)控/埋點(diǎn),和限流等。

2.1 核心概念:

路由(route):路由是網(wǎng)關(guān)最基礎(chǔ)的部分,路由信息由一個(gè)ID,一個(gè)目的URL,一組斷言工廠和一組Filter組成。

斷言(predicates):java8中的斷言函數(shù),Spring Cloud Gateway中的斷言函數(shù)允許開(kāi)發(fā)者去定義匹配來(lái)自Http Request中的任何信息。當(dāng)斷言為真時(shí),則匹配路由。

過(guò)濾器(filter):對(duì)請(qǐng)求和響應(yīng)進(jìn)行過(guò)濾

下面通過(guò)實(shí)踐來(lái)操作微服務(wù)網(wǎng)關(guān),本項(xiàng)目有依賴于Nacos與Sentinel,如果不需要這部分的內(nèi)容可以在配置文件中去除。

2.2 搭建環(huán)境:

1、引入工程導(dǎo)入依賴

創(chuàng)建api_gateway_server工程,在工程中的pom.xml中導(dǎo)入依賴,項(xiàng)目全局依賴如下:

<?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>
    <groupId>com.javayz</groupId>
    <artifactId>nacos-discovery-spring-cloud-gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>nacos-discovery-spring-cloud-gateway</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <projec.build.sourceEncoding>UTF-8</projec.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.0.RELEASE</spring-boot.version>
        <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
 
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
 
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
 
        <!--springcloudgateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
 
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>
 
    <!--當(dāng)前項(xiàng)目繼承的依賴-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
 
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
 
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
 
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
</project>

2、配置啟動(dòng)類

創(chuàng)建GatewayApplication類

@EnableDiscoveryClient
@SpringBootApplication
public class NacosDiscoverySpringCloudGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(NacosDiscoverySpringCloudGatewayApplication.class, args);
    }
}

3、編寫配置文件

這里對(duì)配置文件的編寫使用.yml格式的配置文件,在resource文件夾下創(chuàng)建applicaiion.yml。這里需要注意的是gateway下routes的配置,首先用id自定義網(wǎng)關(guān);接著定義uri,意思是當(dāng)訪問(wèn)的是9090端口(即訪問(wèn)的是網(wǎng)關(guān)時(shí)),就自動(dòng)把ip和端口號(hào)變成該uri;最后寫斷言predicates,這里的Path=/index/** 指得是自動(dòng)匹配 /index/**的路徑。當(dāng)請(qǐng)求地址為http://localhost:9090/index/1時(shí),微服務(wù)網(wǎng)關(guān)會(huì)去訪問(wèn)http://nacos-discovery-consumer/index/1,這就是微服務(wù)網(wǎng)關(guān)調(diào)用微服務(wù)的功能。

server:
  port: 9090
spring:
  application:
    name: nacos-discovery-spring-cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #啟用discoveryClient網(wǎng)關(guān)集成,實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)
      routes:
        - id: route1
          uri: lb://nacos-discovery-consumer  #lb://表示負(fù)載均衡
          predicates:  #判斷條件
            - Path=/test,/index/**

(三) 路由配置詳解

路由斷言中有許多匹配規(guī)則,之前只介紹了Path,其實(shí)還有許多匹配規(guī)則

predicates:
    #匹配一個(gè)時(shí)間,在這個(gè)時(shí)間之后發(fā)生的請(qǐng)求才能訪問(wèn)(格式是ZonedDateTime)
    - After=2021-03-14T11:31:08.377+08:00[Asia/Shanghai] 
    #匹配一個(gè)時(shí)間,在這個(gè)時(shí)間之前發(fā)生的請(qǐng)求才能訪問(wèn)(ZonedDateTime)
    - Before=2021-03-14T11:31:08.377+08:00[Asia/Shanghai]
    #匹配兩個(gè)時(shí)間,在這個(gè)時(shí)間之間才能訪問(wèn)
    - Between=2021-03-14T11:31:08.377+08:00[Asia/Shanghai],2021-03-14T12:31:08.377+08:00[Asia/Shanghai] #路由斷言之間
    #路由斷言Cookie匹配,匹配給定名稱(如master)或者正則表達(dá)式,如下面配置,請(qǐng)求的cookie中必須有token=master才能訪問(wèn)
    - Cookie=token,master
    #根據(jù)請(qǐng)求頭信息匹配,使用方式和cookie類似
    - Header=XXX,XXX
    #根據(jù)host地址匹配
    - Host=**.somehost.org   
    #根據(jù)請(qǐng)求方法匹配
    - Method=GET  
    #根據(jù)請(qǐng)求路徑進(jìn)行匹配 
    - Path=***   
    #根據(jù)參數(shù)匹配,如果配置為token,則所有的請(qǐng)求必須要帶上token=XXX
   - Query=token
   #根據(jù)遠(yuǎn)程IP匹配
   - RemoteAddr=192.168.1.1/24    
   #權(quán)重,第一個(gè)參數(shù)是組名,第二個(gè)參數(shù)是權(quán)重,兩個(gè)route下配置不同權(quán)重,會(huì)根據(jù)權(quán)重負(fù)載訪問(wèn)
   - Weight=group1,8

定義請(qǐng)求路徑時(shí),我們還可以據(jù)微服務(wù)名稱拉取請(qǐng)求路徑,下面是兩種不同方法定義uri,實(shí)現(xiàn)同樣的功能。

uri: http://127.0.0.1:9001  #當(dāng)訪問(wèn)9090端口時(shí),自動(dòng)把ip和端口替換為此uri
uri: lb://userservice #根據(jù)微服務(wù)名稱拉取請(qǐng)求路徑

總體的配置:

server:
  port: 9090
spring:
  application:
    name: nacos-discovery-spring-cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #啟用discoveryClient網(wǎng)關(guān)集成,實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)
      routes:
        - id: route1
          uri: lb://nacos-discovery-consumer  #lb://表示負(fù)載均衡
          predicates:  #判斷條件
            - Path=/test,/index/**,/**
 
    nacos:
      discovery:
        server-addr: 192.168.78.128:8848
      username: nacos
      password: nacos
 
    sentinel:
      eager: true
      transport:
        dashboard: localhost:8080

3.1 自定義斷言配置

自定義斷言的實(shí)現(xiàn)分為兩步,假設(shè)我們現(xiàn)在要實(shí)現(xiàn)一個(gè)自定義的過(guò)濾器,規(guī)則是必須攜帶一個(gè)token,并且token要等于指定的值。

1、定義配置類:這里包含在配置文件要傳入的對(duì)象值

@Data
public class TokenConfig {
    private String token;
}

2、定義路由斷言工廠:首先是命名必須是XXXRoutePredicateFactory,繼承 AbstractRoutePredicateFactory

@Slf4j
@Component
public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<TokenConfig> {
    public TokenRoutePredicateFactory(){
        super(TokenConfig.class);
    }
    //用來(lái)把配置中的值變成一個(gè)集合
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("token");
    }
    //通過(guò)jdk1.8的斷言接口來(lái)返回true或者false,如果是true表示過(guò)濾器不攔截
    @Override
    public Predicate<ServerWebExchange> apply(TokenConfig config) {
        return exchange ->{
            //獲取request請(qǐng)求參數(shù)
            MultiValueMap<String,String> valueMap=exchange.getRequest().getQueryParams();
            boolean flag=false;
            List<String> list=new ArrayList<>();
            //將request請(qǐng)求的value保存到集合里
            valueMap.forEach((k,v)->{
                list.addAll(v);
            });
            //判斷有沒(méi)有和配置文件中相同的值
            for (String s:list){
                log.info("Token"+s);
                if (StringUtils.equalsIgnoreCase(s,config.getToken())){
                    flag=true;
                    break;
                }
            }
            return flag;
        };
    }
}

最后在斷言處寫上我們自定義的內(nèi)容:

predicates:  #判斷條件
  - Path=/test,/index/**,/**
  - Token=javayz

只有鏈接是http://localhost:9090/sentinel/test1?token=javayz帶上token=javayz的請(qǐng)求才能訪問(wèn)。

3.2 斷言不匹配404頁(yè)面自定義

SpringCloudGateway默認(rèn)給出的404頁(yè)面是

這樣的頁(yè)面實(shí)在不友好,我們可以通過(guò)自定義的方式讓他返回一個(gè)JSON字符串

public class MyErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {
 
    public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }
 
    /**
     * 指定響應(yīng)處理方法為JSON處理
     * @param errorAttributes
     * @return
     */
    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(),this::renderErrorResponse);
    }
 
 
    /**
     * 根據(jù)code獲取對(duì)應(yīng)的HttpStatus
     * @param errorAttributes
     * @return
     */
    @Override
    protected int getHttpStatus(Map<String, Object> errorAttributes) {
        return (int) errorAttributes.get("status");
    }
 
    /**
     * 構(gòu)建異常信息
     * @param request
     * @param ex
     * @return
     */
    private String buildMessage(ServerRequest request,Throwable ex){
        StringBuilder builder = new StringBuilder("Failed to handle request:");
        builder.append(request.methodName());
        builder.append(" ");
        builder.append(request.uri());
        if (ex!=null){
            builder.append(ex.getMessage());
        }
        return builder.toString();
    }
 
    /**
     * 返回的json數(shù)據(jù)
     * @param status
     * @param errorMsg
     * @param data
     * @return
     */
    public static Map<String,Object> response(int status,String errorMsg,Object data){
        Map<String,Object> map=new HashMap<>();
        map.put("code",status);
        map.put("message",errorMsg);
        map.put("data",data);
        return map;
    }
}

新建一個(gè)類叫做MyErrorWebExceptionHandler:

再編寫一個(gè)配置類,將自定義的異常頁(yè)面代碼注入到Bean容器中:

@Configuration
public class GatewayConfiguration {
    private final ServerProperties serverProperties;
    private final ApplicationContext applicationContext;
    private final ResourceProperties resourceProperties;
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;
 
    public GatewayConfiguration(ServerProperties serverProperties, ApplicationContext applicationContext, ResourceProperties resourceProperties, ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
        this.serverProperties = serverProperties;
        this.applicationContext = applicationContext;
        this.resourceProperties = resourceProperties;
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }
 
    @Bean("myErrorWebExceptionHandler")
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public ErrorWebExceptionHandler myErrorWebExceptionHandler(ErrorAttributes errorAttributes){
        MyErrorWebExceptionHandler exceptionHandler=new MyErrorWebExceptionHandler(
                errorAttributes,
                this.resourceProperties,
                this.serverProperties.getError(),
                this.applicationContext
        );
        exceptionHandler.setViewResolvers(this.viewResolvers);
        exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
        exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
        return exceptionHandler;
    }
}

最后訪問(wèn)到404就會(huì)以JSON的格式返回,方便調(diào)用方做處理。

(四)Spring Cloud Gateway過(guò)濾器

Spring Cloud Gateway除了具有請(qǐng)求路由功能之外,也支持對(duì)請(qǐng)求的過(guò)濾。

生命周期:

過(guò)濾器有兩種生命周期,PRE和POST:

PRE:這種過(guò)濾器在請(qǐng)求被路由之前調(diào)用。我們可利用這種過(guò)濾器實(shí)現(xiàn)身份驗(yàn)證、在集群中選擇請(qǐng)求的微服務(wù)、記錄調(diào)試信息等。

POST:這種過(guò)濾器在路由到微服務(wù)以后執(zhí)行。這種過(guò)濾器可用來(lái)為響應(yīng)添加標(biāo)準(zhǔn)的HTTP Header、收集統(tǒng)計(jì)信息和指標(biāo)、將響應(yīng)從微服務(wù)發(fā)送給客戶端等。

過(guò)濾器類型:

GatewayFilter:應(yīng)用到單個(gè)路由或者一個(gè)分組的路由上

GlobalFilter:應(yīng)用到所有的路由上

局部過(guò)濾器可以使用Spring Cloud Gateway內(nèi)置的方法,在官網(wǎng)中(docs.spring.io/spring-clou…

官方過(guò)濾器:

這里簡(jiǎn)單介紹幾個(gè):

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue

添加AddRequestHeader過(guò)濾器后,每次請(qǐng)求轉(zhuǎn)發(fā)給微服務(wù)后都會(huì)在header種增加一個(gè)X-Request-red。

- AddRequestParameter=red, blue

添加Request參數(shù),每次請(qǐng)求轉(zhuǎn)發(fā)給微服務(wù)后都會(huì)增加一個(gè)請(qǐng)求參數(shù)。

自定義全局過(guò)濾器: 創(chuàng)建一個(gè)Filter包,在包下新建GatewayFilter類,自定義全局過(guò)濾器需要繼承GlobalFilter, Ordered接口,并重寫接口的兩個(gè)方法

@Component
public class GatewayFilter implements GlobalFilter, Ordered {
    //在里面寫過(guò)濾器的邏輯
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("進(jìn)入了過(guò)濾器");
        //表示繼續(xù)向下執(zhí)行
        return chain.filter(exchange);
    }
    //過(guò)濾器的優(yōu)先級(jí),數(shù)值越小,優(yōu)先級(jí)越高
    @Override
    public int getOrder() {
        return 0;
    }
}

通過(guò)訪問(wèn)可以看到控制臺(tái)上出現(xiàn)了打印的信息。

模擬用戶認(rèn)證過(guò)程:

全局過(guò)濾器可以實(shí)現(xiàn)對(duì)全局的用戶驗(yàn)證。修改gatewayFilter,編寫失敗的邏輯,如果獲取到的request請(qǐng)求中第一個(gè)屬性不是access-token或?yàn)榭?,則返回HttpStatus.UNAUTHORIZED的報(bào)錯(cuò)

@Component
public class GatewayFilter implements GlobalFilter, Ordered {
    //在里面寫過(guò)濾器的邏輯
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("進(jìn)入了過(guò)濾器");
        String token = exchange.getRequest().getQueryParams().getFirst("access-token");
        if (token==null){
            //如果不存在,認(rèn)證失敗
            System.out.println("沒(méi)有登陸");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
    //過(guò)濾器的優(yōu)先級(jí),數(shù)值越小,優(yōu)先級(jí)越高
    @Override
    public int getOrder() {
        return 0;
    }
}

在瀏覽器中輸入:http://localhost:9090/sentinel/test1,出現(xiàn)報(bào)錯(cuò),因?yàn)闆](méi)有access-token

在瀏覽器中輸入:http://localhost:9090/sentinel/test1?access-token=1,獲取正確結(jié)果。

(五) 網(wǎng)關(guān)限流

在實(shí)際環(huán)境中會(huì)遇到這樣的問(wèn)題,同一時(shí)間會(huì)有許多請(qǐng)求去調(diào)用微服務(wù),大量請(qǐng)求的進(jìn)入很有可能導(dǎo)致微服務(wù)被破環(huán),因此限流就變得很重要。

5.1 常見(jiàn)的一些限流算法:

計(jì)數(shù)器算法:設(shè)定一個(gè)單位時(shí)間內(nèi)的計(jì)數(shù)值,如果單位時(shí)間內(nèi)訪問(wèn)的請(qǐng)求大于這個(gè)設(shè)定的值,則之后的請(qǐng)求都拒絕。直到單位時(shí)間內(nèi)的值低于這個(gè)值才繼續(xù)接收。

漏桶算法:我們可以把漏桶算法想象成一個(gè)漏斗。請(qǐng)求進(jìn)來(lái)時(shí)先到漏斗中,然后按設(shè)定好的輸出速率分配到微服務(wù)上。當(dāng)一下子有很多請(qǐng)求進(jìn)來(lái)時(shí),只能在漏斗上等著。為了控制流量,需要設(shè)置兩個(gè)變量:一個(gè)是桶的大小,另一個(gè)是漏斗流出的速率。

令牌桶算法:令牌桶算法是對(duì)漏桶算法的一種改進(jìn),相比于漏桶算法,令牌桶算法能允許一定程度的突發(fā)調(diào)用。令牌桶算法的原理:在令牌桶算法中,存在一個(gè)桶,用來(lái)存放固定數(shù)量的令牌,令牌會(huì)以一定速率放到桶中,桶中的令牌滿了之后就不會(huì)再放令牌。當(dāng)一個(gè)請(qǐng)求來(lái)臨時(shí),要先在令牌桶中拿到一個(gè)令牌,才能去調(diào)用微服務(wù),當(dāng)令牌桶中沒(méi)有令牌的時(shí)候,后來(lái)到的請(qǐng)求就需要等待。令牌桶算法除了可以限流,還允許一定程度的突發(fā)調(diào)用:比如一個(gè)令牌桶的容量是100,在沒(méi)有請(qǐng)求的時(shí)候,令牌桶中的令牌數(shù)量是滿的。此時(shí)如果突然來(lái)了100個(gè)請(qǐng)求,那么這100個(gè)請(qǐng)求都能被立刻執(zhí)行。

5.2 集成Sentinel進(jìn)行限流

添加依賴

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
    <version>1.7.2</version>
</dependency>

添加Sentinel配置:

spring:
  cloud:
    sentinel:
      eager: true
      transport:
        dashboard: localhost:8080

將Sentinel過(guò)濾器注入到Bean容器中

@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter(){
    return new SentinelGatewayFilter();
}

這樣就可以用Sentinel的方式對(duì)網(wǎng)關(guān)進(jìn)行限流了。

對(duì)于限流后的錯(cuò)誤提示,我們可以修改默認(rèn)錯(cuò)誤提示方式,改成自定義或者跳轉(zhuǎn)到錯(cuò)誤頁(yè)面:

@Configuration
public class GatewayConfiguration {
    private final ServerProperties serverProperties;
    private final ApplicationContext applicationContext;
    private final ResourceProperties resourceProperties;
    private final List<ViewResolver> viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;
 
    public GatewayConfiguration(ServerProperties serverProperties, ApplicationContext applicationContext, ResourceProperties resourceProperties, ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
        this.serverProperties = serverProperties;
        this.applicationContext = applicationContext;
        this.resourceProperties = resourceProperties;
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }
 
    //自定義一個(gè)錯(cuò)誤處理
    @Bean(name = "myBlockRequestHandler")
    public BlockRequestHandler myBlockRequestHandler(){
        BlockRequestHandler blockRequestHandler=new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                return ServerResponse.status(HttpStatus.BAD_GATEWAY)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue("服務(wù)被限流了"));
            }
        };
        return blockRequestHandler;
    }
 
    //用自定義的handler替換掉默認(rèn)的,或者重定向
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(BlockRequestHandler myBlockRequestHandler){
        //自定義Block處理
        GatewayCallbackManager.setBlockHandler(myBlockRequestHandler);
 
        //重定向block處理
        //GatewayCallbackManager.setBlockHandler(new RedirectBlockRequestHandler("http://www.baidu.com"));
        return new SentinelGatewayBlockExceptionHandler(viewResolvers,serverCodecConfigurer);
    }
 
    @Bean
    @Order(-1)
    public GlobalFilter sentinelGatewayFilter(){
        return new SentinelGatewayFilter();
    }
}

5.3 網(wǎng)關(guān)實(shí)現(xiàn)跨域

這個(gè)和SpringBoot中解決跨域的思路類似,配置CorsConfig

@Configuration
public class CorsConfig {
 
    @Bean
    public CorsWebFilter corsWebFilter(){
        CorsConfiguration configuration=new CorsConfiguration();
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        configuration.addAllowedOrigin("*");
 
        UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/*",configuration);
        return new CorsWebFilter(source);
    }
}

(六)總結(jié)

本章內(nèi)容比較多,但是把SpringCloudGateway基本會(huì)遇到的內(nèi)容都講解了一遍,希望對(duì)你有幫助。

到此這篇關(guān)于基于SpringCloudGateway實(shí)現(xiàn)微服務(wù)網(wǎng)關(guān)的文章就介紹到這了,更多相關(guān)SpringCloudGateway?微服務(wù)網(wǎng)關(guān)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決FileWriter 寫入文本不換行的問(wèn)題

    解決FileWriter 寫入文本不換行的問(wèn)題

    這篇文章主要介紹了解決FileWriter 寫入文本不換行的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java中的NumberFormatException異常原因以及解決方案詳解

    Java中的NumberFormatException異常原因以及解決方案詳解

    這篇文章主要介紹了Java中的NumberFormatException異常原因以及解決方案詳解,NumberFormatException 是 Java 中的一個(gè)異常類,通常在字符串轉(zhuǎn)換為數(shù)字的過(guò)程中發(fā)生,它表示一個(gè)無(wú)效的數(shù)字格式,即字符串無(wú)法被正確解析為數(shù)字,需要的朋友可以參考下
    2024-02-02
  • MybatisPlus中selectPage的使用方法

    MybatisPlus中selectPage的使用方法

    本文主要介紹了MybatisPlus中selectPage的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 使用迭代器模式來(lái)進(jìn)行Java的設(shè)計(jì)模式編程

    使用迭代器模式來(lái)進(jìn)行Java的設(shè)計(jì)模式編程

    這篇文章主要介紹了使用迭代器模式來(lái)進(jìn)行Java的設(shè)計(jì)模式編程,文中對(duì)迭代器模式中的容器封裝方面的知識(shí)進(jìn)行了講解,需要的朋友可以參考下
    2016-02-02
  • mybatis的foreach標(biāo)簽語(yǔ)法報(bào)錯(cuò)的解決

    mybatis的foreach標(biāo)簽語(yǔ)法報(bào)錯(cuò)的解決

    這篇文章主要介紹了mybatis的foreach標(biāo)簽語(yǔ)法報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Spring Boot Redis 集成配置詳解

    Spring Boot Redis 集成配置詳解

    本篇文章主要介紹了Spring Boot Redis 集成配置詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • Java獲取隨機(jī)數(shù)的n種方法

    Java獲取隨機(jī)數(shù)的n種方法

    項(xiàng)目中,我們常常會(huì)用到隨機(jī)數(shù),本文主要介紹了Java獲取隨機(jī)數(shù)的n種方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-11-11
  • Springboot之@Async不執(zhí)行原因及分析

    Springboot之@Async不執(zhí)行原因及分析

    這篇文章主要介紹了Springboot之@Async不執(zhí)行原因及分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • java程序員如何編寫更好的單元測(cè)試的7個(gè)技巧

    java程序員如何編寫更好的單元測(cè)試的7個(gè)技巧

    測(cè)試是開(kāi)發(fā)的一個(gè)非常重要的方面,可以在很大程度上決定一個(gè)應(yīng)用程序的命運(yùn)。良好的測(cè)試可以在早期捕獲導(dǎo)致應(yīng)用程序崩潰的問(wèn)題,但較差的測(cè)試往往總是導(dǎo)致故障和停機(jī)。本文主要介紹java程序員編寫更好的單元測(cè)試的7個(gè)技巧。下面跟著小編一起來(lái)看下吧
    2017-03-03
  • druid ParserException類錯(cuò)誤問(wèn)題及解決

    druid ParserException類錯(cuò)誤問(wèn)題及解決

    這篇文章主要介紹了druid ParserException類錯(cuò)誤問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評(píng)論