<<上篇 | 首页 | 下篇>>

如何利用Nginx的缓冲、缓存优化提升性能

使用缓冲释放后端服务器

 

反向代理的一个问题是代理大量用户时会增加服务器进程的性能冲击影响。在大多数情况下,可以很大程度上能通过利用Nginx的缓冲和缓存功能减轻。

 

当代理到另一台服务器,两个不同的连接速度会影响客户的体验:

从客户机到Nginx代理的连接。

从Nginx代理到后端服务器的连接。

 

Nginx具有优化这些连接调整其行为的能力。

 

如果没有缓冲,数据从代理的服务器发送并立即开始被发送到客户。如果假定客户端很快,缓冲可以关闭而尽快使数据到客户端,有了缓冲,Nginx代理将暂时存储后端的响应,然后按需供给数据给客户端。如果客户端是缓慢的,允许Nginx服务器关闭到后端的连接。然后,它可以处理数据分配到客户端,以任何可能的速度。

 

Nginx默认有缓冲设计,因为客户端往往有很大的不同的连接速度。我们可以用以下指令调节缓冲行为。可以在HTTP,server或location位置来设置。重要的是要记住,大小size指令是针对每个请求配置的,所以增加超出你需求会影响你的性能,如果这时有许多客户端请求:

 

proxy_buffering:该指令控制缓冲是否启用。默认情况下,它的值是“on”。

proxy_buffers:该指令控制代理响应缓冲区的数量(第一个参数)和大小(第二个参数)。默认配置是8个缓冲区大小等于一个内存页(4K或者8K)。增加缓冲区的数目可以让你缓冲更多信息。

proxy_buffer_size:从后端服务器的响应头缓冲区大小,它包含headers,和其他部分响应是分开的。该指令设置响应部分的缓冲区大小。默认情况下,它和proxy_buffers是相同的尺寸,但因为这是用于头信息,这通常可以设置为一个较低的值。

proxy_busy_buffers_size:此指令设置标注“client-ready”缓冲区的最大尺寸。而客户端可以一次读取来自一个缓冲区的数据,缓冲被放置在队列中,批量发送到客户端。此指令控制允许是在这种状态下的缓冲空间的大小。

proxy_max_temp_file_size:这是每个请求能用磁盘上临时文件最大大小。这些当上游响应太大不能装配到缓冲区时被创建。

proxy_temp_file_write_size:这是当被代理服务器的响应过大时Nginx一次性写入临时文件的数据量。

proxy_temp_path:当上游服务器的响应过大不能存储到配置的缓冲区域时,Nginx存储临时文件硬盘路径。

正如你所看到的,Nginx提供了相当多的不同的指令来调整缓冲行为。大多数时候,你不必担心太多,但它对于调整一些值可能是有用的。可能最有用的调整是proxy_buffers和proxy_buffer_size指令。

 

一个例子:、

# server context

 

proxy_buffering on;

proxy_buffer_size 1k;

proxy_buffers 24 4k;

proxy_busy_buffers_size 8k;

proxy_max_temp_file_size 2048m;

proxy_temp_file_write_size 32k;

 

location / {

proxy_pass http://example.com;

}

 

配置代理服务缓存来减少响应时间

 

尽管缓冲可以帮助释放后端服务器以处理更多的请求,Nginx还提供了一种方法来缓存从后端服务器的内容,对于许多请求无需连接到上游。

 

配置代理缓存

要设置缓存用于代理内容,我们可以使用proxy_cache_path指令。这将创建区域保存来自被代理服务器返回的数据。该proxy_cache_path指令必须在HTTP上下文部分进行设置。

 

在下面的例子中,我们将配置一些相关的指令来建立我们的缓存系统。

 

# http context

 

proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=backcache:8m max_size=50m;

proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args";

proxy_cache_valid 200 302 10m;

proxy_cache_valid 404 1m;

 

用proxy_cache_path指令,我们首先应该已经定义在文件系统中希望存储缓存的目录。在这个例子中,我们选择在/var/lib/nginx/cache目录。如果该目录不存在,你可以用正确的权限和所有权创建它:

 

sudo mkdir -p /var/lib/nginx/cache

sudo chown www-data /var/lib/nginx/cache

sudo chmod 700 /var/lib/nginx/cache

levels=参数指定缓存将如何组织。 Nginx将通过散列键(下方配置)的值来创建一个缓存键。我们选择了上述的levels决定了单个字符目录(这是散列值的最后一个字符)配有两个字符的子目录(下两个字符取自散列值的末尾)将被创建。你通常不必对这个细节关注,但它可以帮助Nginx快速找到相关的值。

 

keys_zone=参数定义缓存区域的名字,我们称之为backcache。这也是我们定义多少元数据存储的地方。在这个例子里,我们是存储8 MB的key。对于每兆字节,Nginx可存储8000左右的条目。MAX_SIZE参数设置实际缓存数据的最大尺寸。

 

我们使用上面的另一个指令是proxy_cache_key。这个设置将设置用于存储缓存值的键。此键用于检查是否一个请求可以从高速缓存提供服务。我们将它设置成方案(http或https),HTTP请求方法,以及被请求的主机和URI的组合。

 

proxy_cache_valid指令可以被指定多次。它依赖于状态代码值使我们能够配置多长时间存储。在我们的例子中,我们对于后端返回200和302存储10分钟,404响应的一分钟过期。

 

现在,我们已经配置了缓存区,但我们仍然需要告诉Nginx什么时候使用缓存。

 

在我们代理到后端的location位置,我们可以配置使用这个缓存:

 

# server context

 

location /proxy-me {

    proxy_cache backcache;

    proxy_cache_bypass $http_cache_control;

    add_header X-Proxy-Cache $upstream_cache_status;

 

    proxy_pass http://backend;

}

 

 

使用proxy_cache指令,就可以指定该backcache缓存区被用于这个位置。 Nginx会在这里检查传递给后端有效的条目。

 

上述proxy_cache_bypass指令被设置为$ http_cache_control变量。这将包含一个指示器,用以指示该客户端是否被明确地请求一个最新的,非缓存版本。设置此指令允许Nginx正确处理这些类型的客户端请求。无需进行进一步的配置。

 

我们还增加了被称为X-Proxy-Cache的额外头。我们设置这个头部为$ upstream_cache_status变量的值。这个设置头,使我们能够看到,如果请求导致高速缓存命中,高速缓存未命中,或者高速缓存被明确旁路。这是对于调试特别有价值,也对客户端是有用的信息。

 

关于缓存结果的注意事项

 

 

高速缓存能够极大地提高代理服务器的性能。不过,也需要明确的考虑配置缓存时候,要记住。

 

首先,任何用户相关的数据不应被高速缓存。这可能导致一个用户的数据被呈现给其他用户。如果你的网站是完全静态的,这可能不是一个问题。

 

如果你的网站有一些动态元素,你将不得不考虑到这一点。你如何处理要看是什么应用程序或服务器处理的后端处理。对于私人的内容,你应该设置Cache-Control头为“no-cache”,“no-sotre”,或者“private”依赖于数据的性质:

 

no-cache:

请求: 告知缓存者,必须原原本本的转发原始请求,并告知任何缓存者,需要去转发请求,并验证缓存(如果有的话).对应名词:端对端重载.    

响应: 允许缓存者缓存副本.那么其实际价值是,总是强制缓存者,校验缓存的新鲜度.一旦确认新鲜,则可以使用缓存副本作为响应. no-cache,还可以指定某个包含字段,比如一个典型应用,no-cache=Set-Cookie. 这样做的结果,就是告知缓存者,对于Set-Cookie字段,你不要使用缓存内容.而是使用新滴.其他内容则可以使用缓存

no-store:表示在任何时候收到的数据不被缓存。这对于私人数据是最安全,因为它意味着,该数据必须从服务器每次进行检索。

private:这表明共享的缓存空间不能缓存此数据。这可以用于指示用户的浏览器高速缓存数据,但代理服务器不应当考虑随后的请求数据有效。

public:这表明该响应是可在连接的任何点被高速缓存的公共数据。

一个相关的可以控制此行为报头是max-age头,其指示,任何资源应该缓存的秒数。

 

根据内容的敏感性,正确设置这些头,会帮助你利用缓存优势,同时保持你的私人数据安全,并使您的动态数据最新。

 

如果你的后端也使用Nginx,你可以设置使用过期指令,设置max-age来实现Cache-Control:

 

location / {

    expires 60m;

}

 

location /check-me {

    expires -1;

}

在上面的例子中,第一个块允许缓存一个小时的内容。第二块设置Cache-Control头为“无缓存”。要设置其他值,可以使用add_header指令,就像这样:

 

location /private {

    expires -1;

    add_header Cache-Control "no-store";

}

 

 

标签 : ,

图灵社区 : 图书 : 一步步搭建物联网系统

设计物联网系统是件有意思的事情,它需要考虑到软件、硬件、通讯等多个不同方面。通过探索不同的语言,不同的框架,从而形成不同的解决方案。在这里,我们将对设计物联网系统有一个简单的介绍,并探讨如何设计一个最小的物联网系统。

关于内容的选择,这是一个有意思的话题,因为我们很难判断不同的开发者用的是怎样的语言,用的是怎样的框架。 

于是我们便自作主张地选择了那些适合于理论学习的语言、框架、硬件,去除掉其他一些我们不需要考虑的因素,如语法,复杂度等等。当然,这些语言、框架、硬件也是最流行的。 

Arduino: 如果你从头开始学过硬件的话,那么你会爱上它的。 
Raspberry PI: 如果你从头编译过GNU/Linux的话,我想你会爱上她的。 
Python: 简单地来说,你可以方便地使用一些扩展,同时代码就表达了你的想法。 
PHP : 这是一门容易部署的语言,我想你只需要在你的Ubuntu机器上,执行一下脚本就能完成安装了。而且,如果你是一个硬件开发者的话,你会更容易地找到其他开发者。 
Javascript : 考虑到javascript这门语言已经无处不在了,而且会更加流行。所以,在这里CoAP、MQTT等版本是基于Nodejs的。 
HTML、CSS : 这是必须的,同样,他们仍然无处不在。 
GNU/Linux: 作为部署到服务器的一部分——你需要掌握他。当然如果你要用WAMP也是可以的。 
CoAP: 用NodeJS构建IOT CoAP物联网 

本文档对一些概念(如)只做了一些基本介绍,以方便读者理解。如果您想进一步了解这些知识,会列出一些推荐书目,以供参考。

作者黄峰达,1991年出生于闽南,双子座,毕业于西安文理学院。 
农村长大,热爱大自然,热爱生活。和哈比特人一样喜欢土地里长出来的东西。 
是一个文艺控。喜欢读书,喜欢纸的质感,喜欢用笔铭刻记忆和思想。 
是一个设计控,一个DIY爱好者。喜欢自行设计一些小东西,相比理论而言更喜欢动手实践,比如拆装自己的手机、电脑等。 
最喜欢折腾与计算机相关的东西:SEO、前端开发、硬件相关(如:Raspberry Pi,51,Arduino,OpenWRT,uCOS...)。 
在编程的路上已经走了较长一段,但始终相信前路更长更加广阔。

阅读全文……

标签 :

Nginx负载均衡服务器实现会话粘贴的几种方式

1、使用Nginx 的ip_hash作为负载均衡服务并支持Session sticky 

2、使用nginx sticky第三方模块实现基于cookie的负载均衡 

3、使用nginx的map指令根据cookie分流:

map $COOKIE_abcdexpid $group {
	~*1$	apache001;
	~*2$	apache002;
	default	root;
}
 
upstream apache001 {
	server 192.168.1.1:8080 weight=1 max_fails=1 fail_timeout=30s;
}
 
upstream apache002 {
	server 192.168.1.2:8080 weight=1 max_fails=1 fail_timeout=30s;
}
 
upstream root {
	server 192.168.1.0:8080 weight=1 max_fails=1 fail_timeout=30s;
}
 
server {
	listen       8080;
	server_name  neoremind.net;
 
	log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
					  '$status $body_bytes_sent "$http_referer" "group=$group"'
					  '"$http_user_agent" $gzip_ratio $request_time "$http_x_forwarded_for"';
 
	access_log  logs/access_log main;
	error_log   logs/error_log;
 
	location / {
        proxy_pass http://$group;
		proxy_set_header X-Forwarded-For $remote_addr;
    }	
}

 4、利用set和if…else… 根据cookie分流

 

upstream apache001 {
	server 192.168.1.1:8080 weight=1 max_fails=1 fail_timeout=30s;
}
 
upstream apache002 {
	server 192.168.1.2:8080 weight=1 max_fails=1 fail_timeout=30s;
}
 
upstream root {
	server 192.168.1.0:8080 weight=1 max_fails=1 fail_timeout=30s;
}
 
server {
	listen       8080;
	server_name  beidoutest.baidu.com;
 
	#match cookie
	set $group "root";
	if ($http_cookie ~* "abcdexpid=([^;]+)(1$)"){
		set $group apache001;
	}
	if ($http_cookie ~* "abcdexpid=([^;]+)(2$)"){
		set $group apache002;
	}
 
	log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
					  '$status $body_bytes_sent "$http_referer" "group=$group"'
					  '"$http_user_agent" $gzip_ratio $request_time "$http_x_forwarded_for"';
 
	access_log  logs/access_log main;
	error_log   logs/error_log;
 
	location / {
		proxy_pass http://$group;
		proxy_set_header X-Forwarded-For $remote_addr;
	}
 
}

 

 

5、nginx1.7.2版本后提供的hash方法:

# http context  
upstream backend_hosts {      
hash $cookie_JSESSIONID consistent;      
server host1.example.com;     
server host2.example.com;     
server host3.example.com; 

             }