Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: support for proxy caching plugin based on disk. #1153

Merged
merged 22 commits into from
Mar 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion bin/apisix
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,22 @@ http {
lua_shared_dict jwks 1m; # cache for JWKs
lua_shared_dict introspection 10m; # cache for JWT verification results

{% if proxy_cache then %}
# for proxy cache
{% for _, cache in ipairs(proxy_cache.zones) do %}
proxy_cache_path {* cache.disk_path *} levels={* cache.cache_levels *} keys_zone={* cache.name *}:{* cache.memory_size *} inactive=1d max_size={* cache.disk_size *};
{% end %}
{% end %}

{% if proxy_cache then %}
# for proxy cache
map $upstream_cache_zone $upstream_cache_zone_info {
{% for _, cache in ipairs(proxy_cache.zones) do %}
{* cache.name *} {* cache.disk_path *},{* cache.cache_levels *};
{% end %}
}
{% end %}

lua_ssl_verify_depth 5;
ssl_session_timeout 86400;

Expand Down Expand Up @@ -375,6 +391,8 @@ http {
proxy_pass_header Server;
proxy_pass_header Date;

### the following x-forwarded-* headers is to send to upstream server

set $var_x_forwarded_for $remote_addr;
set $var_x_forwarded_proto $scheme;
set $var_x_forwarded_host $host;
Expand All @@ -398,7 +416,34 @@ http {
proxy_set_header X-Forwarded-Host $var_x_forwarded_host;
proxy_set_header X-Forwarded-Port $var_x_forwarded_port;

proxy_pass $upstream_scheme://apisix_backend$upstream_uri;
{% if proxy_cache then %}
### the following configuration is to cache response content from upstream server

set $upstream_cache_zone off;
set $upstream_cache_key '';
set $upstream_cache_bypass '';
set $upstream_no_cache '';
set $upstream_hdr_expires '';
set $upstream_hdr_cache_control '';

proxy_cache $upstream_cache_zone;
proxy_cache_valid any {% if proxy_cache and proxy_cache.cache_ttl then %} {* proxy_cache.cache_ttl *} {% else %} 5s {% end %};
proxy_cache_min_uses 1;
proxy_cache_methods GET HEAD;
proxy_cache_lock_timeout 5s;
proxy_cache_use_stale off;
proxy_cache_key $upstream_cache_key;
proxy_no_cache $upstream_no_cache;
proxy_cache_bypass $upstream_cache_bypass;

proxy_hide_header Cache-Control;
proxy_hide_header Expires;
add_header Cache-Control $upstream_hdr_cache_control;
add_header Expires $upstream_hdr_expires;
add_header Apisix-Cache-Status $upstream_cache_status always;
{% end %}

proxy_pass $upstream_scheme://apisix_backend$upstream_uri;

header_filter_by_lua_block {
apisix.http_header_filter_phase()
Expand Down
16 changes: 16 additions & 0 deletions conf/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ apisix:
# enable_tcp_pp: true # Enable the proxy protocol for tcp proxy, it works for stream_proxy.tcp option
# enable_tcp_pp_to_upstream: true # Enables the proxy protocol to the upstream server

proxy_cache: # Proxy Caching configuration
cache_ttl: 10s # The default caching time if the upstream does not specify the cache time
zones: # The parameters of a cache
- name: disk_cache_one # The name of the cache, administrator can be specify
# which cache to use by name in the admin api
memory_size: 50m # The size of shared memory, it's used to store the cache index
disk_size: 1G # The size of disk, it's used to store the cache data
disk_path: "/tmp/disk_cache_one" # The path to store the cache data
cache_levels: "1:2" # The hierarchy levels of a cache
# - name: disk_cache_two
# memory_size: 50m
# disk_size: 1G
# disk_path: "/tmp/disk_cache_two"
# cache_levels: "1:2"

# allow_admin: # http://nginx.org/en/docs/http/ngx_http_access_module.html#allow
# - 127.0.0.0/24 # If we don't set any IP list, then any IP access is allowed by default.
# - "::/64"
Expand Down Expand Up @@ -124,6 +139,7 @@ plugins: # plugin list
- fault-injection
- udp-logger
- wolf-rbac
- proxy-cache
- tcp-logger

stream_plugins:
Expand Down
1 change: 1 addition & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ Plugins
* [redirect](plugins/redirect.md): URI redirect.
* [response-rewrite](plugins/response-rewrite.md): Set customized response status code, body and header to the client.
* [fault-injection](plugins/fault-injection.md): The specified response body, response code, and response time can be returned, which provides processing capabilities in different failure scenarios, such as service failure, service overload, and high service delay.
* [proxy-cache](plugins/proxy-cache.md): Provides the ability to cache upstream response data.
* [tcp-logger](plugins/tcp-logger.md): Log requests to TCP servers

Deploy to the Cloud
Expand Down
1 change: 1 addition & 0 deletions doc/README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ Reference document
* [redirect](plugins/redirect-cn.md): URI 重定向。
* [response-rewrite](plugins/response-rewrite-cn.md): 支持自定义修改返回内容的 `status code`、`body`、`headers`。
* [fault-injection](plugins/fault-injection-cn.md):故障注入,可以返回指定的响应体、响应码和响应时间,从而提供了不同的失败场景下处理的能力,例如服务失败、服务过载、服务高延时等。
* [proxy-cache](plugins/proxy-cache-cn.md):代理缓存插件提供缓存后端响应数据的能力。

146 changes: 146 additions & 0 deletions doc/plugins/proxy-cache-cn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
-->

[English](proxy-cache.md)

# proxy-cache

代理缓存插件,该插件提供缓存后端响应数据的能力,它可以和其他插件一起使用。该插件支持基于磁盘的缓存,未来也会支持基于内存的缓存。目前可以根据响应码、请求 Method 来指定需要缓存的数据,另外也可以通过 no_cache 和 cache_bypass 配置更复杂的缓存策略。

基于磁盘的缓存需要注意:
1. 不能动态配置缓存的过期时间,只能通过后端服务响应头 Expires 或 Cache-Control 来设置过期时间,如果后端响应头中没有 Expires 或 Cache-Control,那么 APISIX 将默认只缓存10秒钟
2. 如果后端服务不可用, APISIX 将返回502或504,那么502或504将被缓存10秒钟

### 参数

|名称 |必须|类型|描述|
|------- |-----|------|------|
|cache_zone|是|string|指定使用哪个缓存区域,不同的缓存区域可以配置不同的路径,在conf/config.yaml文件中可以预定义使用的缓存区域|
|cache_key|是|array[string]|缓存key,可以使用变量。例如:["$host", "$uri", "-cache-id"]|
|cache_bypass|否|array[string]|是否跳过缓存检索,即不在缓存中查找数据,可以使用变量,需要注意当此参数的值不为空或非'0'时将会跳过缓存的检索。例如:["$arg_bypass"]|
|cache_method|否|array[string]|根据请求method决定是否需要缓存|
|cache_http_status|否|array[integer]|根据响应码决定是否需要缓存|
|hide_cache_headers|否|boolean|是否将 Expires 和 Cache-Control 响应头返回给客户端,默认为 false|
|no_cache|否|array[string]|是否缓存数据,可以使用变量,需要注意当此参数的值不为空或非'0'时将不会缓存数据。|

注:变量以$开头,也可以使用变量和字符串的结合,但是需要以数组的形式分开写,最终变量被解析后会和字符串拼接在一起。

### 示例

#### 启用插件

示例1:为特定路由启用 `proxy-cache` 插件:

```shell
curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
{
"plugins": {
"proxy-cache": {
"cache_zone": "disk_cache_one",
"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": {
"127.0.0.1:1999": 1
},
"type": "roundrobin"
},
"uri": "/hello"
}'
```

测试:

```shell
$ curl http://127.0.0.1:9080/hello -i
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 6
Connection: keep-alive
Server: APISIX web server
Date: Tue, 03 Mar 2020 10:45:36 GMT
Last-Modified: Tue, 03 Mar 2020 10:36:38 GMT
Apisix-Cache-Status: MISS

hello
```

> http status 返回`200`并且响应头中包含`Apisix-Cache-Status`,表示该插件已启用。

示例2:验证文件是否被缓存,再次请求上边的地址:

测试:

```shell
$ curl http://127.0.0.1:9080/hello -i
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 6
Connection: keep-alive
Server: APISIX web server
Date: Tue, 03 Mar 2020 11:14:46 GMT
Last-Modified: Thu, 20 Feb 2020 14:21:41 GMT
Apisix-Cache-Status: HIT

hello
```

> 响应头 Apisix-Cache-Status 值变为了 HIT,说明文件已经被缓存

示例3:如何清理缓存的文件,只需要指定请求的 method 为 PURGE:

测试:

```shell
$ curl -i http://127.0.0.1:9080/hello -X PURGE
HTTP/1.1 200 OK
Date: Tue, 03 Mar 2020 11:17:35 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX web server
```

> 响应码为200即表示删除成功,如果文件未找到将返回404

#### 禁用插件

移除插件配置中相应的 JSON 配置可立即禁用该插件,无需重启服务:

```shell
curl http://127.0.0.1:9080/apisix/admin/routes/1 -X PUT -d '
{
"uri": "/hello",
"plugins": {},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1999": 1
}
}
}'
```

这时该插件已被禁用。
Loading