代理原理
反向代理产生的背景:
在计算机世界里,由于单个服务器的处理客户端(用户)请求能力有一个极限,当用户的接入请求蜂拥而入时,会造成服务器忙不过来的局面,可以使用多个服务器来共同分担成千上万的用户请求,这些服务器提供相同的服务,对于用户来说,根本感觉不到任何差别。
反向代理服务的实现:
需要有一个负载均衡设备(即反向代理服务器)来分发用户请求,将用户请求分发到空闲的服务器上。
服务器返回自己的服务到负载均衡设备。
负载均衡设备将服务器的服务返回用户。
正向代理:
正向代理的过程隐藏了真实的请求客户端,服务器不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替请求
反向代理:
反向代理的过程隐藏了真实的服务器,客户端不知道真正提供的服务是谁,客户端请求的服务都被代理服务器接受。
扩展:
没有使用LVS时,客户端请求直接到反向代理Nginx,Nginx分发到各个服务器,服务端响应再由Ngnix返回给客户端,这样请求和响应都经过Ngnix的模式使其性能降低,这时用LVS+Nginx解决。
LVS+Nginx,客户端请求先由LVS接收,分发给Nginx,再由Nginx转发给服务器,LVS有三种方式:NAT模式(Network Address Translation)网络地址转换,DR模式(直接路由模式),IP隧道模式,路由方式使服务器响应不经过LVS,由Nginx直接返回给客户端。
实验:启用nginx proxy代理
环境准备俩台服务器
nginx-1 作为真实提供内容的网站服务器
ip 为10.36.192.48
nginx-2 作为代理服务器,就是客户端通过访问代理服务器的ip来访问真实服务器的内容ip为10.36.192.185
实验中 nginx-2的nginx为yum安装
启动
编辑代理机的nginx的配置文件:
[root@nginx-server ~]# vim /etc/nginx/conf.d/default.conf
server {
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://10.36.192.48:80; -----这里是管理真实服务器的ip 也可以写域名http://域名
proxy_redirect default;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
proxy_busy_buffers_size 256k;
proxy_max_temp_file_size 256k;
}
}
改完配置文件记得重新加载nginx的配置文件
[root@nginx-server ~]# nginx -s reload
通过登录网站来观察代理服务器和真实服务器的日志信息
这是代理服务器的日志,由于代理服务器的nginx是yum安装的 ,因此他的日志在/var/log/nginx/access.log
[root@daili nginx]# tailf /var/log/nginx/access.log
这是真实服务器的日志,由于真实服务器的nginx是源码安装的,因此他的日志默认在 /usr/local/nginx/logs/access.log内
[root@997 ~]# tailf /usr/local/nginx/logs/access.log
这是真实服务器的日志信息
这是代理服务器的日志信息
里面的10.36.192.24是我电脑本机的ip,实验过程是 我的电脑本机24通过访问代理机185来查看真实服务器48的内容。
因此我的代理服务器上的日志信息是 有代理服务器的IP185和电脑本机的ip24。
我的真实服务器上的日志信息是 也有代理服务器的IP185和电脑本机IP24。
就是没有真实服务器的ip,这是因为nginx就是提供反向代理的,而反向代理的本质就是隐藏真实服务器的IP。
nginx proxy具体配置详解
proxy_pass :真实服务器的地址,可以是ip也可以是域名和url地址
proxy_redirect :如果真实服务器使用的是的真实IP:非默认端口。则改成IP:默认端口。
proxy_set_header:重新定义或者添加发往后端服务器的请求头
proxy_set_header X-Real-IP :启用客户端真实地址(否则日志中显示的是代理在访问网站)
proxy_set_header X-Forwarded-For:记录代理地址
proxy_connect_timeout::后端服务器连接的超时时间发起三次握手等候响应超时时间
proxy_send_timeout:后端服务器数据回传时间就是在规定时间之内后端服务器必须传完所有的数据
proxy_read_timeout :nginx接收upstream(上游/真实) server数据超时, 默认60s, 如果连续的60s内没有收到1个字节, 连接关闭。像长连接
proxy_buffering on;开启缓存
proxy_buffer_size:proxy_buffer_size只是响应头的缓冲区
proxy_buffers 4 128k; 内容缓冲区域大小
proxy_busy_buffers_size 256k; 从proxy_buffers划出一部分缓冲区来专门向客户端传送数据的地方
proxy_max_temp_file_size 256k;超大的响应头存储成文件。
nginx Proxy配置
代理模块
ngx_http_proxy_module
代理配置
代理
Syntax: proxy_pass URL; #代理的后端服务器URL
Default: ---
Context: location, if in location, limit_except
缓冲区
Syntax: proxy_buffering on | off;
Default: proxy_buffering on; #缓冲开关
Context: http, server, location
proxy_buffering开启的情况下,nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端
(边收边传,不是全部接收完再传给客户端)。
Nginx 全局配置中的 tcp_nopush 的作用就是 数据包会累计到一定大小之后才会发送 。而 tcp_nodelay 是尽快发送数据,所以若你启用了 buffer,建议关闭 tcp_nodelay。
Syntax: proxy_buffer_size size;
Default: proxy_buffer_size 4k|8k; #缓冲区大小
Context: http, server, location
Syntax: proxy_buffers number size;
Default: proxy_buffers 4k|8k; #缓冲区数量
Context: http, server, location
Syntax: proxy_busy_buffers_size size;
Default: proxy_busy_buffers_size 8k|16k;#忙碌的缓冲区大小控制同时传递给客户端的buffer数量
Context: http, server, location
头信息
Syntax: proxy_set_header field value;
Default: proxy_set_header Host $proxy_host; #设置真实客户端地址
proxy_set_header Connection close;
Context: http, server, location
超时
Syntax: proxy_connect_timeout time;
Default: proxy_connect_timeout 60s; #链接超时
Context: http, server, location
Syntax: proxy_read_timeout time;
Default: proxy_read_timeout 60s;
Context: http, server, location
Syntax: proxy_send_timeout time; #nginx进程向fastcgi进程发送request的整个过程的超时时间
Default: proxy_send_timeout 60s;
Context: http, server, location
buffer 工作原理
所有的proxy buffer参数是作用到每一个请求的。每一个请求会按照参数的配置获得自己的buffer。proxy buffer不是global而是 request的。
proxy_buffering 是为了开启response buffering of the proxied server,开启后proxy_buffers和proxy_busy_buffers_size参数才会起作用。
无论proxy_buffering是否开启,proxy_buffer_size(main buffer)都是工作的,proxy_buffer_size所设置的buffer_size的作用是用来存储upstream端response的header。
在proxy_buffering 开启的情况下,Nginx将会尽可能的读取所有的upstream端传输的数据到buffer,直到proxy_buffers设置的所有buffer们 被写满或者数据被读取完(EOF)。此时nginx开始向客户端传输数据,会同时传输这一整串buffer们。同时如果response的内容很大的话,Nginx会接收并把他们写入到temp_file里去。大小由proxy_max_temp_file_size控制。如果busy的buffer 传输完了会从temp_file里面接着读数据,直到传输完毕。
一旦proxy_buffers设置的buffer被写入,直到buffer里面的数据被完整的传输完(传输到客户端),这个buffer将会一直处在busy状态,我们不能对这个buffer进行任何别的操作。所有处在busy状态的buffer size加起来不能超过proxy_busy_buffers_size,所以proxy_busy_buffers_size是用来控制同时传输到客户端的buffer数量的。
Nginx负载均衡
负载均衡的作用:
如果你的nginx服务器给2台web服务器做代理,负载均衡算法采用轮询,那么当你的一台机器web程序关闭造成web不能访问,那么nginx服务器分发请求还是会给这台不能访问的web服务器,如果这里的响应连接时间过长,就会导致客户端的页面一直在等待响应,对用户来说体验就打打折扣,这里我们怎么避免这样的情况发生呢。这里我配张图来说明下问题。
如果负载均衡中其中web2发生这样的情况,nginx首先会去web1请求,但是nginx在配置不当的情况下会继续分发请求道web2,然后等待web2响应,直到我们的响应时间超时,才会把请求重新分发给web1,这里的响应时间如果过长,用户等待的时间就会越长。
下面的配置是解决办法之一:
proxy_connect_timeout 1; #nginx服务器与被代理的服务器建立连接的超时时间,默认60秒
proxy_read_timeout 1; #nginx服务器向被代理服务器组发出read请求后,等待响应的超时间,默认为60秒。
proxy_send_timeout 1; #nginx服务器向被代理服务器组发出write请求后,等待响应的超时间,默认为60秒。
proxy_ignore_client_abort on; #客户端断网时,nginx服务器是否中断对被代理服务器的请求。默认为off。
使用upstream指令配置一组服务器作为被代理服务器,服务器中的访问算法遵循配置的负载均衡规则,同时可以使用该指令配置在发生哪些异常情况时,将请求顺次交由下一组服务器处理.
proxy_next_upstream timeout;
#反向代理upstream中设置的服务器组,出现故障时,被代理服务器返回的状态值。
error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off
error:建立连接或向被代理的服务器发送请求或读取响应信息时服务器发生错误。
timeout:建立连接,想被代理服务器发送请求或读取响应信息时服务器发生超时。
invalid_header:被代理服务器返回的响应头异常。
off:无法将请求分发给被代理的服务器。
http_400,....:被代理服务器返回的状态码为400,500,502,
upstream配置
upstream testapp { #这个testapp是自定义的, 就是管理下面这俩个真实服务器
server 10.0.105.199:8081; #可以指定端口,默认不写是80端口。
server 10.0.105.202:8081;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://testapp; #请求转向 testapp 定义的服务器列表,这个名字得与前面自定义的那个名字相同。
}
负载均衡的 算法:
upstream 支持4种负载均衡调度算法:
A、轮询(
默认)
:每个请求按时间顺序逐一分配到不同的后端服务器;B、
ip_hash
:每个请求按访问IP的hash结果分配,同一个IP客户端固定访问一个后端服务器。可以保证来自同一ip的请求被打到固定的机器上,可以解决session问题。C、
url_hash
:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器。后台服务器为缓存的时候提高效率。D、
fair
:这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx
本身是不支持fair
的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair
模块
配置实例:
1、热备
:如果你有2台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAAA突然A挂啦,BBBBBBBBBBBBBB...
upstream myweb {
server 172.17.14.2:8080;
server 172.17.14.3:8080 backup; #热备
}
默认情况下管理是遵循轮询规则,但是你设置热备以后,就是只会访问你没有设置热备的服务器,设置热备的服务器是空闲的,当你第一台服务器坏了,那么设置热备的服务器就会顶替上来
2.轮询:
nginx默认就是轮询其权重都默认为1,服务器处理请求的顺序:
ABABABABAB....
upstream myweb {
server 172.17.14.2:8080;
server 172.17.14.3:8080;
}
3、加权轮询
跟据配置的权重的大小而分发给不同服务器不同数量的请求。如果不设置,则默认为1。下面服务器的请求顺序为:ABBABBABBABBABB....
upstream myweb {
server 172.17.14.2:8080 weight=1;
server 172.17.14.3:8080 weight=2;
}
4、ip_hash:nginx
会让相同的客户端ip请求相同的服务器。
upstream myweb {
server 172.17.14.2:8080;
server 172.17.14.3:8080;
ip_hash;
}
5.nginx负载均衡配置状态参数
down,表示当前的server暂时不参与负载均衡。
backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
fail_timeout,在经历了max_fails次失败后,暂停服务的时间单位秒。max_fails可以和fail_timeout一起使用。
upstream myweb {
server 172.17.14.2:8080 weight=2 max_fails=2 fail_timeout=2;
server 172.17.14.3:8080 weight=1 max_fails=2 fail_timeout=1;
}
7层协议
4层协议
TCP/IP协议 之所以说TCP/IP是一个协议族,是因为TCP/IP协议包括TCP、IP、UDP、ICMP、RIP、TELNETFTP、SMTP、ARP、TFTP等许多协议,这些协议一起称为TCP/IP协议。
nginx的负载均衡还可以代理多台真实服务器
代理服务器的ip为10.36.192.185
代理服务器的端口: 80 81
真实服务器1的IP:10.36.192.48
它的端口有80 8081
真实服务器2的IP: 10.36.192.120
它的端口是 80 8081
真实服务器48的80端口的页面是
8081端口是
真实服务器120的80端口是
8081端口是
设置代理服务器的配置文件
upstream myweb {
server 10.36.192.48:80 weight=1 max_fails=2 fail_timeout=2s ;
server 10.36.192.120:80 weight=2 max_fails=2 fail_timeout=2s ;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://myweb;
proxy_redirect default;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
root /usr/share/nginx/html;
index index.html index.htm;
}
}
代理服务器的80端口管理俩台真实服务器的80端口的 内容
upstream testapp {
server 10.36.192.48:8081 weight=1 max_fails=2 fail_timeout=2s;
server 10.36.192.120:8081 weight=2 max_fails=2 fail_timeout=2s;
}
server {
listen 81;
server_name localhost;
charset utf-8;
#access_log logs/host.access.log main;
location / {
proxy_pass http://testapp;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
代理服务器的81端口管理俩台真实服务器的8081端口
添加完以后
重启代理服务器的nginx配置
# nginx -s reload
开始测试: