欢迎各位兄弟 发布技术文章
这里的技术是共享的
如下图,nginx不停的向后转发,我们的应用程序 app server 服务器在一定程度上,在一定时间内,能够抗得住我们整个系统的需要了,我们的架构要向前发展,我们的人员要增多,我们的网站不停的向前发展,,,,,,,淘宝最初的功能很简陋,后来不停的增加各种功能,后来都能抢购了,这些功能模块是后来陆续加上来的,,,,,,,我们的应用程序本身处理的逻辑越来越复杂,执行的程序越来越多,提供的功能越来越多,,,,,意味着用户所能够执行的操作越来越多,过一段时间,应用程序服务器可能会抗不住的,,,,而且会由于本身应用程序过于复杂,导致处理逻辑过于复杂,很可能产生bug,各种难以追踪的莫名其妙的问题,此时怎么办?我们可以将网站分区,,,,,,将网站分割开,这一块是新闻的一组服务器,论坛是另外一组服务器,,,,,,但是在主页上看,都是在一个页面上,但是点开以后,会发现是属于不同的服务器组,就像淘宝一样,你看是不是有个搜索框,但是在搜索框里面放关键字搜索的时候,它给你事实上打开某个站点某一个店铺的时候,那完全是不同的服务器组,,,,只不过我们各种各样的应用,服务器组在前台都整合成一个主页了,,,,,任何一个站点主页的访问量是最大的,如果我们每一次访问主页,都在用
程序动态生成的话,是非常慢的,因此在设计高性能网站的时候,有个重要的思路,首页一定要静态化,因为首页的访问量是最大的,,,好多大的网站,首页主页面,通常是静态的,都是html格式的,只不过里面的有些框架,有些子版块,子内容是动态生成的,而这个动态内容,本身也是缓存的,不然的话,打开一个主页,服务器都有可以压垮的
如下图,,,,,由此我们就成了这样的结构,一堆搜索服务器组,一堆抢购服务器组,一堆论坛(在线讨论区),我们都是使用一个前端的服务器,,,,,,,,,前端有个前端服务器组,前端服务器组接收用户对主页的访问,当用户访问的时候,假设一个服务器只能承受2万个用户,,,,,,20万个用户同时过来的时候,10个服务器就能抗得住了,当用户点击了某一个按钮以后,我们通过url重定向,定位到后面的某一个服务器组上面去了,还有图片服务器组(静态服务器组)
如下图,总有一天,你的这一个nginx服务器,可能会有故障的,也有可能会抗不住的,那怎么办?假如会有故障,我们要对nginx服务器高可用,nginx服务器同时是一个分发服务器,主要是转发用户请求的,,,,,,,,,,,,,,我们能够分发的服务器有哪些呢?lvs,nginx(基于反向代理模式工作的),haproxy,,,,,,,,nginx和haproxy是七层的,能理解具体应用协议的,lvs是四层的,,,,,更重要的是lvs是在内核中工作的,而nginx和haproxy是在用户空间中工作的,因为它们是服务,只要是服务,都是在用户空间的,,,,,,,,,性能当然是四层的好,性能上是内核空间的好,因为它不到用户空间直接转发了,所以lvs性能特别的好,,,,经过特殊优化之后,一个lvs抗几百万个请求都没有问题,可以在一个时间内,转发数百万个请求,,,,像nginx,haproxy能达到数万个请求就不错了,,,,它们不是一个档次和级别的,,,,,,,但是lvs是四层的,配置(任何一个分发器都要检查后端的real server的健康状况的),lvs自身不具备这种能力,还要调用ldirector,,,,,,,,,,,,另外一个,我们要使用dr模型,它的配置过程比较复杂,,,所以lvs,它的配置逻辑上比较复杂,但是性能确实很好,也是最好的一种,,,,,,由此我们的网站架构,你开始使用E配置的?????像nginx,haproxy都可以,但是nginx和haproxy比较起来,在同样的硬件条件下,它没有haproxy的转发能力强,,,,但是nginx对系统资源的要求量是非常小的,所以各有优缺点,,,,,,,,nginx转发能力虽然不如haproxy,但是差别不是很大,因为它俩都是服务,都基于事件驱动,都基于线程,,,,,,,,因此用哪一种都可以,有些站点采用nginx,有些站点采用haproxy,,,,,,,,,,,,,而nginx自身可以有缓存功能,haproxy的缓存能力差,如果有必要的话,可以借助于专业的缓存服务器来实现,比如varnish,,,,,,,,,,,,这种能力,本身就是转发器,直接就转发到app server了,尤其是lvs是这样的,直接转发过去,也就意味着每一个用户请求直接面向于app server了,,,,,,,
如下图,nginx如何降低每一个app server面临的压力?是在本地提供缓存实现的,让用户的请求异步转发至app server,让那些能够缓存的数据直接在本地提供缓存,(马哥提到了三个缓存,这个,以及memcache,xcache),,,这个缓存是干什么的?(memcache缓存的是从mysql中查找的数据,这个数据还要由我们的应用程序再处理一次的,)(xcache缓存的是应用程序php编译的结果的,可以在多进程之间共享op code的),,,,,,,这里的缓存是整个程序 op code 执行以后生成的结果的,包括 op code 加上数据,处理之后要输出一个结果的,这个结果数据要缓存下来......不然的话,每次要想请求同样一个应用逻辑的话,是不是都要让应用程序执行一遍,为了避免应用程序每次都反复执行,它就缓存了这个执行结果,,,,,,,,,转发服务器本身就很忙, 再让它负责缓存,那么压力会更大,可能会抗不住,我们将缓存独立出来,
如下图,前面有转发,你可以从lvs,nginx,haproxy中选型????而我们要独立出来一个缓存服务器的话,这个缓存服务器本身才是直接面临的(面向的)前端转发,,,,,,,所以说假如我有两个缓存服务器,我们前端的转发器,每一次转发的时候,直接将请求转发给缓存服务器,,,,,我们的缓存服务器,如果本地有,由缓存服务器构建响应,而由nginx再回转发,回送给客户端;;假如缓存服务器自身没有,再到 app server上去取数据,,,,,当然又出现一个问题,前端转发的时候,如果我第一次请求,转发到了第一个缓存服务器,第二次请求,转发给了第二个缓存服务器,当然,不能命中第一个缓存服务器了,,,,,为了提高命中率,做持久连接,,,,或者让两个缓存服务器做缓存同步,持久连接好像效果好一点,但是持久连接会破坏负载均衡效果的,,,,,,,,,,,
如下图,这些 app server 是服务于动态内容的,我们还可以加个服务于静态内容的服务器组,假如淘宝站点,图片量非常的大,我们可以使用一组服务器,专门用来存储图片,当用户请求静态内容的时候,我们直接给它转发至对应的图片服务器就可以了,只有用户请求php内容的时候,才转交给 app server ,(其实此时是应该先转发给varnish,然后可能直接返回,或再转发给app server),,,,很显然,对于图片的请求,我们也是转交给 varnish ,(有些??还是全部??静态内容由varnish到静态服务器中去,然后返回给varnish本地缓存图片)
如下图,当然我们也可以只让两个varnish专门为 app server提供缓存,再来两个 varnish 专门为图片服务器提供缓存,,,当我们请求图片内容的时候,向下面的两个varnish请求,进行相应的转发,,,,,,,,问题是我们怎么能够实现在nginx这里转发对于不同内容的请求呢?lvs没有这种能力,lvs无法判断你请求的内容是什么?(所以为了能够让有这种判断的能力,前面是lvs????后面放varnish,,varnish后面再放haproxy,向后面进行调度,,这样又加了一层,当然这样的系统已经达到了亿级pv的级别,才有必要搞这么复杂的)
我们的nginx到底如何实现对不同内容的请求能够转发至后端去,我们在nginx里面,我们如何用 nginx 做前端,nginx可以将用户的请求代理至后端,此前说过,如何将 nginx 对于 php 的请求转发至fastcgi服务器
反向代理,到我这儿请求,我这儿没有,我可以帮你去请求,,,,,,,,,为什么称为反向代理?既然有反向,就有正向
location ~* \.php$ {
fastcgi_pass 127.0.0.1:9000; # fastcgi_proxy???? 是用来定义反向代理的
}
fastcgi_proxy 是反向代理的一种,只反向代理了对fastcgi协议的访问, 如果说我们期望 nginx 对任何内容都向后反向代理,怎么办????
nginx的配置文件是分段的,由n个section组成,由main段(global段),,,,events段,,,,,,,,,标准的一大堆的http某个模块的段,好几个额外的段,,,,,,main直接在全局定义,events使用一组花括号定义,,,另外还有其它的section,如httpd,server,location,,这些都被称为分段的配置,location可以放在server中,也可以放在httpd中,server只能放在httpd中,server不能嵌套,,,,,location可以嵌套,,,,它们组织成的这个能够怎么配置的,彼此间可不可以嵌套的,我们称为上下文(context),,,比如这些叫httpd上下文,server上下文,location上下文,,,,,,,,,,,,,,,对于nginx来讲,它的每一个指令(directive 配置选项)必须使用分号结尾,每一个指令可能还有很多的参数(parameters,或者叫值)等等,都通过这样的格式来进行定义,,,,,,,,,,,
每个server用来定义一个虚拟主机,nginx必须要定义成一个虚拟主机的,它不像apache那样,有中心主机的概念,哪怕只有一个, 也得定义成主机,,,,,,,,,,
httpd是关于httpd相关的配置 (nginx不仅可以提供web功能,还能提供邮件功能) ,,,所以只要跟web相关,都要放在这里面,,,,,,,,,,,
events 定义事件驱动相关的内容 (nginx是事件驱动的),nginx使用哪个事件驱动 epoll(linux上的),kkil(是bsd上的)?? /dev/poll(soraris上的),,,,,,epoll本身可以定义很多的参数,比如epoll一次,一批可以扫描多少个事件驱动信号,一批可以处理多少个信号,都是可以定义的
main段不需要放在某个花括号里面,可以直接定义就可以了,主要是用来定义worker进程数,错误日志,用户,组等等
main段
worker_process # worker 进程数
error_log #错误日志
user #用户
group #组
events {
}
httpd {
}
server {
}
location {
directive <parameters>;
}
server {
listen 80; #listen指令是非常复杂的,不仅可以定义端口,还可以定义接收缓冲,发送缓冲,连接超时时长等
server_name www.magedu.com;
location / { #当用户请求的是这个location的内容,如果不能被其它location匹配的话,直接被转发至后端服务器去了,
#root 定义我们的网页文件在哪里,现在本地不提供任何网页内容了
#后端服务器;;;;;;;;;都转发到后端有个服务器来提供服务的,使用代理,明确定义上游服务器(后端服务器),当前的nginx是代理
}
}
反向代理: 使用 proxy_pass 明确说明转发给谁,
location: 后面一般跟URI, 说明是uri路径,里面定义的是网页存放的位置,还可以定义访问控制规则,(谁能访问,谁不能访问) 定义uri的访问属性 定义uri及对应的文件系统的操作属性?????
location [op] URI { #op是操作符 波浪线~, 波浪线星~*, 拖字符波浪线^~,等于=,
}
#op是操作符
波浪线~, 区分大小写正则表达式原字符匹配
波浪线星~*, 不区分大小写正则表达式原字符匹配
拖字符波浪线^~,拖字符^表示否,,,,,,,,不作正则表达式原字符匹配 (算作模式匹配),作逐字符搜索的
等于=, 路径精确匹配,只包含自己当前路径,如果是个目录,都不包含目录下的内容,,,,,,,所以通常用来匹配一个文件的
location [op] URI { # 里面的root 换成 proxy_pass, 就能够实现将用户的请求定向到后端其它服务器上去的,,,,proxy_pass的格式 通常是URL, 如下,所以它会把 URI 映射为路径 http://172.16.100.11/
proxy_pass http://172.16.100.11/;
}
server {
listen 80;
server_name www.magedu.com
location /forum { #如果 location后面有模式匹配的话, 是不能从 /forum 转换到 http://172.16.100.11:8080/bbs 只能指到 http://172.16.100.11:8080 ,,,,,,,,,,,,多了就算语法错误
proxy_pass http://172.16.100.11:8080/bbs; #去访问这个服务器的8080
}
}
用户访问 http://www.magedu.com/forum/
-->http://172.16.100.11:8080/bbs
location ~* ^/forum { #所有的uri路径中以/forum开头的, 对 http://www.magedu.com/forum/ 的访问能匹配到此location,所以它一定会将这个请求的/forum这个串匹配附加在 http://172.16.100.11:8080 的后面,即 http://172.16.100.11:8080/forum 而且这个/forum还得是服务器自己本地的才能正常访问
proxy_pass http://172.16.100.11:8080; #用模式匹配时后面 不能跟内容 比如 跟 /bbs
}
此时用户访问 http://www.magedu.com/forum/
-->http://172.16.100.11:8080/forum
location @name {
}
如下图,我们的局域网中,工作在客户端前端,我们的局域网中有一大堆用户,需要访问互联网,但是这堆用户都是私有地址,上不了互联网,我们该怎么办?源地址转换??这里我们不做源地址转换了,我们做一个代理服务器,是一个web代理,用户请求别的内容我们不管,如果请求的是80端口的web的话,我们都转发给代理服务器,而我们的代理服务器如果发现没有,由代理服务器上互联网,从互联网上取回来之后,放在代理服务器本地,在代理服务器本地构建响应,返给客户端,,,这个代理服务器干什么用?是代理客户端访问互联网服务器的,,,这种代理我们称为正向代理,,,,,,,,,,,这个代理服务器相当于总管,告诉别人,到我这里啥都找得到,随便你上哪个站点,,,,,,,上web服务器的时候,只需要找代理服务器,无论搜狐,新浪都能找,
如下图,我们的服务器不允许其它人直接访问,在服务器前面放一个代理人,所有来自于互联网的客户端,要想访问我们的服务器,得先把请求交给我们前端的这个服务器,而由前端服务器需要跟我们的服务器联系的时候,再来找我,(这个代理服务器可以理解成秘书),,,,,,这就叫反向代理,,,,,,,,,,,它把我们web服务器的内容在代理服务器那儿输出了,它告诉别人我就是web服务器,事实上它不是web服务器,,,,,,,,,,它只代理我这一家站点,
三、Nginx反向代理
Nginx通过proxy模块实现反向代理功能。在作为web反向代理服务器时,nginx负责接收客户请求,并能够根据URI、客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server)。nginx在实现反向代理功能时的最重要指令为proxy_pass,它能够将location定义的某URI代理至指定的上游服务器(组)上。如下面的示例中,location的/uri将被替换为上游服务器上的/newuri。
location /uri {
proxy_pass http://www.magedu.com:8080/newuri;
}
不过,这种处理机制中有两个例外。一个是如果location的URI是通过模式匹配定义的,其URI将直接被传递至上游服务器,而不能为其指定转换的另一个URI。例如下面示例中的/forum将被代理为http://www.magedu.com/forum。
location ~ ^/forum {
proxy_pass http://www.magedu.com;
}
第二个例外是,如果在location中使用的URL重定向,那么nginx将使用重定向后的URI处理请求,而不再考虑上游服务器上定义的URI。如下面所示的例子中,传送给上游服务器的URI为/index.php?page=<match>,而不是/index。
location / {
rewrite /(.*)$ /index.php?page=$1 break;
proxy_pass http://localhost:8080/index;
}
3.1 proxy模块的指令
proxy模块的可用配置指令非常多,它们分别用于定义proxy模块工作时的诸多属性,如连接超时时长、代理时使用http协议版本等。下面对常用的指令做一个简单说明。
proxy_connect_timeout:nginx将一个请求发送至upstream server之前等待的最大时长;
proxy_cookie_domain:将upstream server通过Set-Cookie首部设定的domain属性修改为指定的值,其值可以为一个字符串、正则表达式的模式或一个引用的变量;
proxy_cookie_path: 将upstream server通过Set-Cookie首部设定的path属性修改为指定的值,其值可以为一个字符串、正则表达式的模式或一个引用的变量;
proxy_hide_header:设定发送给客户端的报文中需要隐藏的首部;
proxy_pass:指定将请求代理至upstream server的URL路径;
proxy_set_header:将发送至upsream server的报文的某首部进行重写;
proxy_redirect:重写location并刷新从upstream server收到的报文的首部;
proxy_send_timeout:在连接断开之前两次发送至upstream server的写操作的最大间隔时长;
proxy_read_timeout:在连接断开之前两次从接收upstream server接收读操作的最大间隔时长;
如下面的一个示例:
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 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 30;
proxy_send_timeout 15;
proxy_read_timeout 15;
3.2 upstream 模块
与proxy模块结合使用的模块中,最常用的当属upstream模块。upstream模块可定义一个新的上下文,它包含了一组宝岛upstream服务器???????,这些服务器可能被赋予了不同的权重、不同的类型甚至可以基于维护等原因被标记为down。
upstream模块常用的指令有:
ip_hash:基于客户端IP地址完成请求的分发,它可以保证来自于同一个客户端的请求始终被转发至同一个upstream服务器;
keepalive:每个worker进程为发送到upstream服务器的连接所缓存的个数??????;
least_conn:最少连接调度算法;
server:定义一个upstream服务器的地址,还可包括一系列可选参数,如:
weight:权重;
max_fails:最大失败连接次数,失败连接的超时时长由fail_timeout指定;
fail_timeout:等待请求的目标服务器发送响应的时长;
backup:用于fallback的目的,所有服务均故障时才启动此服务器;
down:手动标记其不再处理任何请求;
例如:
upstream backend {
server www.magedu.com weight=5;
server www2.magedu.com:8080 max_fails=3 fail_timeout=30s;
}
upstream模块的负载均衡算法主要有三种,轮调(round-robin)、ip哈希(ip_hash)和最少连接(least_conn)三种。
此外,upstream模块也能为非http类的应用实现负载均衡,如下面的示例定义了nginx为memcached服务实现负载均衡之目的。
upstream memcachesrvs {
server 172.16.100.6:11211;
server 172.16.100.7:11211;
}
server {
location / {
set $memcached_key "$uri?$args";
memcached_pass memcachesrvs;
error_page 404 = @fallback;
}
location @fallback {
proxy_pass http://127.0.0.1:8080;
}
}
3.3 if判断语句
在location中使用if语句可以实现条件判断,其通常有一个return语句,且一般与有着last或break标记的rewrite规则一同使用。但其也可以按需要使用在多种场景下,需要注意的是,不当的使用可能会导致不可预料的后果。
location / {
if ($request_method == “PUT”) {
proxy_pass http://upload.magedu.com:8080;
}
if ($request_uri ~ "\.(jpg|gif|jpeg|png)$") {
proxy_pass http://imageservers;
break;
}
}
upstream imageservers {
server 172.16.100.8:80 weight 2;
server 172.16.100.9:80 weight 3;
}
3.3.1 if语句中的判断条件
正则表达式匹配:
~:与指定正则表达式模式匹配时返回“真”,判断匹配与否时区分字符大小写;
~*:与指定正则表达式模式匹配时返回“真”,判断匹配与否时不区分字符大小写;
!~:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时区分字符大小写;
!~*:与指定正则表达式模式不匹配时返回“真”,判断匹配与否时不区分字符大小写;
文件及目录匹配判断:
-f, !-f:判断指定的路径是否为存在且为文件;
-d, !-d:判断指定的路径是否为存在且为目录;
-e, !-e:判断指定的路径是否存在,文件或目录均可;
-x, !-x:判断指定路径的文件是否存在且可执行;
3.3.2 nginx常用的全局变量
下面是nginx常用的全局变量中的一部分,它们经常用于if语句中实现条件判断。
$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri
[root@master ~]# cd /etc/nginx/
[root@master nginx]# pwd
/etc/nginx
[root@master nginx]#
[root@master nginx]# mv nginx.conf nginx.conf.fastcgi #备份下上次修改的
[root@master nginx]# cp nginx.conf.bak nginx.conf #使用原生默认的配置文件
[root@master nginx]#
[root@master nginx]# service nginx restart
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
停止 nginx: [确定]
正在启动 nginx: [确定]
[root@master nginx]#
[root@master nginx]# pwd
/etc/nginx
[root@master nginx]# vim nginx.conf #原生默认的配置文件内容
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443;
# server_name localhost;
# ssl on;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_timeout 5m;
# ssl_protocols SSLv2 SSLv3 TLSv1;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}
[root@master nginx]# cd /usr/html
[root@master html]#
[root@master html]# ls /usr/html
50x.html index.html
[root@master html]#
[root@master html]# mkdir /usr/html/forum
[root@master html]#
[root@master html]# vim /usr/html/forum/index.html
<h1>Forum ON Nginx.</h1>
现在让对 /forum 的访问到另一台服务器上去
在另一台服务器 192.168.0.61 上
[root@slave ~]# yum install httpd
在另一台服务器 192.168.0.61 上
[root@slave ~]# cd /var/www/html/
[root@slave html]# ls
[root@slave html]# mkdir forum
[root@slave html]# cd forum
[root@slave forum]# ls
[root@slave forum]# pwd
/var/www/html/forum
[root@slave forum]#
[root@slave forum]# vim index.html
<h1>Forum ON BackServer Apache. </h1>
在另一台服务器 192.168.0.61 上
[root@slave forum]# service httpd restart
停止 httpd: [确定]
正在启动 httpd: [确定]
[root@slave forum]#
在第一台服务器 192.168.0.60 上
[root@master html]# vim /etc/nginx/nginx.conf
..................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /forum/ {
proxy_pass http://192.168.0.61/bbs; #192.168.0.61是另一台服务器
}
location / {
root html;
index index.html index.htm;
}
..................................
[root@master html]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master html]#
[root@master html]# service nginx restart
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
停止 nginx: [确定]
正在启动 nginx: [确定]
[root@master html]#
在另一台服务器 192.168.0.61 上
[root@slave html]# mv forum/ bbs
[root@slave html]#
在另一台服务器 192.168.0.61 上
[root@master html]# curl http://192.168.0.60 #192.168.0.60是本机
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
[root@master html]#
[root@master html]# curl http://192.168.0.60/forum
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.4.7</center>
</body>
</html>
[root@master html]#
马哥的 如下图
我的
在第一台服务器 192.168.0.60 上
[root@master html]# vim /etc/nginx/nginx.conf
....................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /forum { #把 /forum 后面的斜杠去掉
proxy_pass http://192.168.0.61/bbs; #192.168.0.61是另一台服务器
}
location / {
root html;
index index.html index.htm;
}
....................................................................
[root@master html]# service nginx restart
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
停止 nginx: [确定]
正在启动 nginx: [确定]
[root@master html]#
在第一台服务器 192.168.0.60 上
root@master html]# curl http://192.168.0.60/forum
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://192.168.0.61/bbs/">here</a>.</p>
<hr>
<address>Apache/2.2.15 (Red Hat) Server at 192.168.0.61 Port 80</address>
</body></html>
[root@master html]#
http://192.168.0.60/forum/ #好像正常了
在第一台服务器 192.168.0.60 上
[root@master html]# vim /etc/nginx/nginx.conf
....................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /forum/ { #把 forum 和 下面的 bbs 后面都有斜杠也像也没问题
proxy_pass http://192.168.0.61/bbs/;
}
location / {
root html;
index index.html index.htm;
}
....................................................................
在第一台服务器 192.168.0.60 上
[root@master html]# service nginx restart
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
停止 nginx: [确定]
正在启动 nginx: [确定]
[root@master html]#
在第一台服务器 192.168.0.60 上
[root@master html]# curl http://192.168.0.60/forum
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.4.7</center>
</body>
</html>
[root@master html]#
在第一台服务器 192.168.0.60 上
[root@master html]# vim /etc/nginx/nginx.conf
....................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location ~* ^/forum { #使用正则
proxy_pass http://192.168.0.61/bbs;
}
location / {
root html;
index index.html index.htm;
}
....................................................................
[root@master html]# nginx -t
nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block in /etc/nginx/nginx.conf:43
nginx: configuration file /etc/nginx/nginx.conf test failed
[root@master html]#
在第一台服务器 192.168.0.60 上
[root@master html]# vim /etc/nginx/nginx.conf
....................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location ~* ^/forum { #使用正则,,,,,,forum 路径会被映射到 http://192.168.0.61 后面
proxy_pass http://192.168.0.61; #把 /bbs 去掉 ,,,
}
location / {
root html;
index index.html index.htm;
}
....................................................................
[root@master html]# nginx -t #没错了
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master html]#
[root@master html]# service nginx reload #重载一下
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master html]#
http://192.168.0.60/forum 访问不到了 ,因为 location 使用正则时,forum 会对应到 http://192.168.0.61 的forum
在另一台服务器 192.168.0.61 上
[root@slave html]# mv bbs/ forum
[root@slave html]#
http://192.168.0.60/forum/ 现在可以了
下图画框是一些请求和响应信息
[root@master html]# curl -I http://192.168.0.60/forum #仅显示首部信息
HTTP/1.1 301 Moved Permanently
Server: nginx/1.4.7
Date: Thu, 29 Apr 2021 06:14:01 GMT
Content-Type: text/html; charset=iso-8859-1
Location: http://192.168.0.60/forum/
Connection: keep-alive
[root@master html]#
在另一台服务器 192.168.0.61 上
[root@slave html]# tail /var/log/httpd/access_log
#后端服务器记录日志的时候,访问端记录的是192.168.0.60,是代理服务器的ip地址,不是我们浏览器物理机的ip地址
192.168.0.60 - - [29/Apr/2021:13:13:25 +0800] "GET /bbs/ HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.0.60 - - [29/Apr/2021:14:11:20 +0800] "GET /forum// HTTP/1.0" 404 284 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:11:22 +0800] "GET /forum// HTTP/1.0" 404 284 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:11:22 +0800] "GET /forum// HTTP/1.0" 404 284 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:11:27 +0800] "GET /forum/ HTTP/1.0" 404 283 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.0.60 - - [29/Apr/2021:14:14:50 +0800] "GET /forum// HTTP/1.0" 200 38 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:14:57 +0800] "GET /forum/ HTTP/1.0" 200 38 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.0.60 - - [29/Apr/2021:14:19:41 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:26:41 +0800] "HEAD /forum HTTP/1.0" 301 - "-" "curl/7.19.7 (i686-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
192.168.0.60 - - [29/Apr/2021:14:26:56 +0800] "HEAD /forum HTTP/1.0" 301 - "-" "curl/7.19.7 (i686-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
[root@slave html]#
如下图, apache 日志里是 nginx 自己创建报文请求的,后端服务器记录的客户端地址,地址是 nginx 服务器的地址,不是客户端的地址,,,,,,,,,,,,,,,,,,,
所以记录的地址没意义
nginx提供代理功能是靠代理模块来提供的,,,,,,,,,,,,,,,,,,,
https://www.nginx.cn/doc/standard/httpproxy.html
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_proxy_module.html
proxy_set_header 可以在向后代理的时候,把这个请求报文里面, 在代理服务器(nginx)添加一个特有的httpd首部,,将用户的请求转发至后端 upstream server,转发时,可以设定一个独特的header,
proxy_set_header Host $proxy_host; #改改host,表示请求的服务器改了, proxy_set_header Connection Close; #改改connection
proxy_set_header X-Real-IP $remote_addr #特有的首部 X-Real-IP,实际ip地址,nginx提供的,,,,X-Real-IP对应的值是客户端自己的地址,每次不同的客户端人家是不同的地址,,,,,把客户端地址通过这个独特的首部传递给后端的web服务器,后端web服务器记录到日志时记录下来就可以了
核心模块提供了很多变量,都可以使用
The core module supports built-in variables, whose names correspond with the names of variables in Apache.
First of all, there are the variables, which represent the lines of the title of the client request, for example,$http_user_agent
,$http_cookie
, and so forth.
Furthermore, there are other variables:
This variable contains the value of theGET
request variable PARAMETER if present in the query string
This variable is equal to arguments in the line of request;
The address of the client in binary form;
(undocumented)
This variable is equal to lineContent-Length
in the header of request;
This variable is equal to lineContent-Type
in the header of request;
The value of the cookie COOKIE;
This variable is equal to the value of directive root for the current request;
The same as $uri.
This variable is equal to lineHost
in the header of request or name of the server processing the request if theHost
header is not available.
The value of the HTTP header HEADER when converted to lowercase and with 'dashes' converted to 'underscores', e.g. $http_user_agent, $http_referer...;
Evaluates to "?" if $args is set, "" otherwise.
This variable allows limiting the connection rate.
The same as $args.
The address of the client.
The port of the client;
This variable is equal to the name of user, authenticated by the Auth Basic Module;
This variable is equal to path to the file for the current request, formed from directives root or alias and URI request;
This variable(0.7.58+) contains the body of the request. The significance of this variable appears in locations with directives proxy_pass or fastcgi_pass.
Client request body temporary filename;
(undocumented)
This variable is equal to the method of request, usuallyGET
orPOST
HEAD
PUT
TRACE
OPTIONS
CONNECTION
DELETE
This variable is equal to the complete initial URI together with the arguments;
The HTTP scheme (i.e. http, https). Evaluated only on demand, for example:
rewrite ^(.+)$ $scheme://example.com$1 redirect;
Equal to the server address. As a rule, for obtaining the value of this variable is done one system call. In order to avoid system call, it is necessary to indicate addresses in directives listen and to use parameterbind
.
The name of the server.
This variable is equal to the port of the server, to which the request arrived;
This variable is equal to the protocol of request, usually thisHTTP/1.0
orHTTP/1.1
.
This variable is equal to current URI in the request, it can differ from initial, for example by internal redirects, or with the use of index it is file with internal redirects.
在第一台服务器上(前端服务器nginx)
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location ~* ^/forum {
proxy_pass http://192.168.0.61;
proxy_set_header X-Real-IP $remote_addr; #每次转发请求到后端以后,后端的每一个请求报文里面都有个独特的首部叫 X-Real-IP ,这个X-Real-IP也会被传送到后端
}
location / {
root html;
index index.html index.htm;
}
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
在另一台服务器上(后端)
[root@slave ~]# tail /var/log/httpd/access_log #远程ip好像还是 192.168.0.60(nginx的地址)
192.168.0.60 - - [29/Apr/2021:14:11:22 +0800] "GET /forum// HTTP/1.0" 404 284 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:11:22 +0800] "GET /forum// HTTP/1.0" 404 284 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:11:27 +0800] "GET /forum/ HTTP/1.0" 404 283 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.0.60 - - [29/Apr/2021:14:14:50 +0800] "GET /forum// HTTP/1.0" 200 38 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:14:57 +0800] "GET /forum/ HTTP/1.0" 200 38 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.0.60 - - [29/Apr/2021:14:19:41 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:26:41 +0800] "HEAD /forum HTTP/1.0" 301 - "-" "curl/7.19.7 (i686-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
192.168.0.60 - - [29/Apr/2021:14:26:56 +0800] "HEAD /forum HTTP/1.0" 301 - "-" "curl/7.19.7 (i686-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
192.168.0.60 - - [30/Apr/2021:08:49:45 +0800] "GET /forum// HTTP/1.0" 200 38 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [30/Apr/2021:08:49:47 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
[root@slave ~]#
[root@slave ~]# vim /etc/httpd/conf/httpd.conf
................................................................................
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
#百分号花括号 X-Real-IP这个首部中的 i 百分号后面加个某个具体的http首部,再加个i,表示引用它的值,,就是客户端地址
................................................................................
[root@slave ~]# tail /var/log/httpd/access_log #192.168.0.103是我的电脑上的地址,真正的客户端了
192.168.0.60 - - [29/Apr/2021:14:14:57 +0800] "GET /forum/ HTTP/1.0" 200 38 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
192.168.0.60 - - [29/Apr/2021:14:19:41 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [29/Apr/2021:14:26:41 +0800] "HEAD /forum HTTP/1.0" 301 - "-" "curl/7.19.7 (i686-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
192.168.0.60 - - [29/Apr/2021:14:26:56 +0800] "HEAD /forum HTTP/1.0" 301 - "-" "curl/7.19.7 (i686-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
192.168.0.60 - - [30/Apr/2021:08:49:45 +0800] "GET /forum// HTTP/1.0" 200 38 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.60 - - [30/Apr/2021:08:49:47 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.103 - - [30/Apr/2021:08:58:33 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.103 - - [30/Apr/2021:08:58:34 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.103 - - [30/Apr/2021:08:58:34 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
192.168.0.103 - - [30/Apr/2021:08:58:34 +0800] "GET /forum// HTTP/1.0" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
[root@slave ~]#
对整个网站的访问通通代理到后端
在第一台服务器上(前端服务器nginx)
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
location / {
proxy_pass http://192.168.0.61/; #最后加斜线
proxy_set_header X-Real-IP $remote_addr;
}
#location / {
# root html;
# index index.html index.htm;
#}
................................................................................
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 是后端web页面
nginx 一个location可以代理多个后台服务器,可以负载均衡, 可以检查后端real server?的健康状况,这已经不是proxy的功能了,得把几个后台服务器定义成组,,这叫 upstream
upstream 模块将多个服务器归并成一个组,在一个组里面定义负载均衡调度算法,,,,,,,,,,,,,,,,
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_upstream_module.html
https://www.nginx.cn/doc/standard/httpupstream.html
配置例子 指令 upstream server ip_hash keepalive least_conn 嵌入的变量 |
ngx_http_upstream_module
模块 允许定义一组服务器。它们可以在指令proxy_pass、 fastcgi_pass和 memcached_pass中被引用到。
upstream 是定义在server之外的,
upstream backend { server backend1.example.com weight=5; # server定义后端服务器的 weight表示权重 没有权重,是不做负载均衡的,第一次分配给谁,就永远分配给谁??
有了权重以后,可以实现加权轮调,权重一样,那就是轮调 server backend2.example.com:8080; # 可以端口映射 server后面只能跟域名或地址,前面没有http等协议 server unix:/tmp/backend3; server backup1.example.com:8080 backup; server backup2.example.com:8080 backup; } server { location / { proxy_pass http://backend; } }
语法: | upstream |
默认值: | — |
上下文: | http |
定义一组服务器。 这些服务器可以监听不同的端口。 而且,监听在TCP和UNIX域套接字的服务器可以混用。
例子:
upstream backend { server backend1.example.com weight=5; server 127.0.0.1:8080 max_fails=3 fail_timeout=30s; server unix:/tmp/backend3; }
默认情况下,nginx按加权轮转的方式将请求分发到各服务器。 在上面的例子中,每7个请求会通过以下方式分发: 5个请求分到backend1.example.com
, 一个请求分到第二个服务器,一个请求分到第三个服务器。 与服务器通信的时候,如果出现错误,请求会被传给下一个服务器,直到所有可用的服务器都被尝试过。 如果所有服务器都返回失败,客户端将会得到最后通信的那个服务器的(失败)响应结果。
语法: | server |
默认值: | — |
上下文: | upstream |
定义服务器的地址address
和其他参数parameters
。 地址可以是域名或者IP地址,端口是可选的,或者是指定“unix:
”前缀的UNIX域套接字的路径。如果没有指定端口,就使用80端口。 如果一个域名解析到多个IP,本质上是定义了多个server。
你可以定义下面的参数:
weight
=number
设定服务器的权重,默认是1。
max_fails
=number
设定Nginx与服务器通信的尝试失败的次数。在fail_timeout
参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout
时间段,服务器不会再被尝试。 失败的尝试次数默认是1。设为0就会停止统计尝试次数,认为服务器是一直可用的。 你可以通过指令proxy_next_upstream、 fastcgi_next_upstream和 memcached_next_upstream来配置什么是失败的尝试。 默认配置时,http_404
状态不被认为是失败的尝试。
fail_timeout
=time
设定
默认情况下,该超时时间是10秒。
统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。
服务器被认为不可用的时间段。
backup
标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器。
down
标记服务器永久不可用,可以跟ip_hash指令一起使用。
Example:
upstream backend { server backend1.example.com weight=5; server 127.0.0.1:8080 max_fails=3 fail_timeout=30s; server unix:/tmp/backend3; server backup1.example.com:8080 backup; }
语法: | ip_hash; |
默认值: | — |
上下文: | upstream |
指定服务器组的负载均衡方法,请求基于客户端的IP地址在服务器间进行分发。 IPv4地址的前三个字节或者IPv6的整个地址,会被用来作为一个散列key。 这种方法可以确保从同一个客户端过来的请求,会被传给同一台服务器。除了当服务器被认为不可用的时候,这些客户端的请求会被传给其他服务器,而且很有可能也是同一台服务器。
从1.3.2和1.2.2版本开始支持IPv6地址。
如果其中一个服务器想暂时移除,应该加上down
参数。这样可以保留当前客户端IP地址散列分布。
例子:
upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com down; server backend4.example.com; }
从1.3.1和1.2.2版本开始,ip_hash
的负载均衡方法才支持设置服务器权重值。
语法: | keepalive |
默认值: | — |
上下文: | upstream |
这个指令出现在版本 1.1.4.
激活对上游服务器的连接进行缓存。
connections
参数设置每个worker进程与后端服务器保持连接的最大数量。这些保持的连接会被放入缓存。 如果连接数大于这个值时,最久未使用的连接会被关闭。
需要注意的是,keepalive
指令不会限制Nginx进程与上游服务器的连接总数。 新的连接总会按需被创建。connections
参数应该稍微设低一点,以便上游服务器也能处理额外新进来的连接?????????。
配置memcached上游服务器连接keepalive的例子:
upstream memcached_backend { server 127.0.0.1:11211; server 10.0.0.2:11211; keepalive 32; } server { ... location /memcached/ { set $memcached_key $uri; memcached_pass memcached_backend; } }
对于HTTP代理,proxy_http_version指令应该设置为“1.1
”,同时“Connection”头的值也应被清空。
upstream http_backend { server 127.0.0.1:8080; keepalive 16; } server { ... location /http/ { proxy_pass http://http_backend; proxy_http_version 1.1; proxy_set_header Connection ""; ... } }
另外一种选择是,HTTP/1.0协议的持久连接也可以通过发送“Connection: Keep-Alive”头来实现。不过不建议这样用。
对于FastCGI的服务器,需要设置 fastcgi_keep_conn 指令来让连接keepalive工作:
upstream fastcgi_backend { server 127.0.0.1:9000; keepalive 8; } server { ... location /fastcgi/ { fastcgi_pass fastcgi_backend; fastcgi_keep_conn on; ... } }
当使用的负载均衡方法不是默认的轮转法时,必须在keepalive
指令之前配置。
针对SCGI和uwsgi协议,还没有实现其keepalive连接的打算。
语法: | least_conn; |
默认值: | — |
上下文: | upstream |
这个指令出现在版本 1.3.1 和 1.2.2.
指定服务器组的负载均衡方法,根据其权重值,将请求发送到活跃连接数最少的那台服务器。 如果这样的服务器有多台,那就采取有权重的轮转法进行尝试。
ngx_http_upstream_module
模块支持以下嵌入变量:
$upstream_addr
保存服务器的IP地址和端口或者是UNIX域套接字的路径。 在请求处理过程中,如果有多台服务器被尝试了,它们的地址会被拼接起来,以逗号隔开,比如: “192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock
”。 如果在服务器之间通过“X-Accel-Redirect”头或者error_page有内部跳转,那么这些服务器组之间会以冒号隔开,比如:“192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock : 192.168.10.1:80, 192.168.10.2:80
”。
$upstream_response_time
以毫秒的精度保留服务器的响应时间,(输出)单位是秒。 出现多个响应时,也是以逗号和冒号隔开。
$upstream_status
保存服务器的响应代码。 出现多个响应时,也是以逗号和冒号隔开。
$upstream_http_...
保存服务器的响应头的值。比如“Server”响应头的值可以通过$upstream_http_server
变量来获取。 需要注意的是只有最后一个响应的头会被保留下来。
翻译: Weibin Yao |
准备一个前端nginx 192.168.0.60
再准备两个后端apache 192.168.0.61 192.168.0.62
前端 nginx 192.168.0.60
第二个后端 apache 192.168.0.62
[root@mysql-proxy ~]# yum -y install httpd
第一个后端 apache 192.168.0.61
[root@slave ~]# vim /var/www/html/index.html
<h1>node1.magedu.com</h1>
第二个后端 apache 192.168.0.62
[root@mysql-proxy ~]# vim /var/www/html/index.html
<h1>node2.magedu.com</h1>
[root@mysql-proxy ~]# chkconfig --list httpd
httpd 0:关闭 1:关闭 2:关闭 3:关闭 4:关闭 5:关闭 6:关闭
[root@mysql-proxy ~]# chkconfig httpd on
[root@mysql-proxy ~]# chkconfig --list httpd
httpd 0:关闭 1:关闭 2:启用 3:启用 4:启用 5:启用 6:关闭
[root@mysql-proxy ~]# service httpd restart
停止 httpd: [确定]
正在启动 httpd: [确定]
[root@mysql-proxy ~]#
http://192.168.0.61/ 可直接访问
http://192.168.0.62/ 可直接访问
前端 nginx 192.168.0.60
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
upstream websrvs { #upstream定义在server的外面, upstream有个名字
server 192.168.0.61 weight=1;
server 192.168.0.62 weight=2;
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://websrvs;#改proxy_pass 这样就直接调度到upstream 的 websrvs,由upstream完成负载均衡
proxy_set_header X-Real-IP $remote_addr;
}
................................................................................
前端 nginx 192.168.0.60
[root@master ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 多次刷新有变化的,实现了负载均衡
如果某个后台服务器挂了,?upstream可以做健康状况检查,
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_upstream_module.html
翻译内容可能已经过旧。 你可以通过 英文版本 查看最近的更新。
配置例子 指令 upstream server ip_hash keepalive least_conn 嵌入的变量 |
ngx_http_upstream_module
模块 允许定义一组服务器。它们可以在指令proxy_pass、 fastcgi_pass和 memcached_pass中被引用到。
upstream backend { server backend1.example.com weight=5; server backend2.example.com:8080; server unix:/tmp/backend3; server backup1.example.com:8080 backup; server backup2.example.com:8080 backup; } server { location / { proxy_pass http://backend; } }
语法: | upstream |
默认值: | — |
上下文: | http |
定义一组服务器。 这些服务器可以监听不同的端口。 而且,监听在TCP和UNIX域套接字的服务器可以混用。
例子:
upstream backend { server backend1.example.com weight=5; server 127.0.0.1:8080 max_fails=3 fail_timeout=30s; server unix:/tmp/backend3; }
默认情况下,nginx按加权轮转的方式将请求分发到各服务器。 在上面的例子中,每7个请求会通过以下方式分发: 5个请求分到backend1.example.com
, 一个请求分到第二个服务器,一个请求分到第三个服务器。 与服务器通信的时候,如果出现错误,请求会被传给下一个服务器,直到所有可用的服务器都被尝试过。 如果所有服务器都返回失败,客户端将会得到最后通信的那个服务器的(失败)响应结果。
语法: | server |
默认值: | — |
上下文: | upstream |
定义服务器的地址address
和其他参数parameters
。 地址可以是域名或者IP地址,端口是可选的,或者是指定“unix:
”前缀的UNIX域套接字的路径。如果没有指定端口,就使用80端口。 如果一个域名解析到多个IP,本质上是定义了多个server。?????
你可以定义下面的参数:
weight
=number #权重
设定服务器的权重,默认是1。
max_fails
=number #最大错误次数
设定Nginx与服务器通信的尝试失败的次数。在fail_timeout
参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可用。在下一个fail_timeout
时间段,服务器不会再被尝试。 失败的尝试次数默认是1。设为0就会停止统计尝试次数,认为服务器是一直可用的。 你可以通过指令proxy_next_upstream、 fastcgi_next_upstream和 memcached_next_upstream来配置什么是失败的尝试。 默认配置时,http_404
状态不被认为是失败的尝试。
fail_timeout
=time #检查错误最大持续时间,默认10秒
设定
默认情况下,该超时时间是10秒。
统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可用。
服务器被认为不可用的时间段。
backup
标记为备用服务器。当主服务器不可用以后,请求会被传给这些服务器。
down
标记服务器永久不可用,可以跟ip_hash指令一起使用。
Example:
upstream backend { server backend1.example.com weight=5; server 127.0.0.1:8080 max_fails=3 fail_timeout=30s; server unix:/tmp/backend3; server backup1.example.com:8080 backup; }
语法: | ip_hash; |
默认值: | — |
上下文: | upstream |
指定服务器组的负载均衡方法,请求基于客户端的IP地址在服务器间进行分发。 IPv4地址的前三个字节或者IPv6的整个地址,会被用来作为一个散列key。 这种方法可以确保从同一个客户端过来的请求,会被传给同一台服务器。除了当服务器被认为不可用的时候,这些客户端的请求会被传给其他服务器,而且很有可能也是同一台服务器。
从1.3.2和1.2.2版本开始支持IPv6地址。
如果其中一个服务器想暂时移除,应该加上down
参数。这样可以保留当前客户端IP地址散列分布。
例子:
upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com down; server backend4.example.com; }
从1.3.1和1.2.2版本开始,ip_hash
的负载均衡方法才支持设置服务器权重值。
语法: | keepalive |
默认值: | — |
上下文: | upstream |
这个指令出现在版本 1.1.4.
激活对上游服务器的连接进行缓存。
connections
参数设置每个worker进程与后端服务器保持连接的最大数量。这些保持的连接会被放入缓存。 如果连接数大于这个值时,最久未使用的连接会被关闭。
需要注意的是,keepalive
指令不会限制Nginx进程与上游服务器的连接总数。 新的连接总会按需被创建。connections
参数应该稍微设低一点,以便上游服务器也能处理额外新进来的连接。
配置memcached上游服务器连接keepalive的例子:
upstream memcached_backend { server 127.0.0.1:11211; server 10.0.0.2:11211; keepalive 32; } server { ... location /memcached/ { set $memcached_key $uri; memcached_pass memcached_backend; } }
对于HTTP代理,proxy_http_version指令应该设置为“1.1
”,同时“Connection”头的值也应被清空。
upstream http_backend { server 127.0.0.1:8080; keepalive 16; } server { ... location /http/ { proxy_pass http://http_backend; proxy_http_version 1.1; proxy_set_header Connection ""; ... } }
另外一种选择是,HTTP/1.0协议的持久连接也可以通过发送“Connection: Keep-Alive”头来实现。不过不建议这样用。
对于FastCGI的服务器,需要设置 fastcgi_keep_conn 指令来让连接keepalive工作:
upstream fastcgi_backend { server 127.0.0.1:9000; keepalive 8; } server { ... location /fastcgi/ { fastcgi_pass fastcgi_backend; fastcgi_keep_conn on; ... } }
当使用的负载均衡方法不是默认的轮转法时,必须在keepalive
指令之前配置。
针对SCGI和uwsgi协议,还没有实现其keepalive连接的打算。
语法: | least_conn; |
默认值: | — |
上下文: | upstream |
这个指令出现在版本 1.3.1 和 1.2.2.
指定服务器组的负载均衡方法,根据其权重值,将请求发送到活跃连接数最少的那台服务器。 如果这样的服务器有多台,那就采取有权重的轮转法进行尝试。
ngx_http_upstream_module
模块支持以下嵌入变量:
$upstream_addr
保存服务器的IP地址和端口或者是UNIX域套接字的路径。 在请求处理过程中,如果有多台服务器被尝试了,它们的地址会被拼接起来,以逗号隔开,比如: “192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock
”。 如果在服务器之间通过“X-Accel-Redirect”头或者error_page有内部跳转,那么这些服务器组之间会以冒号隔开,比如:“192.168.1.1:80, 192.168.1.2:80, unix:/tmp/sock : 192.168.10.1:80, 192.168.10.2:80
”。
$upstream_response_time
以毫秒的精度保留服务器的响应时间,(输出)单位是秒。 出现多个响应时,也是以逗号和冒号隔开。
$upstream_status
保存服务器的响应代码。 出现多个响应时,也是以逗号和冒号隔开。
$upstream_http_...
保存服务器的响应头的值。比如“Server”响应头的值可以通过$upstream_http_server
变量来获取。 需要注意的是只有最后一个响应的头会被保留下来。
在第一台服务器上(前端服务器nginx)
[root@master ~]# vim /etc/nginx/nginx.conf
............................................................................................................
upstream websrvs {
server 192.168.0.61 weight=1 max_fails=2 fail_timeout=2;
server 192.168.0.62 weight=1 max_fails=2 fail_timeout=2;
}
.............................................................................................................
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 刷新多次是正常的
第二个后端 apache 192.168.0.62
[root@mysql-proxy ~]# service httpd stop # down 掉
停止 httpd: [确定]
[root@mysql-proxy ~]#
http://192.168.0.60/ 刷新,终于为node1 nginx的upstream功能自动判断哪个服务器down了
第二个后端 apache 192.168.0.62
[root@mysql-proxy ~]# service httpd start
正在启动 httpd: [确定]
[root@mysql-proxy ~]#
http://192.168.0.60/ 刷新多次又是正常的了
万一所有后台服务器 down了,前端nginx配置一个sorry server........
在第一台服务器上(前端服务器nginx)
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
server {
listen 8080;
server_name localhost;
root /web/errorpages;
index index.html;
}
................................................................................
[root@master ~]# mkdir -pv /web/errorpages
mkdir: 已创建目录 "/web/errorpages"
[root@master ~]#
[root@master ~]# vim /web/errorpages/index.html
sorry,....
[root@master ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60:8080/ 直接访问,没问题
在第一台服务器上(前端服务器nginx)
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
upstream websrvs {
server 192.168.0.61 weight=1 max_fails=2 fail_timeout=2;
server 192.168.0.62 weight=1 max_fails=2 fail_timeout=2;
server 127.0.0.1:8080 backup; #backup就是定义fall back server (fail back server)的
}
................................................................................
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 现在刷新多次是正常的了,负载均衡也是正常负载的
第一个后端 apache 192.168.0.61 停掉
[root@slave ~]# service httpd stop
停止 httpd: [确定]
[root@slave ~]#
第二个后端 apache 192.168.0.62 停掉
[root@mysql-proxy ~]# service httpd stop
停止 httpd: [确定]
[root@mysql-proxy ~]#
http://192.168.0.60/ 跳到sorry了
第一个后端 apache 192.168.0.61 上线
[root@slave ~]# service httpd start
正在启动 httpd: [确定]
[root@slave ~]#
第二个后端 apache 192.168.0.62 上线
[root@mysql-proxy ~]# service httpd start
正在启动 httpd: [确定]
[root@mysql-proxy ~]#
http://192.168.0.60/ 刷新多次,正常显示了
默认nginx负载均衡是轮询,,但是同一客户端是定向同一个后台(可以称为 real server吧),目的是重用session信息
前端 nginx 192.168.0.60
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
upstream websrvs {
ip_hash; #根据客户端请求的源地址做hash,只要hash相同,此前分发过一次,下次分发到同一个服务器,此时权重基本没有意义了
server 192.168.0.61 weight=1 max_fails=2 fail_timeout=2;
server 192.168.0.62 weight=1 max_fails=2 fail_timeout=2;
server 127.0.0.1:8080 backup;
}
................................................................................
nginx,支持三种负载均衡算法
round-robin #默认的,,,事实上是加权的round-robin(循环),只要给每个server定义了权重,就是round-robin;;如果未定义权重,表示这个服务器不参加负载均衡
ip_hash #根据客户端请求的源地址做hash,只要hash相同,此前分发过一次,下次分发到同一个服务器,此时权重基本没有意义了
least_conn #最少连接,挑最少的负责响应请求
前端 nginx 192.168.0.60
[root@master ~]# service nginx reload #为何报错
nginx: [emerg] invalid parameter "backup" in /etc/nginx/nginx.conf:39
nginx: configuration file /etc/nginx/nginx.conf test failed
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
upstream websrvs {
ip_hash; #为何不能使用 server 127.0.0.1:8080 backup,因为一旦定义到错误的服务器上,永远就到错误的服务器上 ;;;不用backup server 有其它方法来解决?可以条件判断,重定向的,
server 192.168.0.61 weight=1 max_fails=2 fail_timeout=2;
server 192.168.0.62 weight=1 max_fails=2 fail_timeout=2;
#server 127.0.0.1:8080 backup; #先注掉,再说
}
................................................................................
[root@master ~]# service nginx reload #重新加载
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 刷新多次,一直是 node2 了
[root@master ~]# netstat -ant #当前主机所有客户端连接状况,刷新多次可以看到的
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:40244 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
tcp 0 52 192.168.0.60:22 192.168.0.103:1442 ESTABLISHED
tcp 0 0 :::3306 :::* LISTEN
tcp 0 0 :::57643 :::* LISTEN
tcp 0 0 :::111 :::* LISTEN
tcp 0 0 :::22 :::* LISTEN
tcp 0 0 ::1:631 :::* LISTEN
tcp 0 0 ::1:25 :::* LISTEN
tcp 0 0 ::ffff:192.168.0.60:3306 ::ffff:192.168.0.61:34698 TIME_WAIT
[root@master ~]#
[root@master ~]# netstat -ant | grep :80 #看80连接状况
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
[root@master ~]#
[root@master ~]# netstat -ant | grep ":80\>" #看80连接状况 # \>或\b 锚定词尾
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
[root@master ~]#
awk命令 统计各类状态的当前的数目的
awk中引用变量值,不需要加$,比如S[A] ,,,,,但这里 S[$NF] NF是有值的,比如为4, 那么$NF就是$4,表示第4个字段的值
S是数组 $NF是最后一个字段名称,是下标,比如这里为字符串LISTEN
for(A in S) 表示A是S的下标,,比如这里为LISTEN
[root@master ~]# netstat -ant | awk '/:80\>/{S[$NF]++}END{for(A in S) {print A,S[A]}}'
LISTEN 1
[root@master ~]#
评估服务器多少连接时 netstat awk 这个命令很常用
nginx使用缓存,不同的应用缓存不一样?
nginx,
cache: 共享内存: 存储键和缓存对象元数据
磁盘空间: 存储数据 (固态硬盘性能好点,机械硬盘,iops太差了)
用来几块固态盘做上raid0,性能很好的了,??????
proxy_cache_path 这个指令来定义缓存大小,不能定义在server{}上下文中,必须定义在http{}上下文中
levels=levels 缓存目录,子目录级别,存储几级目录, levels=1:2 表示由两个目录,组成,第一级目录是1个字符,第二级目录是2个字符,,,,最多三级,每一级字符最多2个
proxy_cache_path /nginx/cache/first levels=1:2:1 表示三级目录,一级是1个字符,二级是2个字符,三级是1个字符
keys_zone=name:size 没中括号,必须的,,,,,,用来存储键的区域,,, name表示命名的键,区域名称,size表示大小,,,,,我们可以定义多个区域,每个区域要有一个名称来引用,
proxy_cache_path /nginx/cache/first levels=1:2:1 keys_zone=first:20m
缓存目录并非越大越好,越大,数据越多,查找时间越长,管理要花费的更多的系统资源max_size=size定义目录使用多大空间来存储缓存对象的
proxy_cache_path /nginx/cache/first levels=1:2:1 keys_zone=first:20m max_size=1G
存满了,cache_manager进程,根据最近最少使用算法(LRU???),将此前没有用的缓存清除出去,,,如果刚清除出去,又要使用了,这叫未命中,还要重新取了,
缓存太大,管理起来麻烦,,太小了,需要频繁清理,一清理,命中率会降低,,,,,,,,所以要观察测试的
如下图,通过层层子目录,找内容,速度会很快,分层(层层子目录)后缓存对象的命名方式简单,,,如果没有子目录,1千万个对象,每个对象名称不能相同
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_proxy_module.html
语法: | proxy_cache_path |
默认值: | — |
上下文: | http |
设置缓存的路径和其他参数。缓存数据是保存在文件中的,缓存的键和文件名都是在代理URL上执行MD5的结果。 levels
参数定义了缓存的层次结构。比如,下面配置
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
缓存中文件名看起来是这样的:
/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
被缓存的响应首先写入一个临时文件,然后进行重命名。从0.8.9版本开始,临时文件和缓存可以放在不同的文件系统。但请注意,这将导致文件在这两个文件系统中进行拷贝,而不是廉价的重命名操作。因此,针对任何路径,都建议将缓存和proxy_temp_path指令设置的临时文件目录放在同一文件系统。
此外,所有活动的键和缓存数据相关的信息都被存放在共享内存中。共享内存通过keys_zone
参数的name
和size
来定义。被缓存的数据如果在inactive
参数指定的时间内未被访问,就会被从缓存中移除,不论它是否是刚产生的。inactive
的默认值是10分钟。
特殊进程“cache manager”监控缓存的条目数量,如果超过max_size
参数设置的最大值,使用LRU算法移除缓存数据。
nginx新启动后不久,特殊进程“cache loader”就被启动。该进程将文件系统上保存的过去缓存的数据的相关信息重新加载到共享内存。加载过程分多次迭代完成,每次迭代,进程只加载不多于loader_files
参数指定的文件数量(默认值为100)。此外,每次迭代过程的持续时间不能超过loader_threshold
参数的值(默认200毫秒)。每次迭代之间,nginx的暂停时间由loader_sleep
参数指定(默认50毫秒)。
在第一台服务器上(前端服务器nginx)
缓存是在 server 之外定义
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
upstream websrvs {
ip_hash;#大意是根据hash计算,同一个客户端会一直连到同一个web后台服务器
server 192.168.0.61 weight=1 max_fails=2 fail_timeout=2;
server 192.168.0.62 weight=1 max_fails=2 fail_timeout=2;
#server 127.0.0.1:8080 backup;
}
proxy_cache_path /nginx/cache/first levels=1:2 keys_zone first:20m max_size=1g; #定义缓存,,,这只说明我们具有缓存功能了,至于谁哪里使用缓存,得在location中定义,,,,,,,,,,,应该是keys_zone=first:20m
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://websrvs;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache first; #启用缓存功能 值为off 表示不使用缓存,,first表示使用first这个缓存
}
#location / {
# root html;
................................................................................
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_proxy_module.html 可看到许多有关cache相关的指令
proxy_cache_valid 对不同的响应码,定义不同的缓存时间,,,,,,
proxy_cache_valid 200 302 10m; # 200 302 缓存10分钟
proxy_cache_valid 404 1m; # 404 错误页面,缓存1分钟
proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m; #任意其它缓存一分钟
语法: | proxy_cache_valid [ |
默认值: | — |
上下文: | http , server , location |
为不同的响应状态码设置不同的缓存时间。比如,下面指令
proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m;
设置状态码为200和302的响应的缓存时间为10分钟,状态码为404的响应的缓存时间为1分钟。
如果仅仅指定了time
,
proxy_cache_valid 5m;
那么只有状态码为200、300和302的响应会被缓存。
如果使用了any
参数,那么就可以缓存任何响应:
proxy_cache_valid 200 302 10m; proxy_cache_valid 301 1h; proxy_cache_valid any 1m;
缓存参数也可以直接在响应头中设定。这种方式的优先级高于使用这条指令设置缓存时间。 “X-Accel-Expires”响应头可以以秒为单位设置响应的缓存时间,如果值为0,表示禁止缓存响应,如果值以@
开始,表示自1970年1月1日以来的秒数,响应一直会被缓存到这个绝对时间点。 如果不含“X-Accel-Expires”响应头,缓存参数仍可能被“Expires”或者“Cache-Control”响应头设置。 如果响应头含有“Set-Cookie”,响应将不能被缓存。 这些头的处理过程可以使用指令proxy_ignore_headers忽略。
在第一台服务器上(前端服务器nginx)
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
location / {
proxy_pass http://websrvs;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache first;#表示缓存在哪里 key_zone那边定义first
proxy_cache_valid 200 10m; # 200页面缓存10分钟;
}
................................................................................
[root@master ~]# nginx -t
nginx: [emerg] invalid parameter "keys_zone" in /etc/nginx/nginx.conf:41
nginx: configuration file /etc/nginx/nginx.conf test failed
[root@master ~]#
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
proxy_cache_path /nginx/cache/first levels=1:2 keys_zone=first:20m max_size=1g; #在keys_zone后面加等号
................................................................................
[root@master ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: [emerg] mkdir() "/nginx/cache/first" failed (2: No such file or directory)
nginx: configuration file /etc/nginx/nginx.conf test failed
[root@master ~]#
[root@master ~]# mkdir /nginx/cache/first -pv
mkdir: 已创建目录 "/nginx"
mkdir: 已创建目录 "/nginx/cache"
mkdir: 已创建目录 "/nginx/cache/first"
[root@master ~]#
[root@master ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master ~]#
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
在第一台服务器上(前端服务器nginx)
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
upstream websrvs {
# ip_hash; # 去掉它看看
server 192.168.0.61 weight=1 max_fails=2 fail_timeout=2;
server 192.168.0.62 weight=1 max_fails=2 fail_timeout=2;
#server 127.0.0.1:8080 backup;
}
................................................................................
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 刷新多次还是如下的图,是缓存的作用,,,,这是服务器端缓存,,,, 缓存命中了,不会找原始服务器了
下图中
Pragma: no-cache 表示没有使用浏览器缓存
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
add_header X-Via $server_addr; #增加这一行 首部,表示看看谁来响应的 X表示 Xcache Via表示经由的意思
................................................................................
[root@master ~]# nginx -t #没问题
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master ~]#
[root@master ~]# service nginx reload #重载
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 看到了 X-Via ,此时仍然不知道缓存有没有命中,
指令表示可以在配置文件中配置参数,变量表示可以通过它来引用某些值
https://www.nginx.cn/doc/standard/httpupstream.html
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_memcached_module.html
我这边看不到下面的截图,,马哥那边看到的
http://tengine.taobao.org/nginx_docs/en/docs/http/ngx_http_upstream_module.html 英文版也看到
$upstream_cache_status 加到首部,可以告诉客户端到底命中与否
MISS 未命中
EXPIRED 过期
UPDATING 更新
STALE 失效
HIT 命中
在第一台服务器上(前端服务器nginx) 192.168.0.60
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status; #加上这行,看是否命中
................................................................................
[root@master ~]# nginx -t #没问题
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master ~]#
[root@master ~]# service nginx reload #重载
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 由下图,缓存命中
在第一台服务器上(前端服务器nginx) 192.168.0.60
[root@master ~]# service nginx stop
停止 nginx: [确定]
[root@master ~]# rm -rf /nginx/cache/first/2/b3/bc9c9eed354a58d3c2bde97d0a7d7b32 #删缓, 现在应该命中不了了
[root@master ~]# service nginx start
正在启动 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 刷新,由下图,命中不了
http://192.168.0.60/ 刷新,由下图,又命中了
在第一台服务器上(前端服务器nginx) 192.168.0.60
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
#add_header X-Via $server_addr; 注掉它
add_header X-Cache "$upstream_cache_status from $server_addr"; #改成它
................................................................................
[root@master ~]# service nginx reload #重新载入
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/ 强制刷新,由下图
nginx还可以为了快速存储日志,打开缓存能力的(对于日志来讲,它是缓冲区),,,,,,,为fastcgi打开缓存功能(马哥不演示,找fastcgi模块,有类似的指令,定义缓存空间,让fastcgi进行cache的时候,指向那个缓存空间)
缓存分级,浏览器自己提供的是私有缓存,nginx提供的是公共缓存,所以浏览器生效
除了 proxy_cache_path
另外常用的三种缓存
open_log_cache 打开日志文件的缓存,可以将写出的日志信息先保存至内存,而后同步到磁盘,可以降低磁盘IO,
open_file_cache 打开文件缓存,nginx将文件(尤其是元数据)在内存中打开,可以加速响应过程
fastcgi_cache 必须要慎用, nginx缓存php运行的结果,,,如果php逻辑改了,仍然可能从缓存中返回
而nginx的limit限制也基于共享内存实现。明确说明在共享内存里最多允许打开多少个连接,维持着每个用户的会话监控,每个用户最多使用多快的速度来实现文件获取,马哥不细讲了
假设流量大,但带宽有限,打开压缩功能,可节约带宽,它也能够在连接开始发送的那一刻,将发送数据到客户端的速度的时间缩短
nginx: gzip 编译时默认自带,如果需要的话,可以打开gzip的功能,并指定压缩级别等
https://www.nginx.cn/doc/standard/httpgzip.html
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_gzip_module.html
gzip 通过压缩的格式向客户端响应,
gzip 指令
gzip on #开启压缩 并非所有情况下需要压缩,缓存时压缩副作用大(第一个用户压缩,第二个用户请求同样的内容,压缩的内容和请求的内容可能不一致??????使得缓存命中率降低,)
gzip_proxied #定义哪些情况下压缩,哪些情况下不压缩, 实现压缩策略的
gzip_comp_level #压缩比
gzip_buffers #压缩时使用的缓冲区
This translation may be out of date. Check the English version for recent changes.
Example Configuration Directives gzip gzip_buffers gzip_comp_level gzip_disable gzip_min_length gzip_http_version gzip_proxied gzip_types gzip_vary |
The ngx_http_gzip_module
module is a filter that compresses responses using the “gzip” method. This often allows to reduce the size of transmitted data by half or even more.
gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain application/xml;
The $gzip_ratio
variable can be used to log the achieved compression ratio.
syntax: | gzip |
default: | gzip off; |
context: | http , server , location , if in location |
Enables or disables gzipping of responses.
syntax: | gzip_buffers |
default: | gzip_buffers 32 4k|16 8k; |
context: | http , server , location |
Sets the number
and size
of buffers used to compress a response. By default, the buffer size is equal to one memory page. This is either 4K or 8K, depending on a platform.
Until version 0.7.28, four 4K or 8K buffers were used by default.
语法: gzip_buffers number size
默认值: gzip_buffers 4 4k/8k
作用域: http, server, location
设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。 例如 4 4k 代表以4k为单位,按照原始数据大小以4k为单位的4倍申请内存。 4 8k 代表以8k为单位,按照原始数据大小以8k为单位的4倍申请内存。
如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。
syntax: | gzip_comp_level |
default: | gzip_comp_level 1; |
context: | http , server , location |
Sets a gzip compression level
of a response. Acceptable values are in the 1..9 range.
syntax: | gzip_disable |
default: | — |
context: | http , server , location |
This directive appeared in version 0.6.23.
Disables gzipping of responses for requests with “User-Agent” header fields matching any of the specified regular expressions.
The special mask “msie6
” (0.7.12) corresponds to the regular expression “MSIE [4-6]\.
” but works faster. Starting from version 0.8.11, “MSIE 6.0; ... SV1
” is excluded from this mask.
syntax: | gzip_min_length |
default: | gzip_min_length 20; |
context: | http , server , location |
Sets the minimum length of a response that will be gzipped. The length is determined only from the “Content-Length” response header field.
syntax: | gzip_http_version |
default: | gzip_http_version 1.1; |
context: | http , server , location |
Sets the minimum HTTP version of a request required to compress a response.
syntax: | gzip_proxied |
default: | gzip_proxied off; |
context: | http , server , location |
Enables or disables gzipping of responses for proxied requests depending on the request and response. The fact that the response is proxied is determined based on the presence of the “Via” request header field. A directive accepts multiple parameters:
off
disables compression for all proxied requests, ignoring other parameters;
expired
enables compression if a response header includes the field “Expires” with a value that disables caching;
no-cache
enables compression if a response header includes the field “Cache-Control” with the parameter “no-cache
”;
no-store
enables compression if a response header includes the field “Cache-Control” with the parameter “no-store
”;
private
enables compression if a response header includes the field “Cache-Control” with the parameter “private
”;
no_last_modified
enables compression if a response header does not include the field “Last-Modified”;
no_etag
enables compression if a response header does not include the field “ETag”;
auth
enables compression if a request header includes the field “Authorization”;
any
enables compression for all proxied requests.
syntax: | gzip_types |
default: | gzip_types text/html; |
context: | http , server , location |
Enables gzipping of responses for the specified MIME types in addition to “text/html
”. The special value “*
” matches any MIME type (0.8.29). Responses with the type “text/html
” are always compressed.
syntax: | gzip_vary |
default: | gzip_vary off; |
context: | http , server , location |
Enables or disables emitting the “Vary: Accept-Encoding” response header field if the directives gzip or gzip_static are active.
在第一台服务器上(前端服务器nginx) 192.168.0.60
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
# gzip on; #启用压缩,去掉前面的井号注释
................................................................................
[root@master ~]#
如下图,好几台动态服务器,好几台静态服务器(比如提供图片),好几台上传的服务器,,,,,,,,,,,,,
怎样让应用,请求准确的定向到特定的服务器,怎么实现负载均衡
分成几组,,,,,,,,,
fastcgi代理的时候,可以使用upstream组, 实现负载均衡效果的
同样可以定义图片服务器组
upstream phpsrvs {
server
server
}
upstream imgsrvs {
server
server
}
upstream staticfilesrvs { #静态文件服务器组
server
server
}
location / { #其它的请求,定位到这里本地吧 可以把这里定向到 staticfilesrvs
root /web/htdocs;
index index.php index.html
}
location ~* \.php${ #请求php时,定位到php服务组
fastcgi_pass http://phpsrvs; #这里是fastcgi_pass
}
location ~* \.(jpg|jpeg|gif|png)${ #请求图片时,定位到图片服务组
proxy_pass http://imgsrvs; #这里是proxy_pass
}
rewrite: URL重写模块
if指令:只有满足条件时,才作相应的处理
if (condition) {
}
if 通常用在location(最常见用在其中,建议用在其中,通常是为url重写而设定if的),server当中
测试:
双目测试:
是不是等于某个字符串,符合某个正则等
~ 匹配为真
!~ 取反,不匹配为真
= 等于为真
!= 不等于为真
~* 不区分字符大小写,匹配为真
!~* 不区分字符大小写,不匹配为真
if ($request_method="POST") { #请求方法为POST
}
if ($request_uri ~* "/forum") { #请求的路径当中包含 /forum这个字符串
}
单目测试:
某文件是否存在,某文件是否可执行
location /images/ {
rewrite httpd://172.168.100.19/images/
}
https://www.nginx.cn/doc/standard/httprewrite.html
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_rewrite_module.html#rewrite
语法: | rewrite |
默认值: | — |
上下文: | server , location , if |
如果指定的正则表达式能匹配URI,此URI将被replacement
参数定义的字符串改写。rewrite
指令按其在配置文件中出现的顺序执行。flag可以终止后续指令的执行。如果replacement的字符串以“http://
”或“https://
”开头,nginx将结束执行过程,并返回给客户端一个重定向。
可选的flag
参数可以是其中之一:
last
停止执行当前这一轮的ngx_http_rewrite_module
指令集,然后查找匹配改变后URI的新location;
break
停止执行当前这一轮的ngx_http_rewrite_module
指令集;
redirect
在replacement字符串未以“http://
”或“https://
”开头时,使用返回状态码为302的临时重定向;
permanent
返回状态码为301的永久重定向。
完整的重定向URL将按照请求协议($scheme
)、server_name_in_redirect指令和port_in_redirect指令的配置进行补全。
举例:
server { ... rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last; return 403; ... }
但是当上述指令写在“/download/
”的location中时,应使用标志break
代替last
,否则nginx会重复10轮循环,然后返回错误500:
location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break; return 403; }
如果replacement
字符串包括新的请求参数,以往的请求参数会添加到新参数后面。如果不希望这样,在replacement字符串末尾加一个问号“?”,就可以避免,比如:
rewrite ^/users/(.*)$ /show?user=$1? last;
如果正则表达式中包含字符“}
”或者“;
”,整个表达式应该被包含在单引号或双引号的引用中。
语法: | rewrite_log |
默认值: | rewrite_log off; |
上下文: | http , server , location , if |
开启或者关闭将ngx_http_rewrite_module
模块指令的处理日志以notice
级别记录到错误日志中。
Nginx中文文档 | 目录首页 |
Nginx中文站 › 文档首页 › HttpRewrite模块 |
This module makes it possible to change URI using regular expressions, and to redirect and select configuration depending on variables.
该模块允许使用正则表达式改变URI,并且根据变量来转向以及选择配置。
If the directives of this module are given at the server level, then they are carried out before the location of the request is determined. If in that selected location there are further rewrite directives, then they also are carried out. If the URI changed as a result of the execution of directives inside location, then location is again determined for the new URI.
如果在server级别设置该选项,那么他们将在location之前生效。如果在location还有更进一步的重写规则,location部分的规则依然会被执行。如果这个URI重写是因为location部分的规则造成的,那么location部分会再次被执行作为新的URI。
This cycle can be repeated up to 10 times, after which Nginx returns a 500 error.
这个循环会执行10次,然后Nginx会返回一个500错误。
[#break break]
[#if if]
[#return return]
[#rewrite rewrite]
[#set set]
[#uninitialized_variable_warn uninitialized_variable_warn]
语法: break
默认值: none
作用域: server, location, if
Completes the current set of rules. 作用是完成当前的规则列
示例:
if ($slow) { #假如很慢, limit_rate 10k; #10k组 , break; #退出,不再判断了,避免循环 }
语法: if (condition) { ... }
默认: none
作用域: server, location
Checks the truth of a condition. If the condition evaluates to true, then the code indicated in the curly braces is carried out and the request is processed in accordance with the configuration within the following block. Configuration inside directive if is inherited from the previous level.
They can be assigned as the condition:
the name of variable; false values are: empty string "", or any string starting with "0";
the comparison of variable with the line with using the=
and!=
operators;
pattern matching with regular expressions using the symbols~*
and~
:
~
is case-sensitive match;
'~'符合,但是大小写敏感
~*
specifies a case-insensitive match (firefox matches FireFox)
~*大小写不敏感的符合(firefox符合FireFox)
!~ and !~*
mean the opposite, "doesn't match"
!~和!~*代表相反,“不符合”
checking for the existence of a file using the-f and !-f
operators;使用-f以及!-f检测一个文件是否存在
checking existence of a directory using the-d and !-d
operators;使用-d以及!-d检测一个目录是否存在
checking existence of a file, directory or symbolic link using the-e and !-e
operators;使用-e以及!-e检测是否存在一个文件,一个目录或者一个符号链接。
checking whether a file is executable using the-x and !-x
operators.使用-x以及!-x检测一个文件是否可执行
Parts of the regular expressions can be in parentheses, whose value can then later be accessed in the$1 to >$9
variables.
Examples of use:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; } if ($http_cookie ~* "id=([^;] +)(?:;|$)" ) { set $id $1; } if ($request_method = POST ) { return 405; } if (!-f $request_filename) { break; proxy_pass http://127.0.0.1; } if ($slow) { limit_rate 10k; } if ($invalid_referer) { return 403; }
The value of the built-in variable$invalid_referer
is given by the directive valid_referers.
语法: return code
默认值: none
作用域: server, location, if #用在这几个上下文中
This directive concludes execution of the rules and returns the status code indicated to client. It is possible to use the following values: 204, 400, 402-406, 408, 410, 411, 413, 416 and 500-504. Furthermore, nonstandard code 444 closes the connection without sending any headers.
这个指令根据规则的执行情况,返回一个状态值给客户端。可使用值包括:204,400,402-406,408,410,411,413,416以及500-504。也可以发送非标准的444代码-未发送任何头信息下结束连接。
语法: rewrite regex replacement flag
默认: none
作用域: server, location, if
This directive changes URI in accordance with the regular expression and the replacement string. Directives are carried out in order of appearance in the configuration file.
这个指令根据表达式来更改URI,或者修改字符串。指令根据配置文件中的顺序来执行。
Be aware that the rewrite regex only matches the relative path instead of the absolute URL. If you want to match the hostname, you should use an if condition, like so:
注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句,如下:
if ($host ~* www\.(.*)) { set $host_without_www $1; rewrite ^(.*)$ http://$host_without_www$1 permanent; # $1 contains '/foo', not 'www.mydomain.com/foo' }
Flags make it possible to end the execution of rewrite directives.
If the replacement string begins withhttp://
then the client will be redirected, and any further rewrite directives are terminated.
Flags can be any of the following:
last - completes processing of rewrite directives, after which searches for corresponding URI and location
break - completes processing of rewrite directives
redirect - returns temporary redirect with code 302; it is used if the substituting line begins withhttp://
permanent - returns permanent redirect with code 301
Note that if an redirect is relative (has no host part), then when redirecting Nginx uses the "Host" header if the header match name of server_name directive or the first name ofserver_name
directive, if the header does not match or is absent. If noserver_name
is set, then the local hostname is used. If you want Nginx to always use the "Host" header, you can use a wildcard "*"server_name
(but see the restrictions on doing so).Example:
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last; return 403;
But if we place these directives in location /download/, then it is necessary to replace flag "last" by "break", otherwise nginx will hit the 10 cycle limit and return error 500:
location /download/ { : rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; : rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break; : return 403; }
If in the line of replacement arguments are indicated, then the rest of the request arguments are appended to them. To avoid having them appended, place a question mark as the last character:
: rewrite ^/users/(.*)$ /show?user=$1? last; #user加后面的任意内容 进行替换
注: 对花括号( { 和 } )来说, 他们既能用在重定向的正则表达式里,也是用在配置文件里分割代码块, 为了避免冲突, 正则表达式里带花括号的话,应该用双引号(或者单引号)包围。比如,要将类似以下的url
/photos/123456
重定向到:
/path/to/photos/12/1234/123456.png
可以用以下方法 (注意双引号):
rewrite "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/$1/$1$2/$1$2$3.png;
syntax: set variable value
default: none
context: server, location, if
Directive establishes value for the variable indicated. As the value it is possible to use a text, variables and their combination.
syntax: uninitialized_variable_warn on|off
default: uninitialized_variable_warn on
context: http, server, location, if
Enables or disables logging of warnings about noninitialized variables.
Internally, the rewrite directives are compiled at the time the configuration file is loaded into internal codes, usable during the request by the interpreter.
This interpreter is a simple stack virtual machine. For example, the directive:
location /download/ { : if ($forbidden) { : return 403; : } : if ($slow) { : limit_rate 10k; : } : rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break; }
will be compiled into this sequence:
: variable $forbidden : checking to zero : recovery 403 : completion of entire code : variable $slow : checking to zero : checkings of regular expression : copying "/" : copying $1 : copying "/mp3/" : copying $2 : copying "..mpe" : completion of regular expression : completion of entire sequence
Note that there is no code for directive limit_rate, since it does not refer to module ngx_http_rewrite_module. The "if" block exists in the same part of the configuration as the "location" directive.
If $slow is true, then what's inside the "if" block is evaluated, and in this configuration limit_rate it is equal to 10k.
Directive:
: rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;
It is possible to reduce the sequence, if in the regular expression we include the first slash inside the parentheses:
: rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
then the sequence will appear like this:
: checking regular expression : copying $1 : copying "/mp3/" : copying $2 : copying "..mpe" : completion of regular expression : completion of entire code
referer: 上一个网页,跳转从哪里过来的,,,
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_referer_module.html
https://www.nginx.cn/doc/standard/httpreferer.html
ngx_http_referer_module模块 | english русский 简体中文 עברית 日本語 türkçe 新闻 [en] nginx 介绍 下载 [en] 安全漏洞 [en] 文档 FAQ 外部连接 [en] 书籍 [en] 支持 [en] 捐献 [en] trac wiki nginx.com | ||||||||||||||||||
配置实例valid_referers none blocked server_names *.example.com example.* www.example.org/galleries/ ~\.google\.; if ($invalid_referer) { return 403; } 指令
这个指令出现在版本 1.0.5. 设置用来存储有效referer的哈希桶的大小。 详细的情况参见哈希表设置。
这个指令出现在版本 1.0.5. 设置用来存储有效referer的哈希表最大
“Referer”请求头为指定值时,内嵌变量 该指令的参数可以为下面的内容:
实例: valid_referers none blocked server_names *.example.com example.* www.example.org/galleries/ ~\.google\.; |
valid_referers 明确定义谁是合法的referers,来自于哪些地方的引用是合法的引用,
none 没有任何地方引用,浏览器直接输入
blocked 类似于启用防火墙法则,只要不符合给定条件的,就是不合法的 例 ( valid_referers none blocked www.mydomain.com mydomain.com;blocked后面,,,只是不是www.mydomain.com mydomain.com. 就不合法 )
location /photos/ {
valid_referers none blocked www.mydomain.com mydomain.com;
if ($invalid_referer) { #不能够被 valid_referers 指定的匹配到的
return 403; # 表示禁止吧,,这样能够防止盗链了吧,,,,也可以做到别人盗链时,跳到我们自己的主页(使用rewrite?)或者此图片仅限于某某某网站使用
}
}
This module makes it possible to block access to the site with the incorrect values of line "Referer" in the request header.
Keep in mind that it is easy to spoof this header; therefore, the purpose of using of this module consists not in 100% blocking of these requests, but in the blocking of the mass flow of requests, made from typical browsers. Also, consider that the typical browser does not always provide a "Referer" header, even for correct requests.
Example
location /photos/ { valid_referers none blocked www.mydomain.com mydomain.com; if ($invalid_referer) { return 403; } }
syntax: valid_referers [none|blocked|server_names] ...
default: none
context: server, location
This directive assigns a value of 0 or 1 to the variable$invalid_referer
based on the contents of thereferer
header.
You can use this to help reduce deep-linking from outside sites. IfReferer
header is not accounted for in the list ofvalid_referers
, then$invalid_referer
will be set to 1 (see example above).
The parameters can be as follows:
none
means the absence of "Referer" header.
blocked
means maskedReferer
header by firewall, for example, "Referer: XXXXXXX".
server_names is a list of one or more servers. From version 0.5.33 onwards, * wildcards can be used in the server names.
location /images/ { #所以它完成把一个url替换成另外一个url
rewrite http://172.16.100.19/images/
}
rewrite 支持正则表达式: 把 location 后面的正则表达式 移到 rewrite后面?
location / {
root html;
index index.html;
rewrite "^/bbs/(.*)" http://172.16.100.19/forum/$1; #访问这一个内容,跳到 172.16.100.19下面 $1(前一个里面的括号内的内容)
}
[root@master ~]# mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.proxy #备份一下
[root@master ~]# cp /etc/nginx/nginx.conf.bak /etc/nginx/nginx.conf #使用最简单原始的
[root@master ~]#
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................................................................................................
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
rewrite ^/bbs/(.*)$ http://192.168.0.61/forum/$1; #加上这行,,写rewrite很容易造成循环引用,这就是这里192.168.0.61后面没有跟bbs的原因
}
................................................................................................................................................................
[root@master ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master ~]#
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
302临时重定向 301是永久重定向
跨服务器重定向的通常(记住是通常)是临时重定向
在自己主机内部重定向通常(记住是通常)是永久重定向
http://192.168.0.60/bbs/ 302临时重定向 301是永久重定向
在第一台服务器上(前端服务器nginx) 192.168.0.60
[root@master ~]# ls /usr/html
50x.html forum index.html
[root@master ~]#
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
location / {
root html;
index index.html index.htm;
rewrite ^/bbs/(.*)$ /forum/$1;#这里改下
}
................................................................................
[root@master ~]# nginx -t #检查
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master ~]#
[root@master ~]# service nginx reload #重载
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
http://192.168.0.60/bbs/ 重定向了 隐式重定向 网址没有变成 http://192.168.0.60/forum
就连状态码都是 200
https://www.nginx.cn/doc/standard/httprewrite.html
http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_rewrite_module.html
语法: | rewrite |
默认值: | — |
上下文: | server , location , if |
如果指定的正则表达式能匹配URI,此URI将被replacement
参数定义的字符串改写。rewrite
指令按其在配置文件中出现的顺序执行。flag可以终止后续指令的执行。如果replacement的字符串以“http://
”或“https://
”开头,nginx将结束执行过程,并返回给客户端一个重定向。
可选的flag
参数可以是其中之一:
last
停止执行当前这一轮的ngx_http_rewrite_module
指令集,然后查找匹配改变后URI的新location;
break
停止执行当前这一轮的ngx_http_rewrite_module
指令集;
redirect
在replacement字符串未以“http://
”或“https://
”开头时,使用返回状态码为302的临时重定向;
permanent
返回状态码为301的永久重定向。
完整的重定向URL将按照请求协议($scheme
)、server_name_in_redirect指令和port_in_redirect指令的配置进行补全。
举例:
server { ... rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last; return 403; ... }
但是当上述指令写在“/download/
”的location中时,应使用标志break
代替last
,否则nginx会重复10轮循环,然后返回错误500:
location /download/ { rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break; return 403; }
如果replacement
字符串包括新的请求参数,以往的请求参数会添加到新参数后面。如果不希望这样,在replacement字符串末尾加一个问号“?”,就可以避免,比如:
rewrite ^/users/(.*)$ /show?user=$1? last;
如果正则表达式中包含字符“}
”或者“;
”,整个表达式应该被包含在单引号或双引号的引用中。
语法: | rewrite_log |
默认值: | rewrite_log off; |
上下文: | http , server , location , if |
开启或者关闭将ngx_http_rewrite_module
模块指令的处理日志以notice
级别记录到错误日志中。
Nginx中文文档 | 目录首页 |
Nginx中文站 › 文档首页 › HttpRewrite模块 |
This module makes it possible to change URI using regular expressions, and to redirect and select configuration depending on variables.
该模块允许使用正则表达式改变URI,并且根据变量来转向以及选择配置。
If the directives of this module are given at the server level, then they are carried out before the location of the request is determined. If in that selected location there are further rewrite directives, then they also are carried out. If the URI changed as a result of the execution of directives inside location, then location is again determined for the new URI.
如果在server级别设置该选项,那么他们将在location之前生效。如果在location还有更进一步的重写规则,location部分的规则依然会被执行。如果这个URI重写是因为location部分的规则造成的,那么location部分会再次被执行作为新的URI。
This cycle can be repeated up to 10 times, after which Nginx returns a 500 error.
这个循环会执行10次,然后Nginx会返回一个500错误。
[#break break]
[#if if]
[#return return]
[#rewrite rewrite]
[#set set]
[#uninitialized_variable_warn uninitialized_variable_warn]
语法: break
默认值: none
作用域: server, location, if
Completes the current set of rules. 作用是完成当前的规则列
示例:
if ($slow) { : limit_rate 10k; : break; }
语法: if (condition) { ... }
默认: none
作用域: server, location
Checks the truth of a condition. If the condition evaluates to true, then the code indicated in the curly braces is carried out and the request is processed in accordance with the configuration within the following block. Configuration inside directive if is inherited from the previous level.
They can be assigned as the condition:
the name of variable; false values are: empty string "", or any string starting with "0";
the comparison of variable with the line with using the=
and!=
operators;
pattern matching with regular expressions using the symbols~*
and~
:
~
is case-sensitive match;
'~'符合,但是大小写敏感
~*
specifies a case-insensitive match (firefox matches FireFox)
~*大小写不敏感的符合(firefox符合FireFox)
!~ and !~*
mean the opposite, "doesn't match"
!~和!~*代表相反,“不符合”
checking for the existence of a file using the-f and !-f
operators;使用-f以及!-f检测一个文件是否存在
checking existence of a directory using the-d and !-d
operators;使用-d以及!-d检测一个目录是否存在
checking existence of a file, directory or symbolic link using the-e and !-e
operators;使用-e以及!-e检测是否存在一个文件,一个目录或者一个符号链接。
checking whether a file is executable using the-x and !-x
operators.使用-x以及!-x检测一个文件是否可执行
Parts of the regular expressions can be in parentheses, whose value can then later be accessed in the$1 to >$9
variables.
Examples of use:
if ($http_user_agent ~ MSIE) { : rewrite ^(.*)$ /msie/$1 break; } if ($http_cookie ~* "id=([^;] +)(?:;|$)" ) { : set $id $1; } if ($request_method = POST ) { : return 405; } if (!-f $request_filename) { : break; : proxy_pass http://127.0.0.1; } if ($slow) { : limit_rate 10k; } if ($invalid_referer) { : return 403; }
The value of the built-in variable$invalid_referer
is given by the directive valid_referers.
语法: return code
默认值: none
作用域: server, location, if
This directive concludes execution of the rules and returns the status code indicated to client. It is possible to use the following values: 204, 400, 402-406, 408, 410, 411, 413, 416 and 500-504. Furthermore, nonstandard code 444 closes the connection without sending any headers.
这个指令根据规则的执行情况,返回一个状态值给客户端。可使用值包括:204,400,402-406,408,410,411,413,416以及500-504。也可以发送非标准的444代码-未发送任何头信息下结束连接。
语法: rewrite regex replacement flag # rewrite 正则 要替换的值 标识
默认: none
作用域: server, location, if
This directive changes URI in accordance with the regular expression and the replacement string. Directives are carried out in order of appearance in the configuration file.
这个指令根据表达式来更改URI,或者修改字符串。指令根据配置文件中的顺序来执行。
Be aware that the rewrite regex only matches the relative path instead of the absolute URL. If you want to match the hostname, you should use an if condition, like so:
注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句,如下:
if ($host ~* www\.(.*)) { : set $host_without_www $1; : rewrite ^(.*)$ http://$host_without_www$1 permanent; # $1 contains '/foo', not 'www.mydomain.com/foo' }
Flags make it possible to end the execution of rewrite directives.
If the replacement string begins withhttp://
then the client will be redirected, and any further rewrite directives are terminated.
Flags can be any of the following: 四种标识
last - completes processing of rewrite directives, after which searches for corresponding URI and location
break - completes processing of rewrite directives
redirect - returns temporary redirect with code 302; it is used if the substituting line begins with #http://
permanent - returns permanent redirect with code 301 永久重定向
Note that if an redirect is relative (has no host part), then when redirecting Nginx uses the "Host" header if the header match name of server_name directive or the first name ofserver_name
directive, if the header does not match or is absent. If noserver_name
is set, then the local hostname is used. If you want Nginx to always use the "Host" header, you can use a wildcard "*"server_name
(but see the restrictions on doing so).Example:
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last; rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last; return 403;
But if we place these directives in location /download/, then it is necessary to replace flag "last" by "break", otherwise nginx will hit the 10 cycle limit and return error 500:
location /download/ { : rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break; : rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break; : return 403; }
If in the line of replacement arguments are indicated, then the rest of the request arguments are appended to them. To avoid having them appended, place a question mark as the last character:
: rewrite ^/users/(.*)$ /show?user=$1? last;
注: 对花括号( { 和 } )来说, 他们既能用在重定向的正则表达式里,也是用在配置文件里分割代码块, 为了避免冲突, 正则表达式里带花括号的话,应该用双引号(或者单引号)包围。比如,要将类似以下的url
/photos/123456
重定向到:
/path/to/photos/12/1234/123456.png
可以用以下方法 (注意双引号):
rewrite "/photos/([0-9] {2})([0-9] {2})([0-9] {2})" /path/to/photos/$1/$1$2/$1$2$3.png;
syntax: set variable value
default: none
context: server, location, if
Directive establishes value for the variable indicated. As the value it is possible to use a text, variables and their combination.
syntax: uninitialized_variable_warn on|off
default: uninitialized_variable_warn on
context: http, server, location, if
Enables or disables logging of warnings about noninitialized variables.
Internally, the rewrite directives are compiled at the time the configuration file is loaded into internal codes, usable during the request by the interpreter.
This interpreter is a simple stack virtual machine. For example, the directive:
location /download/ { : if ($forbidden) { : return 403; : } : if ($slow) { : limit_rate 10k; : } : rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break; }
will be compiled into this sequence:
: variable $forbidden : checking to zero : recovery 403 : completion of entire code : variable $slow : checking to zero : checkings of regular expression : copying "/" : copying $1 : copying "/mp3/" : copying $2 : copying "..mpe" : completion of regular expression : completion of entire sequence
Note that there is no code for directive limit_rate, since it does not refer to module ngx_http_rewrite_module. The "if" block exists in the same part of the configuration as the "location" directive.
If $slow is true, then what's inside the "if" block is evaluated, and in this configuration limit_rate it is equal to 10k.
Directive:
: rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;
It is possible to reduce the sequence, if in the regular expression we include the first slash inside the parentheses:
: rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
then the sequence will appear like this:
: checking regular expression : copying $1 : copying "/mp3/" : copying $2 : copying "..mpe" : completion of regular expression : completion of entire code
rewrite regex replacement flag # rewrite 正则 要替换的值 标识
标识四种
last:本次重写完成之后,重启下一轮检查,,,,,一般用它
http://www.magedu.com/bbs/index.html --> http://www.magedu.com/forum/index.html
下面 当重定向到 http://www.magedu.com/forum/$1 后,还得进这个location进行检查
location / {
root html;
index index.html;
rewrite "^/bbs/(.*)" http://www.magedu.com/forum/$1 last;
}
http://www.magedu.com/bbs/a/images/b.jpg --> http://www.magedu.com/bbs/b/images/a.jpg --> http://www.magedu.com/bbs/a/images/b.jpg
下面这个规则就会发生死循环 (来回10次???就会停止了)
location / {
root html;
index index.html;
rewrite "^/bbs/(.*)/images/(.*)\.jpg$" http://www.magedu.com/bbs/$2/images/$1.jpg last;
}
break:本次重写完成之后,中止了,不再进行下一轮检查;;直接进行后续操作了,,,,,有可能死循环时,用break(在某个非根(这就是 location / 根)location中使用的时候,??????尤其要注意,要使用break)
redirect: 显式说明临时重定向
permanent: 显式说明永久重定向
如下图,分发器,web服务器,,,,上传时采用rsync+inotify,sersync,,,,,,但是它一定是某一个服务器写,其它服务器同步的,,但是客户端不一定访问的是哪个web服务器,,,因为只能从主同步到从,,,,,所以要读写分离,,写到主,读到从,,,,,或者写是主,读无所谓主从哪个服务器,,,,,,
演示一下put方法的实现效果,,,,,,,,put基于webDAV的技术,
WebDAV (Web-based Distributed Authoring and Versioning) 一种基于 HTTP 1.1协议的通信协议。它扩展了HTTP 1.1,在GET、POST、HEAD等几个HTTP标准方法以外添加了一些新的方法,使应用程序可直接对Web Server直接读写,并支持写文件锁定(Locking)及解锁(Unlock),还可以支持文件的版本控制。WebDAV 类似于基于上传功能的ftp服务器功能.,,,,在web服务器上上传下载,删除文件等功能,,,,,,增加了PUT DELETE方法,尤其这两种方法,
团队开发时很可能用到WebDAV,,,默认apache支持 WebDAV,只不过未开启
第二个后端 apache 192.168.0.62
[root@mysql-proxy ~]# vim /etc/httpd/conf/httpd.conf #只要这两个模块启用,服务器就允许上传操作
................................................................................
LoadModule dav_module modules/mod_dav.so #这个模块
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule info_module modules/mod_info.so #这个模块
LoadModule dav_fs_module modules/mod_dav_fs.so
................................................................................
DocumentRoot "/var/www/html"
Dav on #加上这个,即可启用 Dav on 写在这里其实是错了,
................................................................................
[root@mysql-proxy ~]# service httpd restart
停止 httpd: [确定]
正在启动 httpd:Syntax error on line 293 of /etc/httpd/conf/httpd.conf:
DAV not allowed here
[失败]
[root@mysql-proxy ~]#
[root@mysql-proxy ~]# getenforce #selinux未启用
Permissive
[root@mysql-proxy ~]#
[root@mysql-proxy ~]# vim /etc/httpd/conf/httpd.conf
................................................................................
<Directory "/var/www/html">
Dav on # 刚刚Dav on位置错了,,删掉刚刚的Dav on
................................................................................
[root@mysql-proxy ~]# service httpd restart
停止 httpd: [确定]
正在启动 httpd: [确定]
[root@mysql-proxy ~]#
在随便另一台电脑(linux)上 192.168.0.61
[root@slave ~]# curl http://192.168.0.62
<h1>node2.magedu.com</h1>
[root@slave ~]#
在随便另一台电脑(linux)上 192.168.0.61
[root@slave ~]# curl -T /etc/issue http://192.168.0.62 # -T (transfer) 指明上传的文件
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /issue #没有权限
on this server.</p>
<hr>
<address>Apache/2.2.15 (Red Hat) Server at 192.168.0.62 Port 80</address>
</body></html>
[root@slave ~]#
第二个后端 apache 192.168.0.62
[root@mysql-proxy ~]# ls -la /var/www/html/ #权限是root用户 root组
总用量 12
drwxr-xr-x. 2 root root 4096 4月 30 10:19 .
drwxr-xr-x. 6 root root 4096 4月 30 10:12 ..
-rw-r--r--. 1 root root 26 4月 30 10:19 index.html
[root@mysql-proxy ~]#
[root@mysql-proxy ~]# setfacl -m u:apache:rwx /var/www/html/ #设权限
[root@mysql-proxy ~]#
在随便另一台电脑(linux)上 192.168.0.61
[root@slave ~]# curl -T /etc/issue http://192.168.0.62 #-T (transfer) 指明上传的文件 成功了 这里-T是put上传?只有put才能上传文件
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>201 Created</title>
</head><body>
<h1>Created</h1>
<p>Resource /issue has been created.</p>
<hr />
<address>Apache/2.2.15 (Red Hat) Server at 192.168.0.62 Port 80</address>
</body></html>
[root@slave ~]#
[root@slave ~]#
http://192.168.0.62/issue #看到上传成功了
我们想第一个后端 apache 192.168.0.61,,,,,,,,,,,,,第二个后端 apache 192.168.0.62 负载均衡,,,,,,,写(上传)只到第二个后端 apache 192.168.0.62,,,,可以任意读
在第一台服务器上(前端服务器nginx) 192.168.0.60
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
#location / { #注掉这个
# root html;
# index index.html index.htm;
# rewrite ^/bbs/(.*)$ /forum/$1;
#}
location / {
proxy_pass http://192.168.0.61/;
if($request_method="PUT"){
proxy_pass http://192.168.0.62/;
}
}
................................................................................
[root@master ~]# nginx -t
nginx: [emerg] unknown directive "if($request_method="PUT")" in /etc/nginx/nginx.conf:50
nginx: configuration file /etc/nginx/nginx.conf test failed
[root@master ~]#
报错,经过修改,最终如下
[root@master ~]# vim /etc/nginx/nginx.conf
................................................................................
#location / { #注掉这个
# root html;
# index index.html index.htm;
# rewrite ^/bbs/(.*)$ /forum/$1;
#}
location / {
proxy_pass http://192.168.0.61/;
if ($request_method = "PUT"){ #if后面要有空格,,,等于号左右要有空格
proxy_pass http://192.168.0.62; #这个后面是没有斜杠
}
}
................................................................................
[root@master ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@master ~]#
[root@master ~]# service nginx reload
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重新载入 nginx: [确定]
[root@master ~]#
在随便另一台电脑(linux)上 192.168.0.61
[root@slave ~]# curl http://192.168.0.60 #为什么都是node1, 没有node2
<h1>node1.magedu.com</h1>
[root@slave ~]# curl http://192.168.0.60
<h1>node1.magedu.com</h1>
[root@slave ~]# curl http://192.168.0.60
<h1>node1.magedu.com</h1>
[root@slave ~]# curl http://192.168.0.60
<h1>node1.magedu.com</h1>
[root@slave ~]#
如果做成集群(upstream),就可以在集群里面均衡了,通过proxy_pass指令实现
[root@slave ~]# curl -T /etc/fstab http://192.168.0.60 #上传
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>201 Created</title>
</head><body>
<h1>Created</h1>
<p>Resource /fstab has been created.</p>
<hr />
<address>Apache/2.2.15 (Red Hat) Server at 192.168.0.62 Port 80</address> #上传的地址
</body></html>
[root@slave ~]#
我们可以定义两个upstream,一个是读组,一个是写组,,,,我们要同步写组的内容(比如这里仅仅是 192.168.0.62 ) 同步到 192.168.0.61