Nginx memcached回退到远程服务

Ana*_*oly 6 memcached nginx

我不能让Nginx使用memcached模块,要求是查询远程服务,缓存memcached中的数据,永远不要获取远程端点,直到后端使缓存无效.我有2个带有memcached v1.4.35的容器和一个带有Nginx v1.11.10的容器.

配置如下:

upstream http_memcached {
  server 172.17.0.6:11211;
  server 172.17.0.7:11211;
}

upstream remote {
  server api.example.com:443;
  keepalive 16;
}

server {
  listen 80;

  location / {
    set $memcached_key "$uri?$args";
    memcached_pass http_memcached;
    error_page     404 502 504 = @remote;
  }

  location @remote {
    internal;
    proxy_pass https://remote;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
  }
}
Run Code Online (Sandbox Code Playgroud)

我试图错误地设置memcached上游,但我得到HTTP 499而不是警告:

*3上游服务器在连接上游时暂时禁用

看来配置Nginx可以成功到达memcached但无法写入或读取.我可以成功地用telnet写入和读取memcached.

你能帮我吗?

ffe*_*ast 2

我对您的配置的猜测

\n\n

1. 499个代码

\n\n

HTTP 499 是 nginx 的自定义代码,表示客户端在收到响应之前终止连接(http://lxr.nginx.org/source/src/http/ngx_http_request.h#0120

\n\n

我们可以很容易地重现它,只需

\n\n
nc -k -l 172.17.0.6 172.17.0.6:11211\n
Run Code Online (Sandbox Code Playgroud)\n\n

卷曲您的资源 - 卷曲将挂起一段时间,然后按 Ctrl+C \xe2\x80\x94 您将在访问日志中看到此消息

\n\n

2. 连接上游时上游服务器暂时禁用

\n\n

这意味着 nginx 无法访问您的 memcached,只是将其从上游池中删除。只要关闭两台 memcached 服务器就足够了,您会不断地在错误日志中看到它(我每次都看到它error_log ... info)。\n当您看到这些消息时,您认为 nginx 可以与 memcached 服务器自由通信的假设似乎并不成立是真实的。

\n\n

考虑显式设置http://nginx.org/en/docs/http/ngx_http_memcached_module.html#memcached_bind \n并在telnet中使用-b选项,以确保您通过 telnet 客户端正确测试 memcached 服务器的可用性

\n\n

3.\xc2\xa0nginx 可以成功到达 memcached,但无法对其进行写入或读取

\n\n

Nginx 只能通过其内置模块从 memcached读取数据 \n( http://nginx.org/en/docs/http/ngx_http_memcached_module.html ):

\n\n
\n

\xc2\xa0ngx_http_memcached_module\xc2\xa0 模块用于从 memcached 服务器获取响应。密钥在\xc2\xa0$memcached_key\xc2\xa0变量中设置。应通过 nginx 外部的方式提前将响应放入 memcached 中。

\n
\n\n

4.整体架构

\n\n

从您的问题中尚不完全清楚整个架构应该如何工作。

\n\n
    \n
  • nginx 的上游默认使用加权循环。\n这意味着您的 memcached 服务器将被随机查询一次。\n您可以通过设置来更改它,memcached_next_upstream not_found这样丢失的密钥将被视为错误,并且所有服务器都将被轮询。对于 2 台服务器的场来说可能没问题,但对于 20 台服务器来说不太可能是您想要的

  • \n
  • memcached 客户端库 \xe2\x80\x94 通常也是如此,它们会根据某种哈希方案从池中选择一台服务器 => 所以你的密钥最终只会出现在池中的 1 台服务器上

  • \n
\n\n

5. 做什么

\n\n

我已经设法在 10 分钟内在本地机器上设置了类似的配置 - 它按预期工作。为了减轻调试,我会摆脱 docker 容器以避免网络过于复杂,使用 -vv 选项在不同端口上以单线程模式运行 2 个 memcached 服务器,以查看请求何时到达它们 ( ),然后使用memcached -p 11211 -U o -vvtail -f卷曲看看你的情况到底发生了什么。

\n\n

6. 工作方案

\n\n

nginx 配置

\n\n

这里没有使用https和http/1.1,但这并不重要

\n\n
upstream http_memcached {                                                       \n    server 127.0.0.1:11211;                                                     \n    server 127.0.0.1:11212;                                                     \n}                                                                               \n\nupstream remote {                                                               \n    server 127.0.0.1:8080;                                                      \n}                                                                               \n\nserver {                                                                        \n    listen 80;                                                                  \n    server_name server.lan;                                                     \n    access_log /var/log/nginx/server.access.log;                                \n    error_log /var/log/nginx/server.error.log info;                             \n\n    location / {                                                                \n        set $memcached_key "$uri?$args";                                        \n        memcached_next_upstream not_found;                                      \n        memcached_pass http_memcached;                                          \n        error_page     404 = @remote;                                           \n    }                                                                           \n\n    location @remote {                                                          \n        internal;                                                               \n        access_log /var/log/nginx/server.fallback.access.log;                   \n        proxy_pass http://remote;                                               \n        proxy_set_header Connection "";                                         \n    }                                                                           \n}            \n
Run Code Online (Sandbox Code Playgroud)\n\n

服务器.py

\n\n

这是我的虚拟服务器(python):

\n\n
from random import randint\n\nfrom flask import Flask\napp = Flask(__name__)\n\n@app.route(\'/\')\ndef hello_world():\n    return \'Hello: {}\\n\'.format(randint(1, 100000))\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是如何运行它(只需要先安装flask)

\n\n
FLASK_APP=server.py [flask][2] run -p 8080    \n
Run Code Online (Sandbox Code Playgroud)\n\n

填写我的第一个 memcached 服务器

\n\n
$ telnet 127.0.0.1 11211\nTrying 127.0.0.1...\nConnected to 127.0.0.1.\nEscape character is \'^]\'.\nset /? 0 900 5\ncache\nSTORED\nquit\nConnection closed by foreign host.\n
Run Code Online (Sandbox Code Playgroud)\n\n

检查:

\n\n

请注意,尽管我们仅在第一台服务器中存储数据,但每次都会得到结果

\n\n
$ curl http://server.lan && echo                                  \ncache\n\n$ curl http://server.lan  && echo                                 \ncache\n\n$ curl http://server.lan && echo                                  \ncache\n
Run Code Online (Sandbox Code Playgroud)\n\n

这个不在缓存中,所以我们将从 server.py 获得响应

\n\n
$ curl http://server.lan/?q=1 && echo\nHello: 32337\n
Run Code Online (Sandbox Code Playgroud)\n\n

全图

\n\n

右边的 2 个窗口是

\n\n
memcached -p 11211 -U o -vv\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
memcached -p 11212 -U o -vv\n
Run Code Online (Sandbox Code Playgroud)\n\n

在此输入图像描述

\n