环境说明
本次环境已经开启APISIX 80端口,文章使用80和9080效果相同!
proxy-cache插件介绍
proxy-cache
插件提供缓存后端响应数据的能力,它可以和其他插件一起使用。该插件支持基于磁盘和内存的缓存。目前可以根据响应码和请求模式来指定需要缓存的数据,也可以通过no_cache
和cache_bypass
属性配置更复杂的缓存策略。
参数属性
名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
---|---|---|---|---|---|
cache_strategy | string | 否 | disk | ["disk","memory"] | 缓存策略,指定缓存数据存储在磁盘还是内存中。 |
cache_zone | string | 否 | disk_cache_one | 指定使用哪个缓存区域,不同的缓存区域可以配置不同的路径,在 conf/config.yaml 文件中可以预定义使用的缓存区域。如果指定的缓存区域与配置文件中预定义的缓存区域不一致,那么缓存无效。 | |
cache_key | array[string] | 否 | ["$host", "$request_uri"] | 缓存 key,可以使用变量。例如:["$host", "$uri", "-cache-id"] | |
cache_bypass | array[string] | 否 | 当该属性的值不为空或者非 0 时则会跳过缓存检查,即不在缓存中查找数据,可以使用变量,例如:["$arg_bypass"] | ||
cache_method | array[string] | 否 | ["GET", "HEAD"] | ["GET", "POST", "HEAD"] | 根据请求 method 决定是否需要缓存。 |
cache_http_status | array[integer] | 否 | [200, 301, 404] | [200, 599] | 根据 HTTP 响应码决定是否需要缓存。 |
hide_cache_headers | boolean | 否 | false | 当设置为 true 时将 Expires 和 Cache-Control 响应头返回给客户端 | |
cache_control | boolean | 否 | false | 当设置为 true 时遵守 HTTP 协议规范中的 Cache-Control 的行为 | |
no_cache | array[string] | 否 | 当此参数的值不为空或非 0 时将不会缓存数据,可以使用变量 | ||
cache_ttl | integer | 否 | 300 秒 | 当选项 cache_control 未开启或开启以后服务端没有返回缓存控制头时,提供的默认缓存时间 |
基于硬盘缓存
添加磁盘缓存需要添加apisix conf配置文件
apisix:
proxy_cache:
cache_ttl: 10s # 如果上游未指定缓存时间,则为默认磁盘缓存时间
zones:
- name: disk_cache_one
memory_size: 50m
disk_size: 1G
disk_path: /tmp/disk_cache_one
cache_levels: 1:2
# - name: disk_cache_two
# memory_size: 50m
# disk_size: 1G
# disk_path: "/tmp/disk_cache_two"
# cache_levels: "1:2"
- name: memory_cache
memory_size: 50m
添加位置
配置生效
#我们可以进入到APISIX容器,查看是否生效
root@abcdocker:~/apisix-docker/example# docker exec -it dcc95564a8f3 bash
apisix@dcc95564a8f3:/usr/local/apisix$ ls /tmp/
disk_cache_one grpc-engine-debug.log
创建路由并配置插件
使用本次磁盘,缓存200,GET请求
curl http://127.0.0.1:9180/apisix/admin/routes/1
-H 'X-API-KEY: edaacc2vvvv3bbb5f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/image/*",
"name": "abcdocker http limit test",
"methods": [
"GET"
],
"host": "apisix.i4t.com",
"plugins": {
"proxy-cache": {
"cache_key": ["$uri", "-cache-id"],
"cache_bypass": ["$arg_bypass"],
"cache_method": ["GET"],
"cache_http_status": [200],
"hide_cache_headers": true,
"no_cache": ["$arg_test"]
}
},
"upstream": {
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 1
}
],
"type": "roundrobin",
"hash_on": "vars",
"scheme": "http",
"pass_host": "pass"
},
"status": 1
}'
效果测试,我们直接curl我们创建的img
接口
MISS
- 在缓存中找不到响应,因此从原始服务器获取。然后可以缓存响应。
EXPIRED
- 缓存中的条目已过期。响应包含来自源服务器的新内容。
HIT
- 响应包含直接来自缓存的有效新鲜内容。
当用户第一次访问
第一次请求该路由,数据未缓存,那么 Apisix-Cache-Status 字段应为 MISS。此时再次请求该路由:
Apisix-Cache-Status: MISS
状态为MISS
root@abcdocker:~# curl -i -X GET "http://127.0.0.1/abcdocker/anything/" -H "Host: apisix.i4t.com"
HTTP/1.1 404 NOT FOUND
Content-Type: text/html; charset=utf-8
Content-Length: 233
Connection: keep-alive
Date: Wed, 20 Sep 2023 07:16:56 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.5.0
Apisix-Cache-Status: MISS
当用户第二次访问
Apisix-Cache-Status: HIT
为HIT 表示已经访问缓存接口
如果返回的响应头中 Apisix-Cache-Status 字段变为 HIT,则表示数据已被缓存,插件生效:
root@abcdocker:~# curl -i -X GET "http://127.0.0.1/image/webp" -H "Host: apisix.i4t.com"
HTTP/1.1 200 OK
Content-Type: image/webp
Content-Length: 10568
Connection: keep-alive
Date: Wed, 20 Sep 2023 07:32:22 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.5.0
Apisix-Cache-Status: HIT
当用户第三次访问
Apisix-Cache-Status: EXPIRED
缓存接口过期
root@abcdocker:~# curl -i -X GET "http://127.0.0.1/image/webp" -H "Host: apisix.i4t.com"
HTTP/1.1 200 OK
Content-Type: image/webp
Content-Length: 10568
Connection: keep-alive
Date: Wed, 20 Sep 2023 07:33:03 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.5.0
Apisix-Cache-Status: EXPIRED
此时我们在看/tmp/disk_cache_one/
目录下就已经生成缓存目录
apisix@dcc95564a8f3:/usr/local/apisix$ ls /tmp/disk_cache_one/
1 a c
apisix@dcc95564a8f3:/usr/local/apisix$
说明
- 对于基于磁盘的缓存,不能动态配置缓存的过期时间,只能通过后端服务响应头
Expires
或Cache-Control
来设置过期时间,当后端响应头中没有Expires
或Cache-Control
时,默认缓存时间为 10 秒钟 - 当上游服务不可用时,APISIX 将返回
502
或504
HTTP 状态码,默认缓存时间为 10 秒钟; - 变量以
$
开头,不存在时等价于空字符串。也可以使用变量和字符串的结合,但是需要以数组的形式分开写,最终变量被解析后会和字符串拼接在一起。
基于内存缓存
通过硬盘缓存难免会有性能问题,但是添加内存中,可以更快的返回数据
缓存:
- 内存 > SSD > 机械磁盘
- 本机 > 网络
- 进程内 > 进程间
原则
- 越靠近用户的请求越好
- 尽量使用本进程和本机的缓存解决
开启并配置内存缓存
curl http://127.0.0.1:9180/apisix/admin/routes/1
-H 'X-API-KEY: edaacc2vvvv3bbb5f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/image/*",
"name": "abcdocker http limit test",
"methods": [
"GET"
],
"host": "apisix.i4t.com",
"plugins": {
"proxy-cache": {
"cache_strategy": "memory",
"cache_zone": "memory_cache",
"cache_ttl": 10
}
},
"upstream": {
"nodes": [
{
"host": "httpbin.org",
"port": 80,
"weight": 1
}
],
"type": "roundrobin",
"hash_on": "vars",
"scheme": "http",
"pass_host": "pass"
},
"status": 1
}'
第一次访问
第一次请求该路由,数据未缓存,那么 Apisix-Cache-Status 字段应为 MISS。此时再次请求该路由:
root@abcdocker:~# curl -I -X GET "http://127.0.0.1:9080/image/png" -H "Host: apisix.i4t.com"
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 8090
Connection: keep-alive
Apisix-Cache-Status: MISS
Date: Wed, 20 Sep 2023 08:25:00 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Server: APISIX/3.5.0
第二次访问
如果返回的响应头中 Apisix-Cache-Status 字段变为 HIT,则表示数据已被缓存,插件生效:
root@abcdocker:~# curl -I -X GET "http://127.0.0.1:9080/image/png" -H "Host: apisix.i4t.com"
HTTP/1.1 200 OK
Content-Type: image/png
Transfer-Encoding: chunked
Connection: keep-alive
Date: Wed, 20 Sep 2023 08:25:00 GMT
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Server: APISIX/3.5.0
Age: 9
Apisix-Cache-Status: HIT
为了清除缓存数据,你只需要指定请求的 method 为 PURGE:
curl -i http://127.0.0.1:9080/image -X PURGE
HTTP 响应码为 200 即表示删除成功,如果缓存的数据未找到将返回 404:
HTTP/1.1 200 OK