Linux运维笔记
我们一直在努力

Nginx反向代理原理和配置实现

Nginx作为一个WEB服务器来说,有个非常重要的功能就是反向代理(Proxy)

一、介绍:

要搞清楚什么是Nginx的反向代理,他是干什么的,为什么要用反向代理,其实是很简单的。

通俗点说

反向代理不干活,他是传话筒,负责把用户的请求传送给后端的Nginx、httpd、Tomcat等负责处理静态或动态资源的服务器,由他们处理完请求后,再返回给Nginx的反向代理服务器,最后把结果给到用户

还不懂???

比如,去快递公司拿快递,有个个窗口坐着美女,看不到其他人,然后你和他说,美女,我要11111的快递

美女接过你的请求转头和后面小窗内的小哥说,把11111的快递找出来给我,

小哥找出来后给了前台

前台再把快递给了你

这个当中美女是Nginx反向代理,而小哥可能是Tomcat或者httpd、PHP这样的服务器,他们才是真正负责处理快递的,而美女(就是Nginx反向代理),他是不负责处理的,只是把请求转到正确的服务器上,在后端服务器处理的这段时间中,Nginx反向代理是处理空闲中的,他只要等待后端把结果返回给他

  • 通常面对外网可以接受访问的只有一台主机(即Nginx反向代理主机本身)
  • 后端真实处理请求的服务器不止一台,可以有多台
  • 后端处理请求的服务器可以没外网,但是要和Nginx反向代理处于同一局域网
  • Nginx反向代理也可以转发给本地127.0.0.1
  • 网页文件都是存放在后端的应用处理服务器上的

使用Nginx反向代理的好处:

  • 缓存
    可以把经常访问的数据缓存在内存中,下次访问可以直接调用本地缓存,无需再转发请求到后端,提高网站的访问速度。 
  • 防火墙功能
    由于所有的客户端请求都必须通过Nginx代理服务器访问后端真实主机,因此可在代理服务器上设限,过滤某些不安全信息。 
  • 负载均衡
    反向代理不但可以把请求代理给一台主机,也可以平均把多个请求分散到后端多个主机上处理,以达到减少服务器压力,加速网站访问的目的

 

二、配置:

反向代理是写在location { }字块中,通过location匹配对应的条件,然后转发给相应的后端

 

案例1:

server {
    listen 80;
    server_name localhost;
    location / {
        proxy_pass http://127.0.0.1;
    }
}

以上就是最简单的一个反向代理,表示只要访问的是url/,也就是网页链接的根,就转发到后端的127.0.0.1,如果没端口默认的是转发到80端口

如果Nginx转发到本地主机上的另外一个服务,比如Nginx转发给Tomcat,通常为了让Nginx反向代理能够正常接收请求,通常是80端口或443,而后端的服务则是8080等非80和443端口

所以只要写上 proxy_pass http://127.0.0.1:8080;

 

案例2:

仅仅有以上的配置实在太简单了,可能不利于我们业务的发展

server {
    listen 80;
    server_name www.redppx.cn;
    index index.php;
    server_tokens off;
    # [Proxy] 反向代理配置字段
    location / {
        proxy_pass http://192.168.10.3:6080;
        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;
    }
}

在location字段中,访问url/的所有请求都转发给了后端一台192.168.10.3服务器上的6080端口,那台服务器上6080端口是httpd服务

除了这段还多出来了几个proxy开头的字段,给大家解释一下

  • proxy_redirect off;
  • 在proxy时是否做重定向,指定修改被代理服务器返回的响应头中的location头域跟refresh头域数值,利用这个指令可以为被代理服务器发出的相对重定向增加主机名
  • proxy_set_header Host $host;
  • # 有虚拟主机的话也能转发,就是让后端的服务器知道,到底用户请求的域名是什么,这样后端服务器有虚拟主机也可以通过域名匹配
  • proxy_set_header X-Real-IP $remote_addr;
  • # 把真正请求的客户端IP发往后端的Server
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  • # 一般Nginx代理是多级的,Nginx向后端代理的时候又是一个Nginx反向代理,在是一个反向代理最终才能到达RealServer,我们为了让后端主机知道,这个请求到底被代理了多少次

到这里其实反向代理能满足我们大部分业务场景的需求了,如果还需要能精确的对服务器优化和根据业务自定义参数的化,我还提供了一部分的参数给大家参考

  • client_max_body_size 20m; # 我们能够接受客户端的最大请求主体部分大小
  • client_body_buffer_size 256k; # 每一个请求报文body buffs大小;要允许客户端上传文件,这20M数据传完后才是完整的,把这20m数据放哪里先?肯定拆成多个IP报文发过来,发了一个发了一个,我们需要在内存中先缓存下来,内存不够的话还应该缓存在client_body_temp_path,为什么只有256k,如果有1w个并发同时上传文件,每一个人都给256k这个就是很大的内存
  • proxy_connect_timeout 90; # 向后端服务器发起连接请求时的超时时间
  • proxy_send_timeout 90; # 向后端服务器发起报文的超时时间
  • proxy_read_timeout 90; # 读取后端服务器响应报文的超时时间
  • proxy_buffer_size 128k; # 代理服务器的缓冲大小
  • proxy_buffers 4 64k; # 表示proxy有4个buffer,表示4段缓冲空间,每一段是64K
  • proxy_busy_buffers_size 128k; # (默认够用,不用管)
  • proxy_temp_file_write_size 128k; # (默认够用,不用管)

案例3(负载均衡):

对于负载均衡配置很简单,除了之前的server {}和 location {}字段,还需要配置一个upstream {} 字段

http {
此处省略N... 
    # [Upstream] Nginx的负载均衡模块配置
    upstream PorxyName {
        server 192.168.0.11:7080 weight=3;
        server 192.168.0.12:7080 weight=3;
        server 192.168.0.13:7080 weight=3;
        server 192.168.0.14:7080 weight=3;
    }
    server {
        listen 80;
        server_name www.redppx.cn;
        index index.php;
        server_tokens off;
        # [Proxy] 反向代理配置字段(包含负载均衡配置)
        location / {
                proxy_pass https://PorxyName;
                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;
        }
}

比如后端有4台httpd的服务器,上面运行着同一个论坛程序

Upstream字段里就是后端处理请求主机列表,一行一个主机IP:端口,PorxyName是自定义的名称,这个名字用在location {}字段中的 proxy_pass https://PorxyName;

也就是说你Upstream写的是什么名字,反向代理就是什么名字,把IP改成upstream的名字即可,这个时候就是负载均衡了

定义负载均衡方式:

1、轮询:

即1个1个平均分配

upstream ProxyName {
    server 172.16.0.162;
    server 172.16.0.163;
}

2、权重:

weight=数字:定义权重,默认为1

在做负载均衡时候占的比重多少,如果有2台主机,一台是3,一台是7,那么如果同时来了10个请求,3个分配给第一个,7个分配给第二个

upstream ProxyName {
    server 172.16.0.162 weight=3;
    server 172.16.0.163 weight=7;
}

3、ip_hash:

根据客户端IP进行调度,每个客户端IP地址来访问时都生成一个hash码,将来自于同一个主机调度到同一个RealServer。

upstream ProxyName {
    ip_hash; 
    server 172.16.0.162 weight=6;
    server 172.16.0.163 weight=2;
}

 

案例4(缓存):

  • Nginx缓存很独特,是键值存储(KV),而键是放在内存中的,数据则是放在磁盘上的。
  • proxy_cache_path :定义缓存目录的位置,只能用在http {}字段
  • 可用定义多个proxy_cache_path
  • 在不同的server中可以调用不同的proxy_cache
http {
此处省略N... 
proxy_cache_path  /tmp/cache/nginx levels=1:1 keys_zone=ProxyCache:32m max_size=64m inactive=1m;  # 这里是定义一个缓存
    # [Upstream] Nginx的负载均衡模块配置
    upstream PorxyName {
        server 192.168.0.11:7080 weight=3;
        server 192.168.0.12:7080 weight=3;
        server 192.168.0.13:7080 weight=3;
        server 192.168.0.14:7080 weight=3;
    }
    server {
        listen 80;
        server_name www.redppx.cn;
        index index.php;
        server_tokens off;
          proxy_cache             ProxyCache01;         # 这里则是调用相应的缓存
          proxy_cache_valid       any 1m;
          proxy_cache_min_uses    2;
        # [Proxy] 反向代理配置字段(包含负载均衡配置)
        location / {
                proxy_pass https://PorxyName;
                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;
        }
}

定义缓存解释:

示例1 proxy_cache_path /cache/nginx levels=1:1 keys_zone=ProxyCache:32m max_size=64m inactive=1m;

示例2 proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;

缓存目录: /data/nginx/cache

1级2级子目录: levels=1:2

:的前是1级,后面是2级,如果在加一个:,:后面为三级。

        如:1:2:1,代表可以用1-3子目录

数字代表每个子目录可以用的字符数:

        如:1:2代表: 1级子目录名字可用1个字符

                               2级子目录名字可用2个字符。

【 如 】:/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c

c为1级子目录名字的字符(1个)

29为2级子目录名字的字符(2个)

[keys_zone=name:size]:内存中存键的

在内存空间中找size大小的空间,给他取ProxyCache这个名字,当做键存储的位置的。

[inactive=time] 非活动期限

一个缓存被放在这里以后,应该会被频繁的使用到,最后一次使用完后多长时间再不使用了,不是放进来就非活动期限,而是放进来后再到达非活动期限前你访问了,非活动期限会重新计数的。也就意味着在这么长时间,必须被访问过一次,如果一次没被访问就会被清除出去

调用缓存

proxy_cache ProxyCache;     # 这里则是调用相应的缓存
proxy_cache_valid any 1m;   # 缓存时间,表示任何缓存都保存1m
proxy_cache_min_uses 2;     # 某一个响应报文,用户请求内容被响应多少次以后才缓存

赞(0) 打赏

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址