高可用并发解决方案Nginx+keepalived

  在这个互联网飞速发展的时代,人们已经离不开网络,其中网购最为常见。在家网购,上班路上网购,吃饭也购物,下班还网购,2019年双十一天猫支付峰值达到了54.4万笔/秒。 热点网站中频繁出现的大量并发如何去解决?
  那么在此篇博文中,将介绍目前处理并发能力非常强悍的开源软件nginx快速入门及使用,介绍nginx+ tomcat集群处理并发解决方案,带大家认识虚拟路由,了解虛拟路由的工作流程并安装keepalived,实现nginx+ keepalived主备配置,达到nginx高可用的效果。

Nginx介绍 

  Nginx (engine x) 是一个高性能的轻量级HTTP反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。由俄罗斯人伊戈尔·赛索耶夫开发。其将源代码以类BSD许可证的形式发布。
  Nginx处理并发能力强(因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗)且占有内存少所以很受欢迎。中国大陆使用nginx网站用户有:百度、京东新浪网易腾讯淘宝等。

Nginx下载和安装

  Nginx官网:http://nginx.org

  Nginx目前已经更新到了1.17.10版本,我们可以直接到官网下载,由于外面服务器大多都使用linux环境作为服务器,所以我们也弄一台linux环境的虚拟机。
  虚拟机我们前面已经装好了,IP: 192.168.254.129, 由于nginx是用C语言写的而且还支持地址栏重写等功能,所以我们需要安装一下相关的依赖包。

yum install gcc-c++
yum install -y pcre-devel
yum install -y zlib zlib-devel
yum install -y openssl-devel

安装流程如下:
  1.我们把刚才从官网下载的Nginx,文件上传到centos的/us/local/server目录去。
  2.紧接着我们在server目录下创建nginx目录把压缩文件解压,进入解压的文件夹。
  3.首先配置nginx安装信息./configure --prefix=nginx安装路径
  4.执行编译和安装make && make install

Nginx常用命令 

nginx常用命令
  nginx -c /usr/1oca1/server/nginx/conf/nginx.conf 启动nginx(windows下start nginx);
  nginx -s quit 停止ngix
  nginx -s reload 重新载入nginx(当配置信息发生修改时)
  nginx -v 查看版本
  nginx -t 查看nginx的配置文件的目录
  nginx -h 查看帮助信息

Nginx常用命令

主模块

基本指令

  daemon

  语法:daemon on | off

  默认值: on

  是否以守护进程的方式运行nginx,守护进程(daemon)是一类在后台运行的特殊进程,关闭守护进程执行的方式可以让我们方便调试nginx

  master_process

  语法: on | off 

  默认值: on

  是否以master/worker方式进行工作,在实际的环境中nginx是以一个master进程管理多个worker进程的方式运行的,关闭后nginx就不会fork出worker子进程来处理请求,而是用master进程自身来处理请求worker_processes number;默认1,在master/worker运行方式 下worker进程的数目,一般情况下用户要配置与CPU内核数相等的worker进程。 

  error_log

  语法: error_log file [ debug | info | notice | warn | error | crit ]

  include

  语法: include file |*

  默认值: none

  可以包含一些其他的配置文件来完成想要的功能。

  0.4.4版本以后,include指令已经能够支持文件通配符:

include vhosts/*.conf; 

  pid

  语法: pid file

  默认值:编译时指定

pid /var/1og/nginx.pid;

  指定pid文件,可以使用kill命令来发送相关信号,例如你如果想重新读取配置文件,则可以使用:

kill -HUP `cat /var/1og/nginx.pid`

  user

  语法: user user [group]

  默认值: nobody nobody

  如果主进程以root运行,Nginx将 会调用setuid()/setgid()来设置用户/组,如果没有指定组,那么将使用与用户名相同的组,默认情况下会使用nobody用户与nobody组(或者nogroup) , 或者在编译时指定的-user=USER和-group=GROUP的值。

  worker_ processes

  语法: worker. processes number

  默认值: 1

  由于以下几点原因,Nginx可能需要运行不止一个进程

  .使用了SMP (对称多处理技术)。

  .当服务器在磁盘I/O出现瓶颈时为了减少响应时间。

  .当使用selec()/poll()限制了每个进程的最大连接数时。

  在事件模块这一章中我们将使用worker_processes和worker_connections来计算理论最大连接数(max _lients) :

  max_ clients = worker_processes * worker_connections

Nginx处理HTTP的核心功能模块

 基本指令
  alias

  语法: alias file-path|directory-path;

  默认值: no

  使用字段: location

  这个指令指定一个路径使用某个某个, 注意它可能类似于root,但是document root没有改变,请求只是使用了别名目录的文件。

location /i/ {
    alias /spoo1/w3/images/; 
}

  上个例子中,请求/top.gif将返回这个文件: */spool/w3/images/top.gif.
  Alias同样可以用于带正则表达式的location,如:

location ~ ^/download/(.*)$ {
    alias /home/website/files/$1;
}

  keepalive_timeout

  语法: keepalive_timeout [ time ][ time ]

  默认值: keepalive_timeout 75

  使用字段: http, server, location

  参数的第一个值指定了客户端与服务器长连接的超时时间,超过这个时间,服务器将关闭连接。

  参数的第二个值(可选)指定了应答头中Keep-Alive: timeout= time的time值,这个值可以使一些浏览器知道什么时候关闭连接,以便服务器不用重复关闭,如果不指定这个参数, nginx不会在应答头中发送Keep-Alive信息。(但这并不是指怎样将一个连接“Keep-Alive")

   参数的这两个值可以不相同

  下面列出了一些服务 器如何处理包含Keep-Alive的应答头:

  .MSIE和Opera将Keep-Alive: timeout=N头忽略。 

  .MSIE保持一个连接大约60-65秒, 然后发送一个TCP RST.

  .Opera将一直保持一个连接处于活动状态。

  .Mozilla将一个连接在N的基础 上增加大约1-10秒。

  .Konqueror保持一个连接大约N秒。

  listen

  语法(0.7.x): listen address:port [ default [ backlog=num I rovbuf=size | sndbuf= size I accept fitr-fiter I deferred I bind I ssI]]

  语法(0.8.x): listen address:port [ default server [ backlog=num I rcvbuf=size I sndbuf=size | accept. filter-filter I deferred | bind |ssl]]

  默认值: listen 80

  使用字段: server

  listen指令指定了server{...}字段中可以被访问到的ip地址及端口号,可以只指定一个ip,一个端口,或者一个可解析的服务器名。

listen 127.0.0.1:8000;
listen 127.0.0.1;
listen 8000;
listen *:8000;
listen localhost:8000;

  location
  语法: location [=|~|~*|^~|@]/uri/{..}
  默认值: no
  使用字段: server

  这个参数根据URI的不同需求来进行配置,可以使用字符串与正则表达式匹配,如果要使用正则表达式,你必须指定下
列前缀:
  1、~*不区分大小写。
  2、~区分大小写。

location =/ {
    #只匹配/的查询。
    [ configuration A ]
}
location / {
    #匹配任何以/开始的查询,但是正则表达式与些较长的字符串将被首先匹配。
    [ configuration B ]
}
location ^~ /images/ {
    #匹配任何以/images/开始的查询并且停止搜索,不检查正则表达式。
    [ configuration C ]
}
location ~* \.(gif|jpg|jpeg)$ {
    #匹配任何以gif, jpg, or jpeg结尾的文件,但是所有/images/ 目录的请求将在Configuration c中处理。
    [ configuration D ]
}

  resolver_timeout
  语法: resolver. timeout time
  默认值: 30s
  使用字段: http, server, location
  解析超时时间。如:
  resolver_timeout 5s;

  root
  语法: root path
  默认值: root html
  使用字段: http, server, location ,location中的if字段
  请求到达后的文件根目录。

  下例中:

location /i/ {
    root /spool/w3;
}

  如果请求"/i/top.gif"文件,nginx将转到"/spool/w3/i/top.gif"文件。 你可以在参数中使用变量。
注意:在请求中root会添加这个location到它的值后面, 即/i/top.gif 并不会请求"/spool/w3/top.gif"文件,如果要实现
上述类似于apache alias的功能,可以使用alias指令。

  server

  语法: server {...}

  默认值: no

  使用字段: http

  server字段包含虚拟主机的配置。

  没有明确的机制来分开基于域名(请求中的主机头)和基于IP的虚拟主机。

  可以通过listen指令来指定必须连接到这个server块的所有地址和端口,并且在server_name指令中可以指定所有的域名。

  server_name

  语法: server_name name [...]

  server_name

  语法: server _name name [...]

  默认值: server_name hostname

  使用字段: server

  这个指令有两个作用:

  .将HTTP请求的主机头与在nginx配置文件中的server{...}字段中指定的参数进行匹配,并且找出第一个匹配结果。 这就是如何定义虚拟主机的方法,域名遵循下述优先级规则:

  1、完整匹配的名称。

  2、名称开始于一个文件通配符: *.example.com。

  3、名称结束于一个文件通配符: www.example.*。

  4、使用正则表达式的名称。

  如果没有匹配的结果,nginx配置文件将安装以 下优先级使用[#server server {... }]字段:

  1、listen指令 被标记为default的server字段。

  2、第一个出现listen (或者默认的listen 80)的server字段。

HTTP负载均衡模块

  摘要

  这个模块为后端的服务器提供简单的负载均衡(轮询(round-robin) 和连接IP (lient IP) )
  如下例:

upstream backend {
    server 192.168.254.130:8080 weight=5 ;
    server 192.168.254.129:8080 ;
}

server {
    location / {
        proxy_pass http://backend;
  } }

  指令
  ip_hash
  语法: ip_hash
  默认值: none
  使用字段: upstream

  这个指令将基于客户端连接的IP地址来分发请求。

  哈希的关键字是客户端的C类网络地址,这个功能将保证这个客户端请求总是被转发到一台服务器上, 但是如果这台服务器不可用,那么请求将转发到另外的服务器上,这将保证某个客户端有很大概率总是连接到一台服务器。

  无法将权重(weight) 与ip_hash联合使用来分发连接。如果有某台服务器不可用,你必须标记其为"down",如下例

upstream backend {
    ip_hash; 
    server backend1.example.com;
    server backend2.example.com; 
    server backend3.example.com down;
    server backend4.example.com;
}

  server
  语法: server name [parameters]
  默认值: none
  使用字段: upstream

  指定后端服务器的名称和一些参数,可以使用域名,IP, 端口,或者unix socket.如果指定为域名,则首先将其解析为IP。

  weight = NUMBER -设置服务器权重,默认为1.

  max_ fails = NUMBER 在一定时间内 (这 个时间在fail timeout参数中设置)检查这个服务器是否可用时产生的最多失
败请求数,默认为1,将其设置为0可以关闭检查,这些错误在proxy_next_upstream或fastcgi_next_upstream (404错误
不会使max_ fails增加)中定义。

  fail_timeout = TIME 在这个时间内产生了max_ fails所设置大小的失败尝试连接请求后这个服务器可能不可用,同样它
指定了服务器不可用的时间(在下一次尝试连接请求发起之前), 默认为10秒,fail _timeout与前端响应时间没有直接
关系,不过可以使用proxy_ connect _timeout和proxy_read_timeout来控制。

  down -标记服务器处于离线状态,通常和ip_hash一起使用。

  backup - (0.6.7或更高如果所有的非备份服务器都宕机或繁忙,则使用本服务器(无法和ip_hash指令搭配使用)。

  示例配置

upstream backend {
    server backtynd1.example.com weight=5; 
    server 127.8.0.1:8080 max_fails=3 fail_timeout=30s;
    server unix: /tmp/backend3 ;
}

  注意:如果你只使用一台上游服务器,nginx将设置一 个内置变量为1, 即max_fails和fail_timeout参数不会被处理。
  结果:如果nginx不能连接到上游,请求将丢失。
  解决:使用多台上游服务器。

  upstream
  语法: upstream name {.. }
  默认值: none
  使用字段: http
  这个字段设置一群服务器, 可以将这个字段放在proxy, passofastcgi pass指令中作为一个单独的实体,它们可以是监听不同端口的服务器,并且也可以是同时监听TCP和Unix socket的服务器。
  服务器可以指定不同的权重,默认为1。

  示例配置

upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;
}

 HTTP访问控制模块(HTTP Access)

  摘要  

  这个模块提供简单的基于主机的访问控制。

  ngx_http_access_module这个模块可以详细的检查客户端P,并且按顺序执行第一条匹配的规则。

  如下例:

location / {
    deny 192.168.254.128;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    denyall; 
}

  上面的例子中仅允许192.168.1.0/24和10.1.1.0/16网络段访问,但192.168.1.1是个例外。

  如果要实施很多复杂的规则,那么最好使用GeolP module模块。

  指令

  allow

  语法: alow [ address I CIDR I all]

  使用字段: http, server, location, limit_except

  指令指定了允许访问的IP或网络段。

  deny

  语法: deny [ address ICIDR I all]

  默认值: no

  使用字段: http, server, location, limit_except

  指令指定了拒绝访问的IP或网络段。

  提示和技巧

  HttpAccess模块可以和error_page指令搭配使用来重定向一个未经验证的访问请求。

location / {
    deny 192.168.1.1;
    allow 192.168.1.0/24;
    allow 10.1.1.0/16;
    denyall;
}

  Nginx + Tomcat实现集群

  当我们网站并发是高的时候,一台tomcat无法承受大量并发,可以考虑Nginx+ Tomcat集群来实现。咱们这就做一个集群演示。

  配置说明

  Nginx搭建图片服务器

  针对任何站点,几乎都要访问图片,而一个网页里面几乎有好些张图片,这时候会占据大量tomcat连接,造成大量并发,我们可以通过Nginx配置直接访问硬盘里的图片,绕开tomcat。

  我们在根路径/创建一个images目录,然后在images目录放入一些图片, 再在nginx的nginx.conf配置里配置一个虚拟机来访问。

server {
    listen 80;
    server_name localhost ;
    #所有带有images访问的路径直接/images目录下查找
    location / {
    root /images;
}

  keepalived+ nginx集群解决单点故障

  再牛逼的软件我们也不能保证它一定不挂,为了防止上Nginx挂了导致整个服务无法使用的灾难发生,我们这里可以考虑使用Keepalived+Nginx集群实现高可用。

  keepalived介绍

  Keepalived是一种高性能的服务 器高可用或热备解决方案,Keepalived 可以用来防止服务器单点故障的发生,通过配合Nginx可以实现web前端服务的高可用。

  Keepalived以VRRP协议为实现基础,用VRRP协议来实现高可用性(HA)。VRRP(Virtual Router Redundancy Protocol)协议是用于实现路由器冗余的协议,VRRP 协议将两台或多台路由器设备虚拟成一个设备, 对外提供虚拟路由器IP(一个或多个,而在路由器组内部,如果实际拥有这个对外IP的路由器如果工作正常的话就是MASTER,或者是通过算法选举产生,MASTER实现针对虚拟路由器IP的各种网络功能,如ARP请求,ICMP, 以及数据的转发等;其他设备不拥有该虚拟IP,状态是BACKUP,除了接收MASTER的VRRP状态通告信息外,不执行对外的网络功能。当主机失效时,BACKUP 将接管原先MASTER的网络功能。
VRRP协议使用多播数据来传输VRRP数据,VRRP 数据使用特殊的虚拟源MAC地址发送数据而不是自身网卡的MAC地址,VRRP 运行时只有MASTER路由器定时发送VRRP通告信息,表示MASTER工作正常以及虚拟路由器IP(组),BACKUP 只接收VRRP数据,不发送数据,如果-定时间内没有接收到MASTER的通告信息,各BACKUP将宣告自己成为MASTER,发送通告信息,重新进行MASTER选举状态。

  方案介绍

     VIP     IP   主机名    主从
192.168.254.135  192.168.254.130   keep130   master
192.168.254.129   keep129   backup

 

Keepalived安装

  将文件上传到服务器,然后解压安装

# cd /usr/1ocal/ server
# tar -zxvf keepalived-x.x.x.tar.gz
# cd keepalived-1.2.18
#./configure --prefix-/usr/local/server/keepalived
# make && make install

将keepalived安装成Linux系统服务

因为没有使用keepalived的默认路径安装(默认是/usr/local) ,安装完成之后,需要做一些工作复 制默认配置文件到默认路径

# mkdir /etc/keepalived
# cp /usr/1ocal/server/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
复制keepalived服务脚本到默认的地址
# cp /usr/1ocal/server/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
# ln -s /usr/local/server/keepalived/sbin/keepalived /sbin/
设置keepalived服务开机启动
# chkconfig keepalived on 

配置主节点

  找到130主机keepalived的配置文件keepalived.conf

global_defs {
    router id keep130
}
vrrp_script chk_ nginx {
    script "/etc/keepalived/nginx_check.sh"
    interval 2
    weight -20
}
vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 130
    mcast_src_ip 192.168.254.130
    priority 100
    nopreempt
    advert_int_1
    authentication {
        auth_type PASS 
        auth_pass 1111
    }
track_script {
    chk_nginx
}
virtual_ipaddress {
    192.168.254.135
}    

配置从节点

global_defs {
    router id keep129
}
vrrp_script chk_nginx {
    script "/etc/keepalived/nginx_check.sh"
    interval 2
    weight -20
}
vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 130
    mcast_src_ip 192.168.254.129
    priority 90
    advert_int_1
    authentication {
        auth_type PASS 
        auth_pass 1111
    }
track_script {
    chk_nginx
}
virtual_ ipaddress {
    192.168.254.135
}    

  Nginx检查脚本

    在/etc/keepalived目录下创建nginx_check.sh文件

#!/bin/bash
A= `ps -C nginx --no-header| wc -l`
if [ $A -eq 0];then
    /usr/1oca1/server/nginx/sbin/nginx
    sleep 2
    if [ `ps -C nginx --no-header| wc -l` -eq 0 ]; then
        killall keepalived
    fi
fi

配置说明

global_defs {
  ## keepalived 自带的邮件提醒需要开启sendmail 服务。建议用独立的监控或第三方SMTP
  router_ id keep130 ##标识本节点的字条串,通常为hostname
}
# keepalived 会定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp. instance 的优先级。如果脚本执行结果为e, 并且weight 配置的值大于e,则优先级相应的增加。如果脚本执行结果非e, 并且weight配置的值小于日,则优先级相应的减少。其他情况,维持原本配置的优先级,即配置文件中priority 对应
的值。
vrrp_script chk_nginx {
  script "/etc/keepalived/nginx. check.sh" #检测nginx 状态的脚本路径
  interval 2 #检测时间间隔
  weight -20 #如果条件成立,权重-20
}
#定义虚拟路由,VI. 1为虚拟路由的标示符,自己定义名称 vrrp_instance VI_1 {   state MASTER #主节点为MASTER, 对应的备份节点为BACKUP   interface eth1 #绑定虚拟IP的网络接口,与本机IP地址所在的网络接口相同,我的是eth1   virtual_router_id 130 #虚拟路由的ID号,两个节点设置必须- 一样,可选IP最后一段使用, 相同的VRID为一个组,他将决定多播的MAC地址   mcast_ src_ ip 192.168.211.130 ##本机IP地址   priority 100 ##节点优先级,值范围0-254, MASTER 要比BACKUP 高   nopreempt #优先级高的设置nopreempt 解决异常恢复后再次抢占的问题   advert_int 1 ##特神组播信息发送间隔,两个节点设置必须-样,默认1s #设置验证信息,两个节点必须-致 authentication {   auth_type PASS   auth_pass 1111 ##真实生产,按需求对应该过来
}

 ##将track script块加入instance 配置块
 track_script {
  chk_nginx #执行Nginx 监控的服务
 }
 #虚拟IP池,两个节点设置必须一样
 virtual_ipaddress {
  192.168.199.135 #虚拟ip, 可以定义多个
 }

}

 

posted @ 2020-04-21 15:10  Tiger-Adan  阅读(923)  评论(0编辑  收藏  举报