当前位置:网站首页>API Gateway/API 网关(三) - Kong的使用 - 限流rate limiting(redis)

API Gateway/API 网关(三) - Kong的使用 - 限流rate limiting(redis)

2022-04-23 14:11:00 anron

一、前言

Kong的限流支持三种方式,分别是本地限流(Local)、数据库限流(Cluster)和Redis限流,这三种限流方式采用的限流算法都是计数器法。支持按照秒/分/小时/日/月/年等不同时间单位限流,并且可以组合,例如可以设置每秒最多100次并且每分钟最多1000次。

  • 本地限流(Local),计数器采用的是Nginx的缓存
  • 数据库限流(Cluster),将计数器保存在了数据库里,Kong支持两种数据库,PostgreSQL和Cassandra
  • Redis限流,和本地限流类似,只是将缓存放到了Redis上

接下来配置Kong API网关,使用Redis限流的方式。 

二、Redis配置

2.1 在Docker-composer.yml中增加Redis的配置

  redis:
    image: redis
    container_name: redis
    restart: always    
    networks:
      - kong-net    
    ports:
      - 6379:6379
    volumes:
      - ./redis/data:/data
    command:
      redis-server /data/redis.conf --requirepass "123321"

2.2 redis.conf配置文件

redis-server带配置文件参数启动,如redis-server redis.conf,需要redis.conf文件提前存在,把redis.conf文件放置在宿主机的./redis/data目录下,点击可以下载redis.conf 

2.3 Docker-compose.yml

version: "3"
 
networks:
  kong-net:
    #external: true #docker network create --subnet=172.18.0.0/16 kong-net
    driver: bridge
  
#volumes:
#  db-data:
#    external:
#      name: ~/db   #manually using `docker volume create --name=~/db`
  
services:
  redis:
    image: redis
    container_name: redis
    restart: always    
    networks:
      - kong-net    
    ports:
      - 6379:6379
    volumes:
      - ./redis/data:/data
    command:
      redis-server /data/redis.conf --requirepass "123321"
  kong-database:
    image: postgres:9.6
    restart: always
    networks:
      - kong-net 
    environment:
      POSTGRES_USER: kong
      POSTGRES_DB: kong
      POSTGRES_PASSWORD: your_pg_password
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "kong"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - ./postgres/data:/var/lib/postgresql/data
    container_name: kong-database
  kong-migration:
    image: kong:latest
    command: "kong migrations bootstrap"
    restart: on-failure
    networks:
      - kong-net 
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_PASSWORD: your_pg_password
      KONG_CASSANDRA_CONTACT_POINTS: kong-database
    links:
      - kong-database
    depends_on:
      - kong-database
    container_name: kong-migration     
  kong:
    image: kong:latest
    restart: always
    networks:
      - kong-net 
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_PASSWORD: your_pg_password
      KONG_CASSANDRA_CONTACT_POINTS: kong-database
      KONG_PROXY_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_ACCESS_LOG: /dev/stdout
      KONG_PROXY_ERROR_LOG: /dev/stderr
      KONG_ADMIN_ERROR_LOG: /dev/stderr
      KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
    depends_on:
      - kong-migration
      - kong-database
    healthcheck:
      test: ["CMD", "curl", "-f", "http://kong:8001"]
      interval: 5s
      timeout: 2s
      retries: 15
    ports:
      - "8001:8001"
      - "8000:8000"
      - "8443:8443"
      - "8444:8444"
    container_name: kong
  konga-prepare:
    image: pantsel/konga:next
    command: "-c prepare -a postgres -u postgresql://kong:your_pg_password@kong-database:5432/konga_db"
    restart: on-failure
    networks:
      - kong-net 
    links:
      - kong-database
    depends_on:
      - kong-database
    container_name: konga-prepare
  konga:
    image: pantsel/konga:latest
    restart: always
    networks:
      - kong-net 
    environment:
      DB_ADAPTER: postgres
      DB_HOST: kong-database
      DB_USER: kong
      DB_PASSWORD: your_pg_password
      TOKEN_SECRET: km1GUr4RkcQD7DewhJPNXrCuZwcKmqjb
      DB_DATABASE: konga_db
      NODE_ENV: production
    depends_on:
      - kong-database
      - konga-prepare
    ports:
      - "1337:1337"  
    container_name: konga

2.4 测试Redis

测试Redis的安装及数据持久化是否正常,在RedisDesktopManager中连接上Redis后,打开控制台,可以输入命令更改Redis的配置信息。

用“CONFIG SET”修改配置之后,如果重启Redis的话,已经改过的参数不会被保存,会还原到原先配置文件中原来的参数。

如果希望“CONFIG SET”修改之后的参数能被一直保存,需要再执行命令“CONFIG REWRITE”,会更新配置文件Redis.conf,这样再重启Redis的话,参数也会是最新修改后的参数。

2.5 Redis的持久化

如果不希望Redis在重启之后数据丢失的情况,需要用到Redis的持久化配置,Redis的持久化有2种方式: RDB和AOF。

2.5.1 RDB持久化方式

RDB方式下,Redis会将数据集的快照dump到dump.rdb文件中,我们也可以通过配置文件来修改Redis服务器dump快照的频率。

  • save 900 1              #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。

  • save 300 10            #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。

  • save 60 10000        #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。

2.5.1.1 SAVE和BGSAVE命令

 SAVE是阻塞式的RDB持久化,当执行这个命令时Redis的主进程把内存里的数据写入到RDB文件(即dump.rdb)中,直到该文件创建完毕的这段时间内Redis将不能处理任何命令请求。

  BGSAVE属于非阻塞式的持久化,它会创建一个子进程专门去把内存中的数据写入到RDB文件中,同时主进程还可以处理来自客户端的命令请求。但子进程基本是一个复制的父进程,这等于两个相同大小的Redis进程在系统上运行,会造成内存使用率的大幅增加。

执行完bgsave后,dump.rdb就会是最新的修改时间。

(案例:Redis本身内存使用率60%,总的内存使用率70-80%,持久化的时候立马飙到百分之一百三十多, 最后根据需求选择了AOF持久化)

2.5.2 AOF持久化方式

AOF持久化的配置

appendonly yes                       #开启AOF持久化,默认关闭
appendfilename "appendonly.aof"      #AOF文件名称(默认)
appendfsync no                       #AOF持久化策略
auto-aof-rewrite-percentage 100      #触发AOF文件重写的条件(默认)
auto-aof-rewrite-min-size 64mb       #触发AOF文件重写的条件(默认

appendfsync有三个选项:always、everysec和no,它们分别是:

  • appendfsync always     #每次有数据修改发生时都会写入AOF文件。
  • appendfsync everysec  #每秒钟同步一次,该策略为AOF的缺省策略。
  • appendfsync no           #系统自身决定。

1、选择always的时候服务器会在每执行一个事件就把AOF缓冲区的内容强制性的写入硬盘上的AOF文件里,可以看成你每执行一个redis写入命令就往AOF文件里记录这条命令,这保证了数据持久化的完整性,但效率是最慢的,却也是最安全的;

2、配置成everysec的话服务端每执行一次写操作(如set、sadd、rpush)也会把该条命令追加到一个单独的AOF缓冲区的末尾,并将AOF缓冲区写入AOF文件,然后每隔一秒才会进行一次文件同步把内存缓冲区里的AOF缓存数据真正写入AOF文件里,这个模式兼顾了效率的同时也保证了数据的完整性,即使在服务器宕机也只会丢失一秒内对redis数据库做的修改;

3、将appendfsync配置成no则意味redis数据库里的数据就算丢失你也可以接受,它也会把每条写命令追加到AOF缓冲区的末尾,然后写入文件,但什么时候进行文件同步真正把数据写入AOF文件里则由系统自身决定,即当内存缓冲区的空间被填满或者是超过了设定的时限后系统自动同步。这种模式下效率是最快的,但对数据来说也是最不安全的,如果redis里的数据都是从后台数据库如mysql中取出来的,属于随时可以找回或者不重要的数据,那么可以考虑设置成这种模式。

     相比RDB每次持久化都会内存翻倍,AOF持久化除了在第一次启用时会新开一个子进程创建AOF文件会大幅度消耗内存外,之后的每次持久化对内存使用都很小。但AOF也有一个不可忽视的问题:AOF文件过大。你对redis数据库的每一次写操作都会让AOF文件里增加一条数据,久而久之这个文件会形成一个庞然大物。还好的是redis提出了AOF重写的机制,即上面配置的auto-aof-rewrite-percentage和auto-aof-rewrite-min-size。auto-aof-rewrite-percentage和auto-aof-rewrite-min-size配置触发AOF重写的条件。Redis 会记录上次重写后AOF文件的文件大小,而当前AOF文件大小跟上次重写后AOF文件大小的百分比超过auto-aof-rewrite-percentage设置的值,同时当前AOF文件大小也超过auto-aof-rewrite-min-size设置的最小值,则会触发AOF文件重写。以上面的配置为例,当现在的AOF文件大于64mb同时也大于上次重写AOF后的文件大小,则该文件就会被AOF重写。

Redis4.0开始允许使用RDB和AOF混合持久化的方式,结合了两者的优点通过aof-use-rdb-preamble配置项可以打开混合开关。最后需要注意的是,如果Redis开启了AOF持久化功能,那么当Redis重启时会优先使用AOF文件来还原数据库。

三、Kong配置

3.1 添加Rate Limiting插件

 3.2 设置minute = 5(即1分钟内不能超过5次)

 3.3 配置policy=redis和redis的连接信息

3.4 配置hide client headers = yes

如果hide client headers = no, HTTP的header会是下面这样

Date →Tue, 28 Apr 2020 16:14:18 GMT
Content-Type →application/json; charset=utf-8
Connection →keep-alive
Retry-After →42
Content-Length →37
X-RateLimit-Limit-Second →5
X-RateLimit-Remaining-Second →5
X-RateLimit-Remaining-Minute →0
RateLimit-Limit →5
RateLimit-Remaining →0
X-RateLimit-Limit-Minute →5
RateLimit-Reset →42
X-Kong-Response-Latency →1
Server →kong/2.0.3

Content-Type →text/plain;charset=UTF-8
Content-Length →4
Connection →keep-alive
Date →Tue, 28 Apr 2020 16:26:28 GMT
X-Kong-Upstream-Latency →8
X-Kong-Proxy-Latency →10
Via →kong/2.0.3

3.5 调用API进行测试

在1分钟内超过5次调用,HTTP返回码为429 Too Many Requests

版权声明
本文为[anron]所创,转载请带上原文链接,感谢
https://blog.csdn.net/anron/article/details/105814601