Nginx 基本概念(反向代理、动静分离、负载均衡、高可用)、安装配置(JDK\Tomcat\Nginx\Keepalived)、配置实例效果

这篇文章将先阐述Nginx相关概念,然后介绍Nginx相关环境的安装配置过程(包括Linux下JDK\Tomcat的安装,都是自己动手操作的记录),及反向代理、负载均衡、动静分离、高可用的配置及测试过程,最后总结下Nginx的工作原理。 

一、Nginx中的核心概念

1.1 Nginx是啥,能做啥?

Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

代理服务器是介于客户端和Web服务器之间的另一台服务器,有了它之后,浏览器不是直接到Web服务器去取回网页而是向代理服务器发出请求,信号会先送到代理服务器,由代理服务器来取回浏览器所需要的信息并传送给你的浏览器。

Nginx的特点是:

  •  跨平台:Nginx 可以在大多数 Unix like OS编译运行,而且也有Windows的移植版本。
  • 非阻塞、高并发连接:数据复制时,磁盘I/O的第一阶段是非阻塞的。官方测试能够支撑5万并发连接,在实际生产环境中跑到2~3万并发连接数。
  • master/worker结构:一个master进程,生成一个或多个worker进程。
  • 内存消耗小:处理大并发的请求内存消耗非常小。在3万并发连接下,开启的10个Nginx 进程才消耗150M内存(15M*10=150M)
  • 成本低廉:Nginx为开源软件,可以免费使用。而购买F5 BIG-IP、NetScaler等硬件负载均衡交换机则需要十多万至几十万人民币
  • 内置的健康检查功能:如果 Nginx Proxy 后端的某台 Web 服务器宕机了,不会影响前端访问。
  • 节省带宽:支持 GZIP 压缩,可以添加浏览器本地缓存的 Header 头。
  • 稳定性高:用于反向代理,宕机的概率微乎其微。
  • 支持热部署:一旦运行几乎不用停下,修改配置后不用重启即可生效。

使用Nginx我们可以实现:

  • 反向代理
  • 负载均衡
  • 动静分离
  • 高可用

 1.2 反向代理

简单说下正向代理,它是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端配置了代理服务器后才能使用正向代理。可以看成客户端和代理服务器是一体的,真正的目标服务器并不知道具体是哪个客户端请求了自己的服务,因为都是经过代理服务器过来的,正向代理过程如下:

正向代理

反向代理可以看成代理服务器和目标服务器是一体的,客户端不知道具体是哪个目标服务器返回的响应,反向代理过程如下:

反向代理

反向代理对用户则是不可知的,比如我们访问百度网站,百度的代理服务器对外的域名为 https://www.baidu.com 。具体内部的服务器节点我们不知道,现实中我们通过访问百度的代理服务器后,代理服务器给我们转发请求到他们N多的服务器节点中的一个给我们进行搜索后将结果返回。

反向代理的作用:

  • 隐藏服务器真实IP:使用反向代理,暴露的是代理服务器地址,可以对客户端隐藏目标服务器的IP地址,提高安全性。
  • 提供安全保障:反向代理服务器可以作为应用层防火墙,为网站提供对基于Web的攻击行为(例如DoS/DDoS)的防护,更容易排查恶意软件等。还可以为后端服务器统一提供加密和SSL加速(如SSL终端代理),提供HTTP访问认证等。
  • 负载均衡:反向代理服务器可以做负载均衡,根据所有目标服务器的负载情况,将客户端请求分发到不同的真实服务器上。

总结:

  • 正向代理就是代理客户端,服务器不知道实际发出请求的客户端是哪一个;
  •  反向代理就是代理服务端,客户端不知道实际提供服务的服务端是哪一个。 

1.3 负载均衡

负载均衡,用来在多个服务器(集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。

怎么理解?先从没有负载均衡说起,客户端发送大量请求到服务器(并发数较大时),单个服务器的性能就成了瓶颈,服务器可能扛不住这么多的请求而宕机。解决的办法可能就是直接增加物理资源(纵向扩展),提升CPU/内存/网络带宽/硬盘等,问题虽然能够得到缓解但是代价高昂,甚至在一些秒杀或直播场景中只是增加物力资源也是不能解决问题的,单点故障在所难免。

有了负载均衡就好办了, 负载均衡是将负载(工作任务,访问请求)进行平衡、分摊到多个操作单元(服务器,组件)上进行执行。是解决高性能,单点故障(高可用),扩展性(水平伸缩)的终极解决方案。

比如:超市买东西结账排队时,要是大家都可着一个收银台排队,那肯定会排很长时间,收银员也累得不轻;但如果把排队的人平均分散到多个收银台,排队时间将大幅减少,收银员的压力也会减少很多。同样的道理,大量请求到来时,若是能通过代理服务器将请求分发到多个目标服务器,那响应效率就会提高很多,压力分摊到多个服务器后,每台服务器的工作量也不大,因此对每台服务器的物理资源要求就不用太高,减低成本。比如有一万个并发请求过来,负载均衡后就会分摊到多个服务器,如下:

负载均衡过程

1.3.1 负载均衡常见策略 

上面的请求分配,若各服务器的物理资源一致情况下,理想中应该平均分配请求树。实际中根据需要,可能需要制定不同的分配策略,Nginx给我们提供了4种负载均衡策略:

  1. 轮询(默认):每个请求按时间顺序逐一分配到不同的服务器,某台服务器宕机就会被自动剔除,为默认策略;
  2. weight权重:设置每台服务器的权重,weight值越大,被分配的请求越多,后端服务器资源不均时可用该策略;
  3. ip_hash:每次请求都会记录请求Ip的hash,固定的客户端可以访问固定的服务器,可以解决分布式session问题;
  4. fair公平:按后端各服务器响应时间来分配,响应时间快的优先分配。

1.4 动静分离

就是动态资源(jsp、ftl、thymeleaf)与静态资源(js、css、img)分开部署,分别访问。动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们则根据静态资源的特点将其做缓存操作,因为静态资源访问比较频繁,且tomcat本身处理静态效率不高,还会带来资源开销,定睛分离就能提高响应能力。

1.5 Nginx高可用集群

主要是多配置几个Nginx代理服务,防止只有一个Nginx服务时,这个唯一的Nginx服务宕机。即配置主Nginx代理服务器和丛Nginx代理服务器,若其中一个宕机另一个马上顶替上开始工作,多个Nginx服务则由统一的虚拟Ip访问,这时还要搭配Keepalived一起使用,才能实现多Nginx高可用部署。过程如下:

高可用

二、Nginx的安装

因为后面要分别配置Nginx的反向代理、负载均衡、动静分离、高可用并测试效果,这些需要一些其他环境,比如JDK\Tomcat等,因此这里顺便梳理下它们在Linux下的安装过程.

2.1 安装JDK

首先是下载对应的JDK,地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 

根据自己的Linux环境下载对应的JDK包,我用的华为云服务器,Linux 64位,下载的包是:jdk-8u251-linux-x64.tar.gz

下载好JDK之后,还要下载一个WinSCP软件,用来将JDK压缩包文件传输到华为云服务器,打开WinSCP,填写

登录后:

右边是远程服务器的文件目录,将JDK压缩包拖到右边对应的文件夹,我这里自己建了一个jdk文件夹:

然后执行tar -xzvf jdk-8u251-linux-x64.tar.gz 就会多出上面的解压包,然后就是配置Jdk的环境变量,环境变量文件位置在etc/profile,进入该路径执行vim etc/profile:

如上图,在profile文件最后添加:

export JAVA_HOME=/root/jdk/jdk1.8.0_251
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib
export PATH=$JAVA_HOME/bin:$PATH

修改好后执行:source  etc/profile,即使文件修改的环境变量生效。这时可以执行java -version命令,验证是否设置成功。

2.2 安装Tomcat

也是先下载tomcat的安装包,地址:https://tomcat.apache.org/download-90.cgi

我这里下载的是apache-tomcat-8.5.57.tar.gz 

与JDK安装一样,使用WinSCP进行传输后解压:

 可以进入Tomcat的conf目录通过server.xml文件修改下访问的端口号,这里我修改成了8086,然后进入bin目录执行startup.up脚本启动Tomcat。进入logs目录执行tail -f catalina.out命令,查看启动日志,出现下面的日志说明成功启动:

最后在浏览器输入华为云的弹性公网IP + :8086:

这里因为是华为云服务器,如果tomcat正常启动,但是访问不了,可能是安全组没有设置,可以设置安全组如下:

这时弹性公网Ip就可以ping通。

2.3 防火墙设置

上面如果安全组已经设置但还是访问不了,那就有可能端口防火墙没开,使用:

firewall-cmd --list-all

可以查看防火墙端口设置情况:

上面ports后面的就是已经开放的端口,如要想开放其他端口,执行:

sudo firewall-cmd --add-port=XXXX/tcp --permanent

最后加载更新这个防火墙配置即可:

firewall-cmd --reload

2.4 Nginx安装

安装Nginx前还要安装它的一些协作(依赖)软件,包含:

  1. pcre
  2. openssl
  3. zlib
  4. nginx

2.4.1 安装pcre

步骤:

1.下载pcre安装包:地址:https://zh.osdn.net/projects/sfnet_pcre/releases/ 找到后选择版本右键复制链接地址,wget下载到服务器(也可以下载后用winSCP传输到远程服务器),之后进行解压:

2.进入解压后的目录,执行./configure命令

3.执行make命令,最后执行make install。

输入pcre-config --version出现下面版本号说明安装成功:

2.4.3 安装zlib

  1. 下载zlib安装包,地址:http://www.zlib.net/,winSCP传输到远程服务器
  2. 解压tar -xvzf zlib-1.2.11.tar.gz
  3. cd zlib-1.2.11.tar.gz,执行./configure
  4. 执行make ,执行make install

2.4.4 安装openssl

  1. 下载zlib安装包,地址:http://www.openssl.org/source/openssl-1.0.2j.tar.gz,winSCP传输到远程服务器
  2. 解压tar -xvzf openssl-1.0.2j.tar.gz
  3. cd openssl-1.0.2j,执行./config --prefix=/root/local/openssl,再执行./config -t
  4. 执行make ,执行make install
  5. ldd /root/gefeng/openssl/bin/openssl 设置依赖文件目录
  6. openssl version -a 查看系统的OpenSSL版本信息

2.4.5 安装Nginx

  1. 下载zlib安装包,地址:http://nginx.org/en/download.html,winSCP传输到远程服务器
  2. 解压tar -xvzf nginx-1.10.3.tar.gz
  3. cd nginx-1.10.3.tar.gz,执行./configure
  4. 执行make ,执行make install
  5. 启动Nginx,上一步已经安装完成,在usr/local下多出nginx文件夹,进入后会有sbin目录,里面有个nginx脚本,执行启动
  6. 启动后,nginx默认是80端口,浏览器访问下出现如下则成功:

三、Nginx有一些常见命令

注意,操作这些命令时需要进入nginx目录中: 

  • 查看Nginx版本号:./nginx -v
  • 启动nginx :sbin目录执行nginx脚本
  • 停止nginx:nginx -s stop
  • 重新加载nginx:nginx -s reload

如修改了nginx的配置文件nginx.conf,就需要重新加载才能生效,注意不是重启nginx,只是重新加载配置文件

 

四、Nginx的配置文件

nginx的配置文件在/conf/nginx.conf中:

 完整的文件如下:


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

Nginx的配置文件由3部分组成:

1、全局块

配置文件开始到events之间的内容,主要是一些影响nginx服务器整体运行的指令,例如允许的work process数,进程PID存储路径,日志路径等。

2、events块

影响Nginx服务器和用户的网络连接,worker_connections = 1024;就代表每个work process支持的最大连接数是1024,这部分配置对nginx的性能影响很大,需要灵活配置。

3、http块

这边配置修改是最频繁的,尤其是包含的server配置块。

http块可以包含多个server块,每个server就相当于一个虚拟机,每个server还包含多个location。server块配置本虚拟机的IP和端口;location是对请求进行匹配,对特定的请求进行处理,地址指向、数据缓存和应答控制等也在这里配置。

五、Nginx反向代理配置实例 一

预期效果:通过域名跳转到特定地址,例如:输入www.666.com,跳转到tomcat主页,过程如下:

步骤:

(1)部署tomcat服务器,端口为8086,为了方便把Tomcat和Nginx部署在同一台服务器;

(2)修改nginx配置文件

(3)重启Nginx

 (4)修改本地hosts文件

因为以某个域名访问的时候,首先会在本地的hosts文件查找是否有这个域名与ip的映射配置,没有才会走dns域名解析,这里

需要配置域名的映射关系,打开hosts文件,路径C:\Windows\System32\drivers\etc,修改如下:

(5)测试,在浏览器输入www.666.com

总结以上流程:

www.666.com域名通过hosts文件与代理服务器的IP:124.70.206.90绑定,Nginx作为代理服务器,通过820端口监听tomcat服务。

六、Nginx反向代理配置实例 二

预期效果:根据访问路径不同跳转到不同端口的服务中。

比如,我们设置nginx的端口为6666;

访问124.70.206.90:6666/static 访问8086的tomcat

访问124.70.206.90:6666/dynamic 访问8087的tomcat

步骤:

(1)启动两个Tmocat服务,端口分别是8086和8087;

(2)为了更直观,先分别在两个Tomcat服务中创建static 和 dynamic文件夹及相应的页面 

 

(3)在nginx.conf中配置方向代理原来的不动,新增一个server ,修改后更新配置或重启Nginx

(PS:这里 ~ 是匹配符号,表示与后面的路径匹配且区分大小写;~*则表示不区分大小写,一般用前一种比较精确) 

(4)测试效果

七、负载均衡配置实例

预期效果:浏览器输入同一个地址,但是后端服务器是切换的,及负载均衡,请求平均分配到8086和8087对应的服务

步骤:

(1)启动两个Tmocat服务,端口分别是8086和8087;

(2)在两个tomcat中都创建一个dynamic文件夹及对应的test.html

(3)在nginx.conf中配置负载均衡,先配置一个默认的策略即轮询策略

(4)重启或更新Nginx后测试轮询效果

 

因为是轮询,所以每次刷新两个tomcat是交替响应的。

其他的策略配置如下:

效果就不演示了。

八、动静分离配置实例 

预期效果:不同的路径访问不同的资源

 步骤:

(1)准备动态和静态资源(要放到根目录下)

(2)配置Nginx

(3)访问效果

九、高可用配置实例 

预期效果:配置两个Nginx服务,一个停下另一个补位,保证服务不间断,主要借助Keepalived和Nginx联合使用进行实现。

步骤:

(1)需要两台服务器(我这边太穷只有一个服务器,这个环节就不演示了,列出主要步骤)

(2)在两台服务器上都安装Nginx

(3)在两台服务器上都安装Keepalived

  1. wget http://www.keepalived.org/software/keepalived-2.0.7.tar.gz
  2. 解压keepalived-2.0.7.tar.gz
  3. cd keepalived-2.0.7
  4. ./configure
  5. make && make install

(4)配置keepalived

十、Nginx原理

查看Nginx进程是会发现它有两个进程:

一个是worker,一个是master。

工作原理我们可以画个总体的图来说明:

(1)

在nginx启动后,会有一个master进程和多个worker进程,master进程主要用来管理worker进程,包括:接受信号,将信号分发给worker进程,监听worker进程工作状态,当worker进程退出时(非正常),启动新的worker进程。基本的网络事件会交给worker进程处理。多个worker进程之间是对等的,他们同等竞争(争抢)来自客户端的请求,各进程互相之间是独立的 。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。一个worker进程出现问题不会影响别的worker。

(2)

当master接收到重新加载的信号会怎么处理(./nginx -s reload)?,master会重新加载配置文件,然后启动新的进程,使用的新的worker进程来接受请求,并告诉老的worker进程他们可以退休了,老的worker进程将不会接受新的,老的worker进程处理完手中正在处理的请求就会退出。
(3)

worker进程是如何处理用户的请求呢?

首先master会根据配置文件生成一个监听相应端口的socket,然后再根据配置(配置文件中,全局块下work process参数)创建相应数量的worker进程,这样每个worker就可以接受从socket过来的消息(其实这个时候应该是每一个worker都有一个socket,只是这些socket监听的地址是一样的)。当一个连接过来的时候,每一个worker都能接收到通知,所有worker相互争抢,但是只有一个worker能和这个连接建立关系,其他的worker都会连接失败。当一个worker进程在accept这个连接之后,就开始读取请求,解析请求,处理请求,产生数据后,再返回给客户端,最后才断开连接。为了解决争抢问题,nginx提供一个共享锁accept_mutex,有了这个共享锁后,就会只有一个worker能接收到这个客户端请求,而不是所有worker都能接收到。

补充一:worker进程的个数设置多少最合适?

worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致。原因是Nginx和Redis类似,都是采用IO多路复用机制,每个worker就是一个进程,和CPU核树一致既能保证性能又能不浪费资源,多了会造成CPU频繁切换上下文损耗,少了则浪费CPU资源。

补充二:每个worker的连接数是多少?

在配置文件even块中有worker_connections 参数,它就代表了每个worker进程独立的连接池的最大容量。下面代表每个worker最多可以支持1024个连接:

events {
    worker_connections  1024;
}

补充三:每个Nginx最大连接数是多少?

一个Nginx能建立的最大连接数 = work_process * worker_connections。

补充四:每个请求将占worker几个连接?

2个或4个,请求静态资源占2个连接,请求动态资源4个 。

补充五:一个Nginx支持的并发请求量怎么算?

若果是普通静态资源访问,每次请求只占2个连接,支持的并发数就是 work_process * worker_connections/2

若果是动态资源访问,每次请求占4个连接,支持的并发数就是 work_process * worker_connections/4

猜你喜欢

转载自blog.csdn.net/weixin_41231928/article/details/107214576