我有一个nginx服务器,坐在运行django的apache前面。
我的网站大部分是静态内容: http : //www.grovemade.com/
我的应用程序服务器可以处理需要dynamic的部分(POST,购物车,订单状态,常见问题等)。
绝大多数命中是静态页面,如产品页面,关于页面,ajax获取请求。
它像一个冠军直接从memcached处理页面。 其实我问过SF在这里确定我的瓶颈: 这是否certificate了networking带宽瓶颈? 而且受到我的主机出站stream量限制。 因此对于我需要的任何东西都是100%的能力。 因为这些数字我都很兴奋; 但是这些数字并不意味着当40页纸被轰炸时,嘿,让我成为一个新的caching! “嘿,我也是!”
唯一的问题是,在stream量大的时候,第二个caching过期了一个特定的页面,我的应用程序服务器遇到了数以千计的请求,这使得所有的东西都陷入了/可能导致服务器崩溃。 我想象的更像是…
答:应用程序服务器按照自己的步调自动将内容推送到memcached(因为它肯定可以填充caching……只有几百个同时进行)。 前端服务器使用它所具有的function – 从不尝试代理获取请求。 地狱,它可以为我所关心的所有人留下一个空白的页面。 至less应用程序服务器将是活着的,接受订单,并能够在未来的某个时刻填充那个破损的页面,而不是一个向下的死亡螺旋,我甚至无法拿起我的盾(memcached)。 问题是:我不得不build立一个系统,确定应该从多个地方caching的每个页面。 Django知道要caching哪些页面; 我想这很容易。 但是nginx – > django:我不希望它代理一切(否则我会处于相同的情况); 所以我必须在一个单独的位置编写更多的逻辑。 咩。
B:Nginx可以限制与应用服务器的连接。 但是,它将如何区分应用程序服务器排队的请求和我只希望它build立单个连接的types? 毕竟,应用程序决定是否应该caching页面。 如果它正在我的应用程序服务器上等待简单的dynamic内容(如提取订单详细信息),我不希望它删除连接。 在caching/应用程序之间build立一个请求响应循环,通知需要build立一个页面? 而后来的请求应该被忽略?
等等。
所以,考虑到99%的stream量是由nginx来满足的,而我的应用服务器真的只是X%谁转换并使其成为一个dynamic页面有趣,我应该怎么做,以防止我的应用服务器在几秒钟内完全淹没它响应的地方:
嘿,你! 让我为你回到这个页面。 还有1000多人想要吗? 好吧,我会这样做,如果我可以的话。
现实世界的问题/例子:今天,我们得到了巨大的命中。 我们通常不会获得很多stream量,但是我们今天发布了我们的产品,预购客户就像疯了似的。 服务器现在正在处理stream量@ 20%的容量,但是有一些非常非常粗略的时间,当我试图生成一个小时caching定时器过期时每个人都点击的小块页面时,我几乎失去了它。
我疯狂地select了最重要的caching页面,并试图将它们保存在caching中。 那是/不是/乐趣! 我也手动拉动从8080上运行的Apache的HTML,并把它们放到memcached。
如果我的apache进程内存不足,完全崩溃说memcached或花了足够长的时间,以至于过期的密钥,会有一个点… …“难以回报”,在那么多的人会绕过caching,我的服务器会比平常更加重载/因此如果不阻止所有请求并开始手动填充高速caching,通常是不可恢复的。
通常做什么来完成这项工作?
对不起,这是一种思路。 我没有睡过,因为这个..
# grove urls # ---------- location / { set $use_memcached no; if ($request_method = GET) { set $use_memcached yes; } if ($host ~ "^cached") { set $use_memcached no; } if ($request_uri ~ '.{240,}') { set $use_memcached no; } if ($args ~ nginx_bypass_cache=true) { set $use_memcached no; } if ($use_memcached = yes) { set $memcached_key "nginx.$request_uri"; memcached_pass localhost:11211; } default_type text/html; client_max_body_size 50m; error_page 404 502 = @cache_miss; } location @cache_miss { proxy_pass http://127.0.0.1:8080; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 50m; client_body_buffer_size 128k; proxy_connect_timeout 60; # time to connect to upstream server proxy_send_timeout 300; # time to wait for upstream to accept data proxy_read_timeout 300; # time to wait for upstream to return data proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; }
如果你可以发布你的nginxconfiguration,我可以帮你更好的方法!
通常,我将使用Nginx的fastcgi_cache / proxy_cache和fastcgi_cache_use_stale / proxy_cache_use_stale
我说这两个选项,因为如果你可以使用Nginx的fastcgi或其他模块运行后端应用程序,那么最好这样做。
如果8080上的Apache无法删除,最好使用proxy_cache和proxy_cache_use_stale updating行。
请提供您的configuration,以便我们可以尝试改进它。
==
添加了一个基于你的样本configuration(非常原始,很可能需要调整)
#IMPORTANT outside server{..} block proxy_cache_path /var/run/nginx-cache levels=1:2 keys_zone=GROVE:500m inactive=60m; proxy_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale updating; server { #other stuff set $no_cache 0; # POST requests and urls with a query string should always go to PHP if ($request_method = POST) { set $no_cache 1; } # grove urls # ---------- location / { default_type text/html; client_max_body_size 50m; proxy_pass http://127.0.0.1:8080; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_body_buffer_size 128k; proxy_connect_timeout 60; # time to connect to upstream server proxy_send_timeout 300; # time to wait for upstream to accept data proxy_read_timeout 300; # time to wait for upstream to return data proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; proxy_cache_bypass $no_cache; proxy_no_cache $no_cache; proxy_cache GROVE; proxy_cache_valid 60m; }