Nginx(恩静克斯)--正向代理、反向代理及负载均衡(图解+配置)

Nginx(恩静克斯)--正向代理、反向代理及负载均衡(图解+配置)

Nginx的官方正确读音是“恩静·埃克斯”即“Engine X”  (恩静X 或 快读为 恩静克斯);

Nginx (engine x) 是一款轻量级的高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP电子邮件代理服务。
其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。

 

 

 

目录
学习背景
一、代理服务
二、正向代理
  2.1 什么是正向代理?
  2.2 如何实现nginx正向代理?
  2.3 客户端访问(验证正向代理)
三、反向代理
   3.1 什么是反向代理?
   3.2 nginx实现反向代理
四、负载均衡
   4.1 什么是负载均衡?
   4.2 负载均衡算法有哪些?

五、Nginx的核心配置
    5.1 Nginx的Master-Worker模式
    思考:Nginx如何做到热部署?
    思考:Nginx如何做到高并发下的高效处理?
   思考:Nginx挂了怎么办?
   5.2 我们的主战场:nginx.conf配置
       5.2.1 虚拟主机
       5.2.2 反向代理【proxy_pass】
       5.2.3 负载均衡【upstream】
       5.2.4 缓存

 

学习背景

   什么是nginx?

      【百度百科】
  Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,公开版本1.19.6发布于2020年12月15日。
    其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2022年01月25日,nginx 1.21.6发布。
   Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好。

       读音发音:Nginx的官方正确发音是“恩静埃克斯”即“Engine X”  (恩静X);  Engine[ˈendʒɪn]   [ˈendʒɪn] 引擎(恩静) 。

       除了反向代理,nginx还支持正向代理、负载均衡以及基于SSL安全证书的HTTPS访问等功能特性~
       本文主要是介绍是如何配置nginx正向代理、反向代理及负载均衡,进入正文~

 

一、代理服务

什么是代理?来一张图了解下

           

代理又分为正向代理和反向代理。

 

 

二、正向代理

1.1 什么是正向代理?

先来看张图 

              在这里插入图片描述
【再举个栗子】

 某同学喜欢面向搜索引擎编程,想通过 百度 搜索引擎查找一些学习资料,但是有些网站直接访问可能不太安全,会暴露自己的IP,同学比较苦恼,想着怎样才能使用百度 搜索自己想要的学习资料,又不会暴露自己的IP在网站上呢?

这时我告诉该同学,我呢手上刚好有一台代理服务器,这台代理服务器通过nginx配置了正向代理转发http和https请求,你呢,只需要在自己的Windows本地电脑的网关配置一下这台代理服务器的IP和端口号,就能正常通过代理服务器访问到百度 并搜索相关的学习资料了,还不会暴露自己真实的IP~


同学非常兴奋,说自己了解过nginx,但是啥是正向代理啊?

正向代理,指的是通过代理服务器 代理浏览器/客户端去重定向请求访问到目标服务器 的一种代理服务。
正向代理服务的特点是代理服务器 代理的对象是浏览器/客户端,也就是对于目标服务器 来说浏览器/客户端是隐藏的。

 

同学觉得有点意思,于是又问,那nginx如何实现正向代理啊?

 

1.2 如何实现nginx正向代理?

(1)正向代理转发https说明

在实现nginx正向代理之前,先说明一下,现在的网站基本上都是https,因此要实现nginx正向代理转发请求,除了要配置转发http80端口的请求,还有配置https443端口的请求~
正向代理转发http请求很简单,不过正向代理转发https请求稍微有一点麻烦,目前网上的教程大多都是如下这样配置的(也不知道他们验证过没。。。):

  一开始我也像上面那样配置,虽然http请求正常转发了,但是发现https并没有转成功,而是报错HTTP/1.1 400 Bad Request~

   后来才了解到,nginx官方并不支持直接转发https请求,但是阿里的一个大佬对nginx拓展了一个ngx_http_proxy_connect_module模块,并且在github上开源了: https://github.com/chobits/ngx_http_proxy_connect_module

  不过维护的ngx_http_proxy_connect_module模块的补丁也是有nginx版本限制的(目前维护了1.4.x~1.19.x版本),如README.md说明:

如果你安装的nginx版本不在1.4.x~1.19.x这个范围内,那无法支持正向代理转发https请求。

 

(2)安装nginx
如果已安装nginx(可跳过),这里以1.9.2版本为例,使用root用户进行安装:

$ cd /usr/nginx
$ wget http://nginx.org/download/nginx-1.9.2.tar.gz
$ tar -xzvf nginx-1.9.2.tar.gz
$ cd /usr/nginx/nginx-1.9.2
$ make && make install

 这里安装nginx通过install进行编译安装,编译后默认安装目录为/usr/local/nginx,后续配置新模块ngx_http_proxy_connect_module还需要重新install编译一次~

 

(3)下载新模块
GitHub上下载ngx_http_proxy_connect_module的zip压缩包源码:https://github.com/chobits/ngx_http_proxy_connect_module

  

(4)解压新模块源码
将新模块ngx_http_proxy_connect_module源码压缩包上传到服务器/usr/nginx目录,并解压并重命名

$ mkdir -p /usr/nginx
$ cd /usr/nginx
$ /usr/nginx
$ unzip ngx_http_proxy_connect_module-master.zip
$ mv ngx_http_proxy_connect_module-master ngx_http_proxy_connect_module

 

(5)添加新模块到nginx
使用root用户进入nginx的资源目录/usr/nginx/nginx-1.9.2,给nginx添加新模块ngx_http_proxy_connect_module和并重新编译nginx 

$ /usr/nginx/nginx-1.9.2
$ patch -p1 < /usr/nginx/ngx_http_proxy_connect_module/patch/proxy_connect.patch
$ ./configure --add-module=/usr/nginx/ngx_http_proxy_connect_module
$ make && make install

  –说明: 这里nginx-1.9.2版本对应proxy_connect.patch补丁,其他版本相关补丁支持版本,详情见GitHub~         https://github.com/chobits/ngx_http_proxy_connect_module

 使用root用户安装和编译新模块完成后,如果你希望后续不使用root用户运维,可以授权安装目录/usr/local/nginx给nginx用户或者其他普通用户~

chown -R nginx:nginx /usr/local/nginx
chown root:root /usr/local/nginx/sbin/nginx
chmod +s /usr/local/nginx/sbin/nginx

 –说明:二进制/usr/local/nginx/sbin/nginx文件需要重新归属为root用户,并且权限位添加s权限(权限位+s的二进制文件属于是管道文件,也就是普通用户也可执行该二进制文件,执行后产生的进程属于该文件的权限所有者,这里文件所有者是root)


(6)修改nginx的配置
修改nginx的配置分别添加http和https的server,其他配置保持不变~

vi /usr/local/nginx/conf/nginx.conf

 

这两个server主要配置是对DNS解析和proxy_pass代理进行:

#正向代理转发http请求
server {
#指定DNS服务器IP地址 resolver 114.114.114.114; #监听80端口,http默认端口8 listen 80; #服务器IP或域名 server_name localhost; #正向代理转发http请求 location / { proxy_pass http://$host$request_uri; proxy_set_header HOST $host; proxy_buffers 256 4k; proxy_max_temp_file_size 0k; proxy_connect_timeout 30; proxy_send_timeout 60; proxy_read_timeout 60; proxy_next_upstream error timeout invalid_header http_502; } } #正向代理转发https请求 server { #指定DNS服务器IP地址 resolver 114.114.114.114; #监听443端口,https默认端口443 listen 443; #正向代理转发https请求 proxy_connect; proxy_connect_allow 443 563; proxy_connect_connect_timeout 10s; proxy_connect_read_timeout 10s; proxy_connect_send_timeout 10s; location / { proxy_pass http://$host; proxy_set_header Host $host; } }

 ----DNS说明:

(国内外)目前比较主流的DNS:
(国外)谷歌:8.8.8.8 developers.google.com
(国外)OpenDNS:208.67.222.222 signup.opendns.com
(国内)114:114.114.114.114 www.114dns.com
(国内)腾讯:119.29.29.29 www.dnspod.cn
(国内)阿里:223.5.5.5 alidns.com
(国内)百度:180.76.76.76 dudns.baidu.com

 

(7)检查和刷新nginx配置

/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s reload

  

1.3 客户端访问(验证正向代理)

客户端要代理访问目标网站示例对象:http://www.baidu.com 和https://www.baidu.com

(1)客户端–Windows浏览器访问

首先在本地电脑的IE浏览器设置代理服务器和端口:IE->右上角 ->工具 ->Internet选项->连接->局域网(LAN)设置 ->配置代理IP和端口

浏览器访问  http://www.baidu.com/ 和 https://www.baidu.com/

实时查看nginx日志

tail -f /usr/local/nginx/logs/access.log

通过实时查看nginx的访问日志,可以看到Windows下设置代理IP和端口后,本地电脑访问的所有网页会通过代理服务器进行访问网页,实现了正向代理的功能,并且隐藏了用户自己真实的IP~

 

(2)客户端–Linux代理访问

Linux下也可以验证代理服务器是否能正常代理转发http和https请求~

curl http://www.baidu.com/ -v -x 127.0.0.1:80
curl https://www.baidu.com/ -v -x 127.0.0.1:443

nginx正向代理转发https成功。

 


三、反向代理

3.1 什么是反向代理?

   先来一张图了解下~

            

 

 

   相比于正向代理,反向代理的定义如下:

    反向代理,指的是浏览器/客户端并不知道自己要访问具体哪台目标服务器,只知道去访问代理服务器 ,代理服务器再通过反向代理 +负载均衡实现请求分发到应用服务器的一种代理服务。
  反向代理服务的特点是代理服务器 代理的对象是应用服务器,也就是对于浏览器/客户端 来说应用服务器是隐藏的。

 

3.2 nginx实现反向代理

(1)修改nginx配置

修改nginx配置vi /usr/local/nginx/conf/nginx.conf 在http模块中配置如下:

nginx反向代理都是结合负载均衡来实现的,这里先直接提供反向代理+负载均衡的配置,负载均衡后一章节介绍~

#反向代理+负载均衡
upstream reverseProxyServer{
    #负载均衡应用服务器A: 权重为10,10s内连接请求失败2次,nginx在10s内认为server是不可用的,将不在发送请求给这台服务器
    server 应用服务器A的IP:8080 weight=10 max_fails=2 fail_timeout=10s; 
    #负载均衡应用服务器B: 代理服务器权重为5,10s内连接请求失败2次,nginx在10s内认为server是不可用的,将不在发送请求给这台服务器
    server 应用服务器B的IP:8080 weight=5 fail_timeout=10s max_fails=2;
    #负载均衡应用服务器C: 代理服务器权重为5,10s内连接请求失败2次,nginx在10s内认为server是不可用的,将不在发送请求给这台服务器
    server 应用服务器C的IP:8080 weight=5 fail_timeout=10s max_fails=2;
}

server {
    #监听80端口,http默认端口80
    listen 80;
 
    #服务器IP或域名 
    server_name  localhost;
 
    #反向代理请求路径中含有/appname的所有请求到upstream定义的对应反向代理模块 
    location /appname { 
        proxy_pass http://reverseProxyServer; 
    } 
}

 

(2)检查和刷新nginx配置

/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s reload

 

(3)浏览器访问

代理服务器部署了tomcat应用,访问tomcat静态页面验证一波~

http://代理服务器IP:8080/appname/ReverseProxy1.html

 

 

四、负载均衡

4.1 什么是负载均衡?

再来看下前面介绍反向代理的这张图~

可以看到负载均衡(Load Balance)的主要作用是采用了负载均衡算法将请求分发到集群模式中的应用服务器上,这样即使某个后台应用服务器挂了,其他应用服务器还可以正常接收请求,实现了高可用,并且集群模式模式下的应用服务器支持纵向扩展,可以应对业务快速增长带来的高并发应用场景~

 

4.2 负载均衡算法有哪些?

负载均衡算法常用的有轮询、权重和ip_hash算法,默认是轮询算法~

(1)基于轮询的算法

原理是每一个请求按时间顺序逐一被分发到不同的应用服务器,如果接收请求的应用服务器挂了,并且请求超过最大失败次数max_fails(1次),则在失效时间fail_timeout(10秒)内不会再转发请求到该节点~

upstream defaultReverseProxyServer{
    server 192.168.0.1:8080; 
    server 192.168.0.2:8080; 
}

 

(2)基于权重的算法

原理是每一个请求按权重被分发到不同的应用服务器,同样,如果接收请求的应用服务器挂了,并且请求超过最大失败次数max_fails(默认1次或可设置N次),则在失效时间fail_timeout(默认10秒,可设置N秒)内,不会再转发请求到该节点~

upstream weightReverseProxyServer{
    server 192.168.0.1:8080 weight=10 max_fails=2 fail_timeout=5s;
    server 192.168.0.2:8080 weight=5 max_fails=2 fail_timeout=5s;
}


(3)基于ip_hash的算法

 原理是每一个请求按用户访问IP的哈希结果分配,如果请求来自同一个用户IP则固定这台IP访问一台应用服务器,该算法可以有效解决动态网页中存在的session共享问题。

upstream ipHashReverseProxyServer{
    ip_hash;
    server 192.168.0.1:8080;
    server 192.168.0.2:8080;
}

一般使用的是基于权重的算法,因为现在很多情况下都是集群部署,而且集群下的各个服务器资源大多都是不均匀的,资源高的则分配权重高一些,资源低的则分配权重低一些,这种情况使用基于权重的负载均衡算法,可以更高效的利用资源和提高并发处理能力~

 

 

 

五、Nginx的核心配置

5.1 Nginx的Master-Worker模式

nginx进程

启动Nginx后,其实就是在80端口启动了Socket服务进行监听,如图所示,Nginx涉及Master进程和Worker进程。

Master-Worker模式

nginx.conf

Master进程的作用是?

读取并验证配置文件nginx.conf;管理worker进程;

Worker进程的作用是?

每一个Worker进程都维护一个线程(避免线程切换),处理连接和请求;注意Worker进程的个数由配置文件决定,一般和CPU个数相关(有利于进程切换),配置几个就有几个Worker进程。

 

思考:Nginx如何做到热部署?

所谓热部署,就是配置文件nginx.conf修改后,不需要stop Nginx,不需要中断请求,就能让配置文件生效!(nginx -s reload 重新加载/nginx -t检查配置/nginx -s stop)

通过上文我们已经知道worker进程负责处理具体的请求,那么如果想达到热部署的效果,可以想象:

方案一:

修改配置文件nginx.conf后,主进程master负责推送给woker进程更新配置信息,woker进程收到信息后,更新进程内部的线程信息。(有点valatile的味道)

方案二:

修改配置文件nginx.conf后,重新生成新的worker进程,当然会以新的配置进行处理请求,而且新的请求必须都交给新的worker进程,至于老的worker进程,等把那些以前的请求处理完毕后,kill掉即可。

Nginx采用的就是方案二来达到热部署的!

 

思考:Nginx如何做到高并发下的高效处理?

上文已经提及Nginx的worker进程个数与CPU绑定、worker进程内部包含一个线程高效回环处理请求,这的确有助于效率,但这是不够的。

作为专业的程序员,我们可以开一下脑洞:BIO/NIO/AIO、异步/同步、阻塞/非阻塞...

要同时处理那么多的请求,要知道,有的请求需要发生IO,可能需要很长时间,如果等着它,就会拖慢worker的处理速度。

Nginx采用了Linux的epoll模型,epoll模型基于事件驱动机制,它可以监控多个事件是否准备完毕,如果OK,那么放入epoll队列中,这个过程是异步的。worker只需要从epoll队列循环处理即可。

 

思考:Nginx挂了怎么办?

Nginx既然作为入口网关,很重要,如果出现单点问题,显然是不可接受的。

答案是:Keepalived+Nginx实现高可用。

Keepalived是一个高可用解决方案,主要是用来防止服务器单点发生故障,可以通过和Nginx配合来实现Web服务的高可用。(其实,Keepalived不仅仅可以和Nginx配合,还可以和很多其他服务配合)

Keepalived+Nginx实现高可用的思路:

第一:请求不要直接打到Nginx上,应该先通过Keepalived(这就是所谓虚拟IP,VIP)

第二:Keepalived应该能监控Nginx的生命状态(提供一个用户自定义的脚本,定期检查Nginx进程状态,进行权重变化,,从而实现Nginx故障切换)

Keepalived+Nginx

 

5.2 我们的主战场:nginx.conf配置

很多时候,在开发、测试环境下,我们都得自己去配置Nginx,就是去配置nginx.conf。

nginx.conf是典型的分段配置文件,下面我们来分析下。

 

5.2.1 虚拟主机

                          http的server段

 

                                           访问结果

其实这是把Nginx作为web server来处理静态资源。

第一:location可以进行正则匹配,应该注意正则的几种形式以及优先级。(这里不展开)

第二:Nginx能够提高速度的其中一个特性就是:动静分离,就是把静态资源放到Nginx上,由Nginx管理,动态请求转发给后端。

第三:我们可以在Nginx下把静态资源、日志文件归属到不同域名下(也即是目录),这样方便管理维护。

第四:Nginx可以进行IP访问控制,有些电商平台,就可以在Nginx这一层,做一下处理,内置一个黑名单模块,那么就不必等请求通过Nginx达到后端在进行拦截,而是直接在Nginx这一层就处理掉。

 

5.2.2 反向代理【proxy_pass】

所谓反向代理,很简单,其实就是在location这一段配置中的root替换成proxy_pass即可。root说明是静态资源,可以由Nginx进行返回;而proxy_pass说明是动态请求,需要进行转发,比如代理到Tomcat上。

反向代理,上面已经说了,过程是透明的,比如说request -> Nginx -> Tomcat,那么对于Tomcat而言,请求的IP地址就是Nginx的地址,而非真实的request地址,这一点需要注意。不过好在Nginx不仅仅可以反向代理请求,还可以由用户自定义设置HTTP HEADER。

 

 

 ----------------------------------

反向代理是什么?

 
  • 代理: 其实就是一个中介,A和B本来可以直连,中间插入一个C,C就是中介。

  • 正向代理: 正向代理类似一个跳板机代理访问外部资源

    • 比如我们国内访问谷歌,直接访问访问不到,我们可以通过一个正向代理服务器,请求发到代理服务器,代理服务器能够访问谷歌,这样由代理去谷歌取到返回数据,再返回给我们,这样我们就能访问谷歌了。

    • 正向代理的用途:

      (1)突破自身IP访问限制,访问原来无法访问的资源,如google

      ​ (2) 可以做缓存,加速访问资源。通常代理服务器都设置一个较大的硬盘缓冲区,会将部分请求的响应保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。

        (3)对客户端访问授权,上网进行认证

        (4)代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息

  • 反向代理:反向代理(Reverse Proxy)实际运行方式是指以代理服务器接受internet上的连接请求,然后将请求转发内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。对于常用的场景,就是Web开发中用到的负载均衡服务器。

    • 反向代理的作用

      (1)使用反向代理,可以对客户端隐藏服务器的IP地址 。保证内网的安全,阻止web攻击,大型网站通常将反向代理作为公网访问地址,Web服务器是内网。反向代理服务器可以作为应用层防火墙,为网站提供对基于Web的攻击行为(例如DoS/DDoS)的防护,更容易排查恶意软件等。还可以为后端服务器统一提供加密和SSL加速(如SSL终端代理),提供HTTP访问认证等。

      (2)负载均衡,通过反向代理服务器来优化网站的负载。反向代理服务器可以做负载均衡,根据所有真实服务器的负载情况,将客户端请求分发到不同的真实服务器上

      (3)提高访问速度:反向代理服务器可以对于静态内容及短时间内有大量访问请求的动态内容提供缓存服务,提高访问速度。

  • 正向代理中,proxy和client同属一个LAN,对server透明;
    反向代理中,proxy和server同属一个LAN,对client透明。
    实际上proxy在两种代理中做的事都是代为收发请求和响应,不过从结构上来看正好左右互换了下,所以把后出现的那种代理方式叫成了反向代理.

-----------------------------------

 

 

5.2.3 负载均衡【upstream】

上面的反向代理中,我们通过proxy_pass来指定Tomcat的地址,很显然我们只能指定一台Tomcat地址,那么我们如果想指定多台来达到负载均衡呢?

第一,通过upstream来定义一组Tomcat,并指定负载策略(IPHASH、加权论调、最少连接),健康检查策略(Nginx可以监控这一组Tomcat的状态)等。

第二,将proxy_pass替换成upstream指定的值即可。

负载均衡可能带来的问题?

负载均衡所带来的明显的问题是,一个请求,可以到A server,也可以到B server,这完全不受我们的控制,当然这也不是什么问题,只是我们得注意的是:用户状态的保存问题,如Session会话信息,不能在保存到服务器上。

 

5.2.4 缓存

缓存,是Nginx提供的,可以加快访问速度的机制,说白了,在配置上就是一个开启,同时指定目录,让缓存可以存储到磁盘上。具体配置,大家可以参考Nginx官方文档,这里就不在展开了。

          

 

````````

`

 

posted @ 2023-01-29 18:47  亟待!  阅读(175)  评论(0)    收藏  举报
……