欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring cloud 限流的多種方式

 更新時(shí)間:2021年06月09日 11:31:25   作者:小碼哥Damon  
在頻繁的網(wǎng)絡(luò)請(qǐng)求時(shí),服務(wù)有時(shí)候也會(huì)受到很大的壓力,尤其是那種網(wǎng)絡(luò)攻擊,非法的。這樣的情形有時(shí)候需要作一些限制。本文主要介紹了兩種限流方法,感興趣的可以了解一下

在頻繁的網(wǎng)絡(luò)請(qǐng)求時(shí),服務(wù)有時(shí)候也會(huì)受到很大的壓力,尤其是那種網(wǎng)絡(luò)攻擊,非法的。這樣的情形有時(shí)候需要作一些限制。例如:限制對(duì)方的請(qǐng)求,這種限制可以有幾個(gè)依據(jù):請(qǐng)求IP、用戶(hù)唯一標(biāo)識(shí)、請(qǐng)求的接口地址等等。

當(dāng)前限流的方式也很多:Spring cloud 中在網(wǎng)關(guān)本身自帶限流的一些功能,基于 redis 來(lái)做的。同時(shí),阿里也開(kāi)源了一款:限流神器 Sentinel。今天我們主要圍繞這兩塊來(lái)實(shí)戰(zhàn)微服務(wù)的限流機(jī)制。

首先講 Spring cloud 原生的限流功能,因?yàn)橄蘖骺梢允菍?duì)每個(gè)服務(wù)進(jìn)行限流,也可以對(duì)于網(wǎng)關(guān)統(tǒng)一作限流處理。

一、實(shí)戰(zhàn)基于 Spring cloud Gateway 的限流

pom.xml引入依賴(lài):

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    </dependency>

其基礎(chǔ)是基于redis,所以:

spring:
  application:
    name: gateway-service
  redis: #redis相關(guān)配置
    database: 8
    host: 10.12.15.5
    port: 6379
    password: 123456 #有密碼時(shí)設(shè)置
    jedis:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
    timeout: 10000ms

接下來(lái)需要注入限流策略的 bean:

@Primary
  @Bean(value = "ipKeyResolver")
  KeyResolver ipKeyResolver() {
      return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
      //return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
      //return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
  }

 
  @Bean(value = "apiKeyResolver")
  KeyResolver apiKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getPath().value());
  }

  
  @Bean(value = "userKeyResolver")
  KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
  }

這里引入ipKeyResolver、apiKeyResolver、userKeyResolver三種策略,可以利用注解 @Primary 來(lái)決定其中一個(gè)被使用。

注入bean后,需要在配置中備用:

spring:
  application:
    name: gateway-service
  redis: #redis相關(guān)配置
    database: 8
    host: 10.12.15.5
    port: 6379
    password: 123456 #有密碼時(shí)設(shè)置
    jedis:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
    timeout: 10000ms

后面是限流的主要配置:

spring
  cloud:
    gateway:
      routes: #路由配置:參數(shù)為一個(gè)List
      - id: cas-server #唯一標(biāo)識(shí)
        uri: lb://cas-server-service #轉(zhuǎn)發(fā)的地址,寫(xiě)服務(wù)名稱(chēng)
        order: -1
        predicates:
        - Path=/cas-server/** #判斷匹配條件,即地址帶有/ribbon/**的請(qǐng)求,會(huì)轉(zhuǎn)發(fā)至lb:cas-server-service
        filters:
        - StripPrefix=1 #去掉Path前綴,參數(shù)為1代表去掉/ribbon

        - name: RequestRateLimiter #基于redis的Gateway的自身限流
          args:
            redis-rate-limiter.replenishRate: 1  # 允許用戶(hù)每秒處理多少個(gè)請(qǐng)求
            redis-rate-limiter.burstCapacity: 3  # 令牌桶的容量,允許在一秒鐘內(nèi)完成的最大請(qǐng)求數(shù)
            key-resolver: "#{@ipKeyResolver}" #SPEL表達(dá)式取的對(duì)應(yīng)的bean

      - id: admin-web
        uri: lb://admin-web-service
        order: -1
        predicates:
        - Path=/admin-web/**
        filters:
        - StripPrefix=1

        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 1  # 允許用戶(hù)每秒處理多少個(gè)請(qǐng)求
            redis-rate-limiter.burstCapacity: 3  # 令牌桶的容量,允許在一秒鐘內(nèi)完成的最大請(qǐng)求數(shù)
            key-resolver: "#{@ipKeyResolver}" #SPEL表達(dá)式取的對(duì)應(yīng)的bean

這里是在原有的路由基礎(chǔ)上加入 RequestRateLimiter限流過(guò)濾器,包括三個(gè)參數(shù):

- name: RequestRateLimiter #基于redis的Gateway的自身限流
          args:
            redis-rate-limiter.replenishRate: 3  #允許用戶(hù)每秒處理多少個(gè)請(qǐng)求
            redis-rate-limiter.burstCapacity: 5  #令牌桶的容量,允許在一秒鐘內(nèi)完成的最大請(qǐng)求數(shù)
            key-resolver: "#{@ipKeyResolver}" #SPEL表達(dá)式取的對(duì)應(yīng)的bean
  • 其中 replenishRate,其含義表示允許每秒處理請(qǐng)求數(shù);
  • burstCapacity 表示允許在一秒內(nèi)處理的最大請(qǐng)求數(shù);
  • key-resolver 這里采用請(qǐng)求 IP 限流,利用SPEL 表達(dá)式取對(duì)應(yīng)的 bean

寫(xiě)一個(gè)小腳本來(lái)壓測(cè)一下:

for i in $(seq 1 30000); do echo $(expr $i \\* 3 + 1);curl -i -H "Accept: application/json" -H "Authorization:bearer b064d95b-af3f-4053-a980-377c63ab3413" -X GET http://10.10.15.5:5556/order-service/api/order/getUserInfo;done

for i in $(seq 1 30000); do echo $(expr $i \\* 3 + 1);curl -i -H "Accept: application/json" -H "Authorization:bearer b064d95b-af3f-4053-a980-377c63ab3413" -X GET http://10.10.15.5:5556/admin-web/api/user/getCurrentUser;done

上面兩個(gè)腳本分別對(duì)2個(gè)服務(wù)進(jìn)行壓測(cè),打印結(jié)果:

{"message":{"status":200,"code":0,"message":"success"},"data":"{\"message\":{\"status\":200,\"code\":0,\"message\":\"get user success\"},\"data\":{\"id\":23,\"isAdmin\":1,\"userId\":\"fbb18810-e980-428c-932f-848f3b9e7c84\",\"userType\":\"super_admin\",\"username\":\"admin\",\"realName\":\"super_admin\",\"password\":\"$2a$10$89AqlYKlnsTpNmWcCMvgluRFQ/6MLK1k/nkBpz.Lw6Exh.WMQFH6W\",\"phone\":null,\"email\":null,\"createBy\":\"admin\",\"createTime\":1573119753172,\"updateBy\":\"admin\",\"updateTime\":1573119753172,\"loginTime\":null,\"expireTime\":null,\"remarks\":\"super_admin\",\"delFlag\":0,\"loginType\":null}}"}ex

在用測(cè)試工具Jmeter在同一秒內(nèi)多次請(qǐng)求后:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Remaining: 0
X-RateLimit-Burst-Capacity: 3
X-RateLimit-Replenish-Rate: 1
content-length: 0

expr: syntax error

HTTP/1.1 429 Too Many Requests
X-RateLimit-Remaining: 0
X-RateLimit-Burst-Capacity: 3
X-RateLimit-Replenish-Rate: 1
content-length: 0

expr: syntax error

從上面可以看到,執(zhí)行后,會(huì)出現(xiàn)調(diào)用失敗的情況,狀態(tài)變?yōu)?29 (Too Many Requests) 。

二、基于阿里開(kāi)源限流神器:Sentinel

首先引入依賴(lài):

<!--基于 阿里的sentinel作限流 -->
    <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    </dependency>

在配置文件 application.yaml 文件中配置,需要新增2個(gè)配置:

spring:
  application:
    name: admin-web
  cloud:
    kubernetes:
      discovery:
        all-namespaces: true
    sentinel:
      eager: true #取消Sentinel控制臺(tái)的懶加載
      transport:
        dashboard: 10.12.15.2:8080 #sentinel的Dashboard地址
        port: 8719 #是sentinel應(yīng)用端和控制臺(tái)通信端口
        heartbeat-interval-ms: 500 #心跳時(shí)間
      scg:
        fallback: #scg.fallback為sentinel限流后的響應(yīng)配置
          mode: response
          response-status: 455
          response-body: 已被限流

其中,這里面配置了一個(gè)服務(wù):spring.cloud.sentinel.transport.dashboard,配置的是 sentinel 的 Dashboard 地址。同時(shí) spring.cloud.sentinel.transport.port 這個(gè)端口配置會(huì)在應(yīng)用對(duì)應(yīng)的機(jī)器上啟動(dòng)一個(gè)Http Server,該 Server 會(huì)與 Sentinel 控制臺(tái)做交互。

Sentinel 默認(rèn)為所有的 HTTP 服務(wù)提供限流埋點(diǎn),上面配置完成后自動(dòng)完成所有埋點(diǎn),只需要控制配置限流規(guī)則即可。
這里我們講下通過(guò)注解來(lái)給指定接口函數(shù)加上限流埋點(diǎn),寫(xiě)一個(gè)RestController,在接口函數(shù)上加上注解

@SentinelResource:
@GetMapping(value = "/getToken")
@SentinelResource("getToken")
public Response<Object> getToken(Authentication authentication){
    //Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    authentication.getCredentials();
    OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)authentication.getDetails();
    String token = details.getTokenValue();
    return Response.ok(200, 0, "get token success", token);
}

以上代碼部分完成了,接下來(lái)先安裝SentinelDashBoard,Sentinel DashBoard下載地址:github.com/alibaba/Sentinel/releases。

下載完成后,命令啟動(dòng):

java -jar sentinel-dashboard-1.6.2.jar

默認(rèn)啟動(dòng)端口為8080,訪問(wèn) IP:8080,就可以顯示 Sentinel 的登錄界面,用戶(hù)名與密碼均為sentinel。登錄 Dashboard 成功后,多次訪問(wèn)接口"/getToken",可以在 Dashboard 看到相應(yīng)數(shù)據(jù),這里不展示了。接下來(lái)可以設(shè)置接口的限流功能,在 “+流控” 按鈕點(diǎn)擊打開(kāi)設(shè)置界面,設(shè)置閾值類(lèi)型為 qps,單機(jī)閾值為5。

瀏覽器重復(fù)請(qǐng)求 http://10.10.15.5:5556/admin-web/api/user/getToken 如果超過(guò)閥值就會(huì)出現(xiàn)如下界面信息:
Blocked by Sentinel (flow limiting)

此時(shí),就看到Sentinel 限流起作用了,可以加上 spring.cloud.sentinel.scg.fallback 為sentinel 限流后的響應(yīng)配置,亦可自定義限流異常信息:

@GetMapping(value = "/getToken")
@SentinelResource(value = "getToken", blockHandler = "handleSentinelException", blockHandlerClass = {MySentinelException.class}))
public Response<Object> getToken(Authentication authentication){
    //Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    authentication.getCredentials();
    OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)authentication.getDetails();
    String token = details.getTokenValue();
    return Response.ok(200, 0, "get token success", token);
}

public class MySentinelException {
    public static Response<Object> handleSentinelException(BlockException e) {
        Map<String,Object> map=new HashMap<>();
        logger.info("Oops: " + ex.getClass().getCanonicalName());
        return Response.ok(200, -8, "通過(guò)注解 @SentinelResource 配置限流埋點(diǎn)并自定義限流后的處理邏輯", null);
    }
}

這里講下注解 @SentinelResource 包含以下屬性:

  • value:資源名稱(chēng),必需項(xiàng);
  • entryType:入口類(lèi)型,可選項(xiàng)(默認(rèn)為 EntryType.OUT);
  • blockHandler:blockHandlerClass中對(duì)應(yīng)的異常處理方法名,參數(shù)類(lèi)型和返回值必須和原方法一致;
  • blockHandlerClass:自定義限流邏輯處理類(lèi)

Sentinel 限流邏輯處理完畢了,但每次服務(wù)重啟后,之前配置的限流規(guī)則就會(huì)被清空。因?yàn)槭莾?nèi)存形式的規(guī)則對(duì)象。所以下面就講下用 Sentinel 的一個(gè)特性 ReadableDataSource 獲取文件、數(shù)據(jù)庫(kù)或者配置中心設(shè)置限流規(guī)則,目前支持 Apollo、Nacos、ZK 配置來(lái)管理。

首先回憶一下,一條限流規(guī)則主要由下面幾個(gè)因素組成:

  • resource:資源名,即限流規(guī)則的作用對(duì)象,即為注解 @SentinelResource 的value;
  • count:限流閾值;grade:限流閾值類(lèi)型(QPS 或并發(fā)線(xiàn)程數(shù));
  • limitApp:流控針對(duì)的調(diào)用來(lái)源,若為 default 則不區(qū)分調(diào)用來(lái)源;
  • strategy:基于調(diào)用關(guān)系的限流策略;
  • controlBehavior:流量控制效果(直接拒絕、排隊(duì)等待、勻速器模式)

理解了意思,接下來(lái)通過(guò)文件來(lái)配置:

#通過(guò)文件讀取限流規(guī)則
spring.cloud.sentinel.datasource.ds1.file.file=classpath:flowrule.json
spring.cloud.sentinel.datasource.ds1.file.data-type=json
spring.cloud.sentinel.datasource.ds1.file.rule-type=flow

在resources新建一個(gè)文件,比如 flowrule.json 添加限流規(guī)則:

[
  {
    "resource": "getToken",
    "count": 1,
    "controlBehavior": 0,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  },
  {
    "resource": "resource",
    "count": 1,
    "controlBehavior": 0,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]

重新啟動(dòng)項(xiàng)目,出現(xiàn)如下日志說(shuō)明成功:

DataSource ds1-sentinel-file-datasource start to loadConfig
DataSource ds1-sentinel-file-datasource load 2 FlowRule

如果采用 Nacos 作為配置獲取限流規(guī)則,可在文件中加如下配置:

spring:
  application:
    name: order-service
  cloud:
    nacos:
      config:
        server-addr: 10.10.15.5:8848
      discovery:
        server-addr: 10.10.15.5:8848
    sentinel:
      eager: true
      transport:
        dashboard: 10.10.15.5:8080
      datasource:
        ds1:
          nacos:
            server-addr: 10.10.15.5:8848
            dataId: ${spring.application.name}-flow-rules
            data-type: json
            rule-type: flow

到此這篇關(guān)于Spring cloud 限流的多種方式的文章就介紹到這了,更多相關(guān)Spring cloud 限流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java mybatis框架配置詳解

    java mybatis框架配置詳解

    在本篇文章里小編給大家整理的是一篇關(guān)于java mybatis框架配置詳解內(nèi)容,對(duì)此有興趣的朋友們可以參考下。
    2021-02-02
  • Java實(shí)現(xiàn)簡(jiǎn)單GUI登錄和注冊(cè)界面

    Java實(shí)現(xiàn)簡(jiǎn)單GUI登錄和注冊(cè)界面

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單GUI登錄和注冊(cè)界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Java多態(tài)到底都有啥好處

    Java多態(tài)到底都有啥好處

    Java中的多態(tài)性有兩種類(lèi)型:編譯時(shí)多態(tài)(靜態(tài)綁定)和運(yùn)行時(shí)多態(tài)(動(dòng)態(tài)綁定)。方法重載是靜態(tài)多態(tài)的一個(gè)例子,而方法重寫(xiě)是動(dòng)態(tài)多態(tài)的一個(gè)例子,接下來(lái)通過(guò)本文給大家分享Java多態(tài)到底教了我干啥?有啥好處,一起了解下吧
    2021-05-05
  • 一文掌握J(rèn)ava中List和Set接口的基本使用

    一文掌握J(rèn)ava中List和Set接口的基本使用

    這篇文章主要為大家詳細(xì)介紹Java中List和Set接口,文中通過(guò)示例代碼讓大家能夠輕松掌握List和Set接口的基本使用,感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-07-07
  • Java通過(guò)URL獲取公眾號(hào)文章生成HTML的方法

    Java通過(guò)URL獲取公眾號(hào)文章生成HTML的方法

    這篇文章主要介紹了Java通過(guò)URL獲取公眾號(hào)文章生成HTML的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 詳解lombok @Getter @Setter 使用注意事項(xiàng)

    詳解lombok @Getter @Setter 使用注意事項(xiàng)

    這篇文章主要介紹了詳解lombok @Getter @Setter 使用注意事項(xiàng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • java連接zookeeper實(shí)現(xiàn)zookeeper教程

    java連接zookeeper實(shí)現(xiàn)zookeeper教程

    這篇文章主要介紹了java連接zookeeper實(shí)現(xiàn)zookeeper教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java利用反射動(dòng)態(tài)設(shè)置對(duì)象字段值的實(shí)現(xiàn)

    Java利用反射動(dòng)態(tài)設(shè)置對(duì)象字段值的實(shí)現(xiàn)

    橋梁信息維護(hù)需要做到字段級(jí)別的權(quán)限控制,本文主要介紹了Java利用反射動(dòng)態(tài)設(shè)置對(duì)象字段值的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • MyBatis?Plus?導(dǎo)入IdType失敗的解決

    MyBatis?Plus?導(dǎo)入IdType失敗的解決

    這篇文章主要介紹了MyBatis?Plus?導(dǎo)入IdType失敗的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java?String源碼contains題解重復(fù)疊加字符串匹配

    Java?String源碼contains題解重復(fù)疊加字符串匹配

    這篇文章主要為大家介紹了Java?String源碼contains題解重復(fù)疊加字符串匹配示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11

最新評(píng)論