跳转至

memc: 标准 NGINX memcached 模块的扩展版本

安装

您可以在任何基于 RHEL 的发行版中安装此模块,包括但不限于:

  • RedHat Enterprise Linux 7、8、9 和 10
  • CentOS 7、8、9
  • AlmaLinux 8、9
  • Rocky Linux 8、9
  • Amazon Linux 2 和 Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-memc
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-memc

通过在 /etc/nginx/nginx.conf 顶部添加以下内容来启用该模块:

load_module modules/ngx_http_memc_module.so;

本文档描述了 nginx-module-memc v0.20,于 2023 年 12 月 27 日发布。


 # GET /foo?key=dog
 #
 # POST /foo?key=cat
 # Cat's value...
 #
 # PUT /foo?key=bird
 # Bird's value...
 #
 # DELETE /foo?key=Tiger
 location /foo {
     set $memc_key $arg_key;

     # $memc_cmd 默认值为 GET 的 get,
     #   POST 的 add,PUT 的 set,以及
     #   DELETE 请求方法的 delete。

     memc_pass 127.0.0.1:11211;
 }
 # GET /bar?cmd=get&key=cat
 #
 # POST /bar?cmd=set&key=dog
 # My value for the "dog" key...
 #
 # DELETE /bar?cmd=delete&key=dog
 # GET /bar?cmd=delete&key=dog
 location /bar {
     set $memc_cmd $arg_cmd;
     set $memc_key $arg_key;
     set $memc_flags $arg_flags; # 默认值为 0
     set $memc_exptime $arg_exptime; # 默认值为 0

     memc_pass 127.0.0.1:11211;
 }
 # GET /bar?cmd=get&key=cat
 # GET /bar?cmd=set&key=dog&val=animal&flags=1234&exptime=2
 # GET /bar?cmd=delete&key=dog
 # GET /bar?cmd=flush_all
 location /bar {
     set $memc_cmd $arg_cmd;
     set $memc_key $arg_key;
     set $memc_value $arg_val;
     set $memc_flags $arg_flags; # 默认值为 0
     set $memc_exptime $arg_exptime; # 默认值为 0

     memc_cmds_allowed get set add delete flush_all;

     memc_pass 127.0.0.1:11211;
 }
   http {
     ...
     upstream backend {
        server 127.0.0.1:11984;
        server 127.0.0.1:11985;
     }
     server {
         location /stats {
             set $memc_cmd stats;
             memc_pass backend;
         }
         ...
     }
   }
   ...
 # 将 memcached 标志读取到 Last-Modified 头中
 # 以响应 304 条件 GET
 location /memc {
     set $memc_key $arg_key;

     memc_pass 127.0.0.1:11984;

     memc_flags_to_last_modified on;
 }
 location /memc {
     set $memc_key foo;
     set $memc_cmd get;

     # 访问 memcached 监听的 unix 域套接字
     memc_pass unix:/tmp/memcached.sock;
 }

描述

此模块扩展了标准 memcached module,以支持几乎整个 memcached ascii protocol

它允许您为 memcached 服务器定义自定义的 REST 接口,或通过子请求或 独立伪请求 从 nginx 服务器内部以非常高效的方式访问 memcached。

此模块不打算合并到 Nginx 核心中,因为我使用 Ragel 生成了 memcached 响应解析器(用 C 编写),这让我很高兴 :)

如果您打算使用此模块来缓存位置响应,可以尝试 srcache-nginx-module 与此模块一起使用,以实现该目标。

lua-nginx-module 一起使用时,建议使用 lua-resty-memcached 库,而不是此模块,因为前者更灵活且内存效率更高。

与 memcached 服务器的保持连接

您需要 HttpUpstreamKeepaliveModule 与此模块一起使用,以便与后端 memcached 服务器保持 TCP 连接。

以下是一个示例配置:

   http {
     upstream backend {
       server 127.0.0.1:11211;

       # 一个最多有 1024 个连接的池
       # 并且不区分服务器:
       keepalive 1024;
     }

     server {
         ...
         location /memc {
             set $memc_cmd get;
             set $memc_key $arg_key;
             memc_pass backend;
         }
     }
   }

工作原理

它完全基于 upstream 机制实现了 memcached TCP 协议。所有涉及 I/O 的操作都是非阻塞的。

该模块本身不会在请求之间保持与上游 memcached 服务器的 TCP 连接,就像其他上游模块一样。有关有效解决方案,请参见 与 memcached 服务器的保持连接 部分。

支持的 Memcached 命令

memcached 存储命令 setaddreplaceprependappend 使用 $memc_key 作为键,$memc_exptime 作为过期时间(或延迟)(默认值为 0),$memc_flags 作为标志(默认值为 0),以构建相应的 memcached 查询。

如果 $memc_value 完全未定义,则请求体将用作 $memc_value 的值,除了 incrdecr 命令。请注意,如果 $memc_value 被定义为空字符串(""),则该空字符串仍将作为值使用。

以下 memcached 命令已实现并经过测试(其参数由本模块定义的相应 nginx 变量标记):

get $memc_key

使用键检索值。

   location /foo {
       set $memc_cmd 'get';
       set $memc_key 'my_key';

       memc_pass 127.0.0.1:11211;

       add_header X-Memc-Flags $memc_flags;
   }

如果找到该键,则返回 200 OK,并将值放入响应体中;否则返回 404 Not Foundflags 数字将设置到 $memc_flags 变量中,因此通常希望通过标准 add_header directive 将该信息放入响应头中。

对于 ERRORCLIENT_ERRORSERVER_ERROR,返回 502

set $memc_key $memc_flags $memc_exptime $memc_value

要使用请求体作为 memcached 值,只需避免设置 $memc_value 变量:

   # POST /foo
   # my value...
   location /foo {
       set $memc_cmd 'set';
       set $memc_key 'my_key';
       set $memc_flags 12345;
       set $memc_exptime 24;

       memc_pass 127.0.0.1:11211;
   }

或者让 $memc_value 保存值:

   location /foo {
       set $memc_cmd 'set';
       set $memc_key 'my_key';
       set $memc_flags 12345;
       set $memc_exptime 24;
       set $memc_value 'my_value';

       memc_pass 127.0.0.1:11211;
   }

如果上游 memcached 服务器回复 STORED,则返回 201 CreatedNOT_STORED 返回 200NOT_FOUND 返回 404ERRORCLIENT_ERRORSERVER_ERROR 返回 502

除了 404 NOT FOUND 外,原始 memcached 响应将作为响应体返回。

add $memc_key $memc_flags $memc_exptime $memc_value

类似于 set command

replace $memc_key $memc_flags $memc_exptime $memc_value

类似于 set command

append $memc_key $memc_flags $memc_exptime $memc_value

类似于 set command

请注意,至少 memcached 版本 1.2.2 不支持 "append" 和 "prepend" 命令。至少 1.2.4 及更高版本似乎支持这两个命令。

prepend $memc_key $memc_flags $memc_exptime $memc_value

类似于 append command

delete $memc_key

使用键删除 memcached 条目。

   location /foo {
       set $memc_cmd delete;
       set $memc_key my_key;

       memc_pass 127.0.0.1:11211;
   }

如果成功删除,则返回 200 OKNOT_FOUND 返回 404ERRORCLIENT_ERRORSERVER_ERROR 返回 502

除了 404 NOT FOUND 外,原始 memcached 响应将作为响应体返回。

delete $memc_key $memc_exptime

类似于 delete $memc_key 命令,但接受由 $memc_exptime 变量指定的可选 expiration 时间。

此命令在最新的 memcached 版本 1.4.4 中不再可用。

incr $memc_key $memc_value

$memc_key 的现有值增加 $memc_value 指定的数量:

   location /foo {
       set $memc_cmd incr;
       set $memc_key my_key;
       set $memc_value 2;
       memc_pass 127.0.0.1:11211;
   }

在前面的示例中,每次访问 /foo 都会导致 my_key 的值增加 2

如果成功,返回 200 OK,并将与该键关联的新值作为响应体;如果未找到该键,则返回 404 Not Found

对于 ERRORCLIENT_ERRORSERVER_ERROR,返回 502

decr $memc_key $memc_value

类似于 incr $memc_key $memc_value

flush_all

将 memcached 服务器上的所有键标记为过期:

   location /foo {
       set $memc_cmd flush_all;
       memc_pass 127.0.0.1:11211;
   }

flush_all $memc_exptime

flush_all 类似,但还接受由 $memc_exptime 变量指定的过期时间。

stats

使 memcached 服务器输出通用统计信息和设置。

   location /foo {
       set $memc_cmd stats;
       memc_pass 127.0.0.1:11211;
   }

如果请求成功,则返回 200 OK;对于 ERRORCLIENT_ERRORSERVER_ERROR 返回 502

来自上游 memcached 服务器的原始 stats 命令输出将放入响应体中。

指令

所有标准 memcached module 指令在 nginx 0.8.28 中直接继承,memcached_ 前缀替换为 memc_。例如,memcached_pass 指令拼写为 memc_pass

在这里,我们仅记录两个最重要的指令(后者是本模块引入的新指令)。

memc_pass

语法: memc_pass <memcached 服务器 IP 地址>:<memcached 服务器端口>

语法: memc_pass <memcached 服务器主机名>:<memcached 服务器端口>

语法: memc_pass <upstream_backend_name>

语法: memc_pass unix:<path_to_unix_domain_socket>

默认值:

上下文: http, server, location, if

阶段: content

指定 memcached 服务器后端。

memc_cmds_allowed

语法: memc_cmds_allowed <cmd>...

默认值:

上下文: http, server, location, if

列出允许访问的 memcached 命令。默认情况下,所有本模块支持的 memcached 命令都是可访问的。 示例:

    location /foo {
        set $memc_cmd $arg_cmd;
        set $memc_key $arg_key;
        set $memc_value $arg_val;

        memc_pass 127.0.0.1:11211;

        memc_cmds_allowed get;
    }

memc_flags_to_last_modified

语法: memc_flags_to_last_modified on|off

默认值: off

上下文: http, server, location, if

将 memcached 标志作为纪元秒读取,并将其设置为 Last-Modified 头的值。对于条件 GET,它将指示 nginx 返回 304 Not Modified 响应以节省带宽。

memc_connect_timeout

语法: memc_connect_timeout <time>

默认值: 60s

上下文: http, server, location

连接到 memcached 服务器的超时时间,默认以秒为单位。

最好始终明确指定时间单位以避免混淆。支持的时间单位有 "s"(秒)、"ms"(毫秒)、"y"(年)、"M"(月)、"w"(周)、"d"(天)、"h"(小时) 和 "m"(分钟)。

此时间必须少于 597 小时。

memc_send_timeout

语法: memc_send_timeout <time>

默认值: 60s

上下文: http, server, location

向 memcached 服务器发送 TCP 请求的超时时间,默认以秒为单位。

最好始终明确指定时间单位以避免混淆。支持的时间单位有 "s"(秒)、"ms"(毫秒)、"y"(年)、"M"(月)、"w"(周)、"d"(天)、"h"(小时) 和 "m"(分钟)。

此时间必须少于 597 小时。

memc_read_timeout

语法: memc_read_timeout <time>

默认值: 60s

上下文: http, server, location

从 memcached 服务器读取 TCP 响应的超时时间,默认以秒为单位。

最好始终明确指定时间单位以避免混淆。支持的时间单位有 "s"(秒)、"ms"(毫秒)、"y"(年)、"M"(月)、"w"(周)、"d"(天)、"h"(小时) 和 "m"(分钟)。

此时间必须少于 597 小时。

memc_buffer_size

语法: memc_buffer_size <size>

默认值: 4k/8k

上下文: http, server, location

此缓冲区大小用于内存缓冲区以保存

  • get 以外的 memcached 命令的完整响应,
  • get memcached 命令的完整响应头(即响应的第一行)。

此默认大小为页面大小,可以是 4k8k

memc_ignore_client_abort

语法: memc_ignore_client_abort on|off

默认值: off

上下文: location

确定当客户端在未等待响应的情况下关闭连接时,是否应关闭与 memcache 服务器的连接。

此指令在 v0.14 版本中首次添加。

变更

每个版本的更改可以从 OpenResty 包的变更日志中获得:

http://openresty.org/#Changes

测试套件

此模块附带一个 Perl 驱动的测试套件。 测试用例 也是 声明式。感谢 Perl 世界中的 Test::Base 模块。

要在您的环境中运行它:

 $ PATH=/path/to/your/nginx-with-memc-module:$PATH prove -r t

如果您已更改 Nginx 服务器二进制文件,则需要在运行测试套件之前终止任何 Nginx 进程。

测试框架使用 LWP::UserAgentIO::Socket

由于所有测试脚本(.t 文件)都使用单个 nginx 服务器(默认是 localhost:1984),因此在调用 prove 工具时指定 -jN 并行运行测试套件是没有意义的。

在运行测试套件之前,您还应该在本地主机上保持一个监听在 11211 端口的 memcached 服务器。

测试套件的某些部分还需要启用 rewriteecho 模块。

另见

GitHub

您可以在 nginx-module-memc 的 GitHub 仓库 中找到此模块的其他配置提示和文档。