Nginx memcached回退到远程服务

时间:2017-03-16 23:50:34

标签: nginx memcached

我不能让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 "";
  }
}

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

  

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

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

你能帮帮我吗?

1 个答案:

答案 0 :(得分:2)

我猜测你的配置发生了什么

1。 499代码

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

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

nc -k -l 172.17.0.6 172.17.0.6:11211

curl 您的资源 - curl会暂停一段时间然后按Ctrl + C - 您的访问日志中会显示此消息

2。上游服务器在连接到上游时暂时禁用

这意味着nginx无法访问您的memcached并将其从上游池中删除。我只关闭两个memcached服务器,你会不断在错误日志中看到它(我每次都会看到它error_log ... info)。 正如您所看到的那样,您认为nginx可以与memcached服务器自由通信的假设似乎并非如此。

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

3。 nginx可以成功到达memcached但无法写入或读取

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

  

ngx_http_memcached_module模块用于获取响应   一个memcached服务器。密钥在$ memcached_key变量中设置。一个   响应应该通过外部方式预先存入memcached   nginx的。

4。整体架构

从你的问题中不完全清楚整体架构应该如何运作。

  • 默认情况下,nginx的上游使用weighted round-robin。 这意味着您的memcached服务器将随机查询一次。 您可以通过设置memcached_next_upstream not_found来更改它,以便将缺少的密钥视为错误,并且将轮询所有服务器。对于一个拥有2台服务器的农场来说,这可能是好的,但不太可能是你想要的20台服务器

  • 同样通常是memcached客户端库的情况 - 他们根据某些散列方案从>中选择一个服务器。所以你的密钥最终只能在池外的1台服务器上

5。怎么做

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

6。工作解决方案

nginx config

这里没有使用https和http / 1.1,但没关系

upstream http_memcached {                                                       
    server 127.0.0.1:11211;                                                     
    server 127.0.0.1:11212;                                                     
}                                                                               

upstream remote {                                                               
    server 127.0.0.1:8080;                                                      
}                                                                               

server {                                                                        
    listen 80;                                                                  
    server_name server.lan;                                                     
    access_log /var/log/nginx/server.access.log;                                
    error_log /var/log/nginx/server.error.log info;                             

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

    location @remote {                                                          
        internal;                                                               
        access_log /var/log/nginx/server.fallback.access.log;                   
        proxy_pass http://remote;                                               
        proxy_set_header Connection "";                                         
    }                                                                           
}            

<强> server.py

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

from random import randint

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello: {}\n'.format(randint(1, 100000))

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

FLASK_APP=server.py [flask][2] run -p 8080    

填写我的第一个memcached服务器

$ telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
set /? 0 900 5
cache
STORED
quit
Connection closed by foreign host.

<强>检查:

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

$ curl http://server.lan && echo                                  
cache

$ curl http://server.lan  && echo                                 
cache

$ curl http://server.lan && echo                                  
cache

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

获得响应
$ curl http://server.lan/?q=1 && echo
Hello: 32337

整体情况

右边的2个窗口是

memcached -p 11211 -U o -vv

memcached -p 11212 -U o -vv

enter image description here