反向代理
关于反向代理的例子, 那就比较多啦. 比如, 孤独的你躺在床上夜不能寐. 于是乎, 拿出手机, 点亮了屏幕, 拨通10086, 中国移动就会随机分配一个当前处于空闲的客服MM, 你可以和客服MM聊聊天, 问问她家住哪里, 有没有男朋友, 她的微信号, 她的手机号, 星座, 八字.......
在这个例子中, 中国移动就充当了反向代理的角色. 你只需要拨打 10086. 至于会不会分配到 MM 会分配到哪个 MM 在接通之前你都是不知道的. 反向代理在互联网中的使用主要是实现负载均衡.当你访问某个网站的时候, 反向代理服务器会从当前网站的所有服务器中选择一个空闲的服务器为你响应. 用于均衡每台服务器的负载率。
反向代理是nginx的一个重要功能,在编译安装时会默认编译该模块。在配置文件中主要配置proxy_pass指令。代理服务器接受客户端的请求,然后把请求代理给后端真实服务器进行处理,然后再将服务器的响应结果返给客户端。
反向代理的优点
1)保护服务安全
隐藏服务节点的IP。将服务节点置于防火墙之后,避免直接攻击业务节点服务器。
2)服务节点更专注于业务,同时提升性能
由于有反向代理的存在,可以让反向代理服务器去实现比如https、gzip压缩等与业务无关的功能提供动静态分离,将静态文件发往静态服务器或本地文件系统,避免业务节点处理这些与业务无关的请求提供缓存机制,将一些短时间内不会变化的动态内容,在反向代理服务器这层增加缓存,降低业务服务器的请求量由于控制权在代理服务这边,完全可以根据服务节点的性能动态分配请求,做到服务节点性能最佳
正是由于Ngxin引入了反向代理的特性,让请求和响应都要经过Nginx,因此给Nginx带来了非常多的可能。比如负载均衡、HTTP缓存等。
反向代理语法
代理服务器的协议,可支持http与https,地址可以指定为域名或IP地址,以及可选端口。proxy模块从客户端接受的是HTTP协议,转发给上游的还是HTTP协议,例如:
Syntax: proxy_pass URL;Default: —Context: location, if in location, limit_exceptproxy_pass http://localhost:9000/uri/;proxy_pass http://192.168.0.188:8080;proxy_pass http://192.168.0.188;
反向代理示例几则
实例一:location和proxy_pass都不带uri路径
192.168.179.99代理服务器 192.168.179.100后端服务器 192.178.179.101客户端192.168.179.99代理服务器[root@www vhost]# vim /usr/local/nginx/conf/vhost/.conf --当访问server {listen 192.168.179.99:80;server_name ;charset utf-8;root /data/www/test1;location /{proxy_pass http://192.168.179.100; --代理给后端服务器192.168.179.100}}192.168.179.100 后端服务器server{listen 80;server_name localhost;charset utf-8;location =/{index index.html; }}[root@www ~]# echo "proxy this is 192.168.179.100 page" > /usr/local/nginx/html/index.html --在后端服务器主页面显示proxy this is 192.168.179.100 page[root@www ~]# curl localhostproxy this is 192.168.179.100 page客户端192.168.179.101访问后端192.168.179.100资源的两种方法(1)不通过代理,客户端直接访问后端192.168.179.100上的资源[root@www ~]# curl 192.168.179.100/index.htmlproxy this is 192.168.179.100 page(2)客户端通过代理服务器192.168.179.99访问192.168.179.100的资源[root@www ~]# curl 192.168.179.99/index.html --可以看到访问的是179.99的页面却拿到的是179.100的页面资源,对于客户端压根感觉不到179.100的存在,所以说后端的服务器对于我们来说是屏蔽的,只能感觉到代理服务器的存在proxy this is 192.168.179.100 page[root@www ~]# tail -f /usr/local/nginx/logs/access.log --可以看到后端服务器压根不知道客户端的IP信息,只能得到代理服务器的信息192.168.179.99 - - [15/Mar/:22:23:25 +0800] "GET /index.html HTTP/1.0" 200 35 "-" "curl/7.29.0"
实例二:proxy_pass没有设置uri路径,但是代理服务器的location 有uri,那么代理服务器将把客户端请求的地址传递给后端服务器
192.168.179.99代理服务器server {listen 192.168.179.99:80;server_name ;charset utf-8;root /data/www/test;location /document/data/{ --这里请求的路径会追加到后端root路径后proxy_pass http://192.168.179.100;}}192.168.179.100后端服务器server{listen 80;server_name localhost;charset utf-8;error_page 404 =200 /404.html;location =/{index index.html; }}[root@www ~]# mkdir -p /usr/local/nginx/html/document/data/[root@www ~]#echo "proxy this is 192.168.179. 100 /usr/local/nginx/html/document/data/index.html" > /usr/local/nginx/html/document/data/index.html192.168.179.101客户端访问[root@www ~]# curl 192.168.179.99/document/data/index.htmlproxy this is 192.168.179. 100 /usr/local/nginx/html/document/data/index.html可以看到,完整请求路径是在后端服务器的root路径/usr/local/nginx/html 后追加客户端请求的路径/document/data/
实例三:如果proxy_pass设置了uri路径,则需要注意,此时,proxy_pass指令所指定的uri会覆盖location的uri。
192.168.179.99代理服务器(/img路径会覆盖/document/data路径)server {listen 192.168.179.99:80;server_name ;charset utf-8;root /data/www/test;location /document/data/{proxy_pass http://192.168.179.100/img/;}}192.168.179.100后端服务器服务端是创建/usr/local/nginx/html/img 还是创建/usr/local/nginx/html/img/document/data ??server{listen 80;server_name localhost;charset utf-8;location /{root html;index index.html;}}[root@www ~]# mkdir -p /usr/local/nginx/html/img[root@www ~]# echo "proxy this is 192.168.179.100 /usr/local/nginx/html/img/index.html" > /usr/local/nginx/html/img/index.html 192.168.179.101 客户端访问[root@www ~]# curl 192.168.179.99/document/data/index.htmlproxy this is 192.168.179.100 /usr/local/nginx/html/img/index.html可以看到如果 proxy_pass 指定了uri路径,与location的uri /document/data/ 就失效了,就不再参考location的uri了。
获取远程客户端真实ip地址(我们并不关心代理服务器的IP,我们关心的是客户端的IP)
因为后端的服务器只知道代理服务器的信息,并不知道客户端的信息,客户端和服务端中间隔着代理服务器。有些服务端需要知道客户端真实的IP,那么这就需要代理服务器将客户端的信息给到后端了
192.168.179.99代理服务器server {listen 192.168.179.99:80;server_name ;charset utf-8;root /data/www/test;location /document/data/{proxy_pass http://192.168.179.100/img/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}192.168.179.100后端服务器日志格式log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_real_ip"';access_log logs/access.log main;192.168.179.101 客户端访问[root@www ~]# curl 192.168.179.99/document/data/proxy this is 192.168.179.100 /usr/local/nginx/html/img/index.html192.168.179.101后端查看日志信息(1)通过curl[root@www ~]# tail -f /usr/local/nginx/logs/access.log --查看后端服务器日志信息192.168.179.99 - - [21/Mar/:10:06:24 +0800] "GET /img/hh.html HTTP/1.0" 200 26 "-" "curl/7.29.0" "192.168.179.101" --可以看到日志里面记录了远程客户端的真实IP192.168.179.101(2)通过浏览器 中输入/document/data/ 访问是如下日志192.168.179.99 - - [21/Mar/:10:11:17 +0800] "GET /img/hh.html HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36" "192.168.179.4"