在介绍“反向代理”之前,首先要介绍一下“正向代理”的概念。
在NAT技术(Network Address Translation)出现之前,所有主机无法直接与外网相连,要想上网,需要连接到一台能够访问外网的Web服务器,再通过这台服务器访问外网。而这台Web服务器就叫做“正向代理服务器”。
现在的“”技术也是如何,我们把请求发给一台可以连接外面世界的Web服务器,由它转发我们的请求,再将结果返回给我们。这台Web服务器就是“正向代理服务器”。
综上所述:正向代理服务器是客户端和目的服务器之间的一个中介,客户端通过正向代理服务器访问客户端原本无法访问的目标服务器。
客户端向一个服务器A提交请求后,服务器A偷偷地去服务器B上获取资源,并返回给客户端。客户端天真地以为数据是服务器A给他的。在这过程中,服务器A称为“反向代理服务器”,服务器B称为反向代理服务器的“后端服务器”。
两者最直观的区别是在用户的角度。“正向代理”是用户使用的技术。用户首先是知道自己要访问的目标服务器是谁,但由于某种原因无法直接访问该目标服务器,因此选择使用正向代理服务器帮忙转发请求。
而“反向代理”是服务器使用的技术。用户向服务器发送请求后,服务器在用户不知情的情况下去其他服务器上获取资源并返回给用户。
反向代理服务器用于存储静态数据和缓存数据,它处于Web服务器之前。当用户发起请求时,请求首先被反向代理服务器截获,若请求的是静态数据或缓存数据,则反向代理服务器直接将数据返回;若请求的是动态数据,且缓存中不存在,则反向代理服务器将请求转发给后端的Web服务器,在获取后端服务器的数据后再返回给用户。
反向代理服务器能够分担后端服务器的压力。在请求数很高的情况下,即使服务器使用了缓存,但仍然无法应对巨大的并发数,因此需要反向代理服务器的帮忙。反向代理服务器收到请求后,如果请求的是缓存数据或静态数据,则直接返回给用户,而无需再劳驾后端服务器了,从而缓解后端服务器的压力。
反向代理服务器有多种选择,可以使用Nginx的反向代理模块,但它毕竟是Nginx的一个插件,功能不够全面。
Squid是一个缓存服务器,除提供反向代理外还拥有其他功能,但过于重量级,历史也比较悠久,性能不咋地。
Varnish是一款专门用于反向代理的服务器,相对于Squid较为轻量,由于使用内存缓存,因此性能较好,但也收到了内存的存储容量的限制。
究竟哪一个反向代理服务器适合你,可以参考:
varnish / squid / nginx cache 有什么不同?
这里我们以Varnish为例。
下载安装Varnish
首先你需要去Varnish官网下载并安装Varnish,这里不做详细介绍了。
配置Varnish的后端服务器的IP和端口号
backend default{
.host = "127.0.0.1";
.port = "80";
}
Varnish采用VCL(Varnish Configuration Language)来让我们自定义缓存规则。
Varnish将反向代理的处理过程分为多个阶段,每个阶段都会触发对应的函数,我们可以在这些函数中配置具体的缓存处理策略。
下面对常用规则的配置进行介绍:
1.vcl_revc函数
sub vcl_revc{
if(req.request!="GET" &&
req.request!="POST" &&
req.request!="PUT" &&
req.request!="HEAD" &&
req.request!="OPTIONS" &&
req.request!="DELETE" &&
req.request!="TRACE"){
return(pipe);
}
if(req.request!="GET" &&
req.request!="HEAD"){
return(pass);
}
if(req.http.Authorization || req.http.Cookie){
return(pass);
}
return (lookup);
}
2.vcl_fetch函数
sub vcl_fetch{
if(!obj.cacheable){
return(pass);
}
if(obj.http.set-Cookie){
return(pass);
}
set obj.prefetch = -30s;
return (deliver);
}
Varnish提供了两种清除缓存的方式:
varnishadm -T localhost:8011 purge.url /xxx.html
PURGE /xxx.html HTTP/1.0
Host:Varnish的地址
后端服务器能够使用HTTP方式删除Varnish上的指定的缓存。
使用varnishstat命令即可查看当前Varnish的运行情况,下面是Varnish运行参数的说明:
Client requests recived:
Varnish接收到的所有请求的个数。
Cache hits:
缓存命中的个数。
Cache misses:
缓存未命中的个数。
N expired objects:
过期缓存的个数。
N LRU moved objects:
被淘汰的缓存的个数。
Total header bytes:
当前缓存中所有数据的HTTP Header长度。
Total body bytes:
当前缓存中所有数据的HTTP body长度。
PS:Varnish还提供了可视化的监控界面。
首先,我们需要通过压力测试来估算网站的最大并发数。
然后观察反向代理服务器中缓存空间的使用率与命中率。
如果缓存空间长时间处于满载,并且缓存的命中率很低,并且后端服务器的实际并发数接近最大并发数,那么我们就需要考虑增加缓存的存储空间。增加缓存空间后,一方面能提高缓存命中率,一方面能减轻后端服务器的压力。
若缓存有效期过长,虽然能够大大减轻后端服务器的压力,但数据的实时性将大大降低;若缓存有效期过短,那么虽然数据实时性大大提高,但后端服务器的压力也增加。
所以缓存有效期的确定需要根据实际的业务情况,如果你的网站对实时性要求很高,那么就需要设置较短的缓存有效期,如果对实时性要求不高,那么可以将缓存设置长一些,从而减轻后端服务器压力。
当然,如果你网站平实的并发数达不到服务器所能承受的最大并发数,那完全可以不用考虑缓存,用户每次请求都让后端服务器直接处理,一切都不用那么麻烦了。
如果有些页面中大部分地方都不需要实时更新,而局部对实时性要求较高,那么可以使用ESI技术,对页面不同的地方设置不同的缓存有效期。
讲到这里,也许有的人要问,反向代理服务器实现了缓存的功能,那么后端服务器还需要缓存吗?答案是:当然需要!
原因主要有如下两点:
由于反向代理服务器和后端服务器是通过TCP进行数据通信,因此为了降低他们之间的通信时延,需要将这两台服务器放在内部网络下,并通过交换机相连。