我不能让Nginx使用memcached模块,要求是查询远程服务,缓存memcached中的数据,永远不要获取远程端点,直到后端使缓存无效.我有2个容器,memcached v1.4.35和一个Nginx v1.11.10.
配置如下:
@H_403_8@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上游,但我得到HTTP 499而不是警告:
*3 upstream server temporarily disabled while connecting to upstream
看来配置Nginx可以成功到达memcached但无法写入或读取.我可以成功地用telnet写入和读取memcached.
你能帮我吗?
1. 499码
HTTP 499是Nginx’自定义代码,表示客户端在接收响应之前终止连接(http://lxr.nginx.org/source/src/http/ngx_http_request.h#0120)
我们可以轻松地重现它
@H_403_8@nc -k -l 172.17.0.6 172.17.0.6:11211
并卷曲你的资源 – 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
并使用-b选项与telnet确保您通过telnet客户端正确测试memcached服务器的可用性
3. Nginx可以成功到达memcached但无法写入或读取
Nginx只能通过其内置模块从memcached中读取
(http://nginx.org/en/docs/http/ngx_http_memcached_module.html):
The ngx_http_memcached_module module is used to obtain responses from
a memcached server. The key is set in the $memcached_key variable. A
response should be put in memcached in advance by means external to
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)然后玩尾巴-f和卷曲,看看你的情况真的发生了什么.
6.工作方案
Nginx配置:
这里没有使用https和http / 1.1,但没关系
@H_403_8@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):
@H_403_8@from random import randint from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello: {}\n'.format(randint(1,100000))
这是如何运行它(只需要先安装烧瓶)
@H_403_8@FLASK_APP=server.py [flask][2] run -p 8080
填写我的第一个memcached服务器:
@H_403_8@$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.
检查:
请注意,尽管我们存储了数据,但每次都会得到一个结果
仅在第一台服务器上
@H_403_8@$curl http://server.lan && echo cache $curl http://server.lan && echo cache $curl http://server.lan && echo cache
这个不在缓存中,所以我们将从server.py获得响应
@H_403_8@$curl http://server.lan/?q=1 && echo Hello: 32337
全貌:
右边的2个窗口
@H_403_8@memcached -p 11211 -U o -vv
和
@H_403_8@memcached -p 11212 -U o -vv