nginx反向代理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nginx反向代理相关的知识,希望对你有一定的参考价值。
一、概念理解
正向代理
在说啥啥反向代理之前,先说下什么是代理
或者正向代理
。
正向代理
也就是代理,他的工作原理就像一个跳板,简单的说,我访问不了google.com,但是我能访问一个代理服务器A,A能访问google.com,于是我先连上代理服务器A,告诉他我需要google.com的内容,A就去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。
结论就是,正向代理
是一个位于客户端
和原始服务器(origin server)
之间的服务器。为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。
目前代理软件很多,浏览器上的代理就更多了。FQ一般就是使用代理服务器的。
反向代理
ok,说完正向代理,再来说啥是反向代理
!
举个例子,比如我想访问 http://www.test.com/readme
,但www.test.com
上并不存在readme
页面,于是他是偷偷从另外一台服务器上取回来,然后作为自己的内容返回用户,但用户并不知情。这里所提到的 www.test.com 这个域名对应的服务器就设置了反向代理功能
。
结论就是,反向代理
正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样。而正向代理用户是知道内容来自哪个网站的。
嗯。正向代理和反向代理就基本清楚了,那我们就来用nginx来配置一个反向代理。
nginx 使用反向代理,主要是使用location
模块下的proxy_pass
选项
二、环境
client:192.168.17.122 proxy:192.168.119.130 real-server1:192.168.119.133 real-server2: 192.168.17.120
准备工作:代理服务器都能正常提供web服务。
proxy安装nginx,real-server安装nginx或apache。笔者三台机器都是安装nginx
real-server1配置文件:
[[email protected]]# egrep -v "^$|#" /usr/local/nginx/conf/nginx.conf user www; worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root /mywww; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
real-server1目录结构:
[[email protected]]# tree /mywww/ /mywww/ ├── hehe │ └── index.html ├── hello │ └── index.html └── index.html 2 directories, 3 files
RS2配置与RS1类似,两台机器安装nginx后配置文件几乎没改,因为测试越简单越易于理解
三、proxy配置
[[email protected] ~]# egrep -v "^$|^#" /usr/local/nginx/conf/nginx.conf user deamon; worker_processes 8; error_log /var/log/nginx/error.log warn; pid /var/run/nginx/nginx.pid; events { use epoll; #使用epoll高效模式,适用于Linux,Unix使用kqueue worker_connections 100000; } worker_rlimit_nofile 100000; #打开的文件句柄数量最高为10万 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; ... ... ... server { listen 80 ; #监听端口号 server_name localhost; root /www/; location / { index index.php index.html index.htm; if (!-e $request_filename) { return 444; } } location ~ \\.php$ { root /www; fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_index index.php; fastcgi_cache_valid 200 60m; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }
########################################################################### location /zabbix{ proxy_pass http://192.168.17.120; } location /haha { proxy_pass http://192.168.119.133/hello; } location /hehe { proxy_pass http://192.168.119.133:80; }
#
########################################################################### #指定对网页图片格式进行缓存max表示10年,也可以是30d(天) location ~ \\.(swf|js|css|xml|gif|jpg|jpeg|png|bmp)$ { error_log off; access_log off; #expires 30d; expires max; } } }
[[email protected] ~]# egrep -v "^$|^#" /usr/local/nginx/conf/nginx.conf user deamon; worker_processes 8; #指定了要开启的进程数,每进程占用10M~12M的内存,建议和CPU的核心数量一样多的进程就行了。 error_log /var/log/nginx/error.log warn; pid /var/run/nginx/nginx.pid; events { use epoll; #使用epoll高效模式,适用于Linux,Unix使用kqueue worker_connections 100000; #定义Ningx没个进程最大的连接数。默认为1024,受到文件句柄的约束。 } worker_rlimit_nofile 100000; #打开的文件句柄数量最高为10万 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 /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; server_names_hash_bucket_size 128; client_header_buffer_size 32k; #客户端请求头部的缓冲区大小,一般一个请求头的大小不会超过1k large_client_header_buffers 4 32k; #客户请求头缓冲大小 nginx默认会用client_header_buffer_size这个buffer来读取header值 client_max_body_size 8m; #设定通过nginx上传文件的大小 gzip on; #该指令用于开启或关闭gzip模块(on/off) gzip_min_length 1k; #设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取 gzip_buffers 4 16k; #设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流 gzip_http_version 1.0; #识别http的协议版本 gzip_comp_level 2; #gzip压缩比,1压缩比最小处理速度最快 #匹配mime类型进行压缩,无论是否指定,”text/html”类型总是会被压缩的 gzip_types text/plain application/x-javascript text/css application/xml text/javascript; gzip_vary on; #和http头有关系,加个vary头,给代理服务器用的 charset utf-8; #字符集为utf-8 access_log off; # 日常日志关闭 log_not_found off; # 日常日志关闭 fastcgi_connect_timeout 300; #指定连接到后端FastCGI的超时时间。 fastcgi_send_timeout 300; #向FastCGI传送请求的超时时间,这个值是指已经完成两次握手后向FastCGI传送请求的超时时间。 fastcgi_read_timeout 300; #接收FastCGI应答的超时时间,这个值是指已经完成两次握手后接收FastCGI应答的超时时间。 fastcgi_buffer_size 254k; #指定读取FastCGI应答第一部分需要用多大的缓冲区 fastcgi_buffers 16 256k; #指定本地需要用多少和多大的缓冲区来缓冲FastCGI的应答。 fastcgi_busy_buffers_size 512k; #这个指令我也不知道是做什么用,只知道默认值是fastcgi_buffers的两倍。 fastcgi_temp_file_write_size 512k; #在写入fastcgi_temp_path时将用多大的数据块,默认值是fastcgi_buffers的两倍。 server { listen 80 ; #监听端口号 #域名为 server_name localhost; # 指定网站的目录 root /www/; # localtion模块指定网站首页名称 location / { index index.php index.html index.htm; if (!-e $request_filename) { return 444; } } location ~ \\.php$ { root /www; #fastcgi_cache MYAPP; #fastcgi_cache_valid 200 60m; fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_index index.php; fastcgi_cache_valid 200 60m; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location /zabbix{ proxy_pass http://192.168.17.120; } location /haha { proxy_pass http://192.168.119.133/hello; } location /hehe { proxy_pass http://192.168.119.133:80; } #指定对网页图片格式进行缓存max表示10年,也可以是30d(天) location ~ \\.(swf|js|css|xml|gif|jpg|jpeg|png|bmp)$ { error_log off; access_log off; #expires 30d; expires max; } }
由于之前在proxy上放了zabbix服务,所以配置文件稍微复杂一点,但不用管这些,只需要关注#####框住部分配置
实际上proxy机器上并没有zabbix目录,也没有hehe、haha目录
这一配置实现的结果就是client访问proxy的zabbix目录时,proxy会从192.168.17.120的web根目录下的zabbix目录获取数据(index.html),再返回给client,这中间发生的一切对client完全透明,client一直认为数据是从proxy获取。、
client访问proxy的haha目录时,proxy会从192.168.119.133的web根目录的hello目录下获取数据(index.html),为什么不是web根目录下的haha目录?只能意会不能言传,比较比较应该能得出结果
client访问proxy的hehe目录时,proxy会从192.168.119.133的web根目录下的hehe目录下获取数据(index.html)
四、访问结果
#####################################################################
利用tcpdump查看RS1(192.168.119.133)的真实客户端,RS1运行tcpdump后用client浏览器访问proxy的haha目录
tcpdump抓取数据包结果:
[[email protected] mywww]# tcpdump -i eth0 dst host 192.168.119.133 and dst port 80 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:47:42.156816 IP 192.168.119.130.54144 > 192.168.119.133.http: Flags [S], seq 1736642454, win 14600, options [mss 1460,sackOK,TS val 2464156420 ecr 0,nop,wscale 6], length 0
14:47:42.157102 IP 192.168.119.130.54144 > 192.168.119.133.http: Flags [.], ack 1302104194, win 229, options [nop,nop,TS val 2464156420 ecr 2378460417], length 0
14:47:42.157119 IP 192.168.119.130.54144 > 192.168.119.133.http: Flags [P.], seq 0:491, ack 1, win 229, options [nop,nop,TS val 2464156420 ecr 2378460417], length 491
14:47:42.157539 IP 192.168.119.130.54144 > 192.168.119.133.http: Flags [.], ack 174, win 245, options [nop,nop,TS val 2464156421 ecr 2378460418], length 0
14:47:42.158316 IP 192.168.119.130.54144 > 192.168.119.133.http: Flags [F.], seq 491, ack 175, win 245, options [nop,nop,TS val 2464156421 ecr 2378460418], length 0
由此可见是proxy在访问RS1
RS1数据是直接返回给client还是proxy呢?
[[email protected] mywww]# tcpdump -i eth0 src host 192.168.119.133 and dst host 192.168.119.130 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:55:28.542770 IP 192.168.119.133.http > 192.168.119.130.55754: Flags [S.], seq 198025648, ack 2710538549, win 14480, options [mss 1460,sackOK,TS val 2378926803 ecr 2464622812,nop,wscale 6], length 0
14:55:28.542949 IP 192.168.119.133.http > 192.168.119.130.55754: Flags [.], ack 492, win 243, options [nop,nop,TS val 2378926803 ecr 2464622812], length 0
14:55:28.543039 IP 192.168.119.133.http > 192.168.119.130.55754: Flags [P.], seq 1:174, ack 492, win 243, options [nop,nop,TS val 2378926803 ecr 2464622812], length 173
14:55:28.543068 IP 192.168.119.133.http > 192.168.119.130.55754: Flags [F.], seq 174, ack 492, win 243, options [nop,nop,TS val 2378926803 ecr 2464622812], length 0
14:55:28.543167 IP 192.168.119.133.http > 192.168.119.130.55754: Flags [.], ack 493, win 243, options [nop,nop,TS val 2378926803 ecr 2464622812], length 0
数据也是直接返回给proxy的
#####################################################################################
怎么降低代理服务器的负载?
方法倒是有:nginx proxy只负责分发客户端请求,响应由后端服务器直接返回给客户端,但这种方法不符合通信过程,因为数据包包头的目的地址和源地址不会改变,假设客户端IP为a,代理服务器IP为b,后端服务器IP为c,那么分发请求时源地址为b,目的地址为c,当后端服务器返回时将c作为源地址,b作为目的地址,这样就不能实现后端服务器直接返回数据给客户端。
怎么解决该问题?
把客户端信息,如IP也传给后端服务器即可,这需要nginx支持realip,所以编译时需要加上:--with-http_realip_module
以上是关于nginx反向代理的主要内容,如果未能解决你的问题,请参考以下文章