【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx

往期文章一览

分布式会话与单点登录SSO系统CAS,包含完整示例代码实现

【15W字长文】主从复制高可用Redis集群,完整包含Redis所有知识点

使用LVS+Keepalived实现Nginx高可用

Nginx介绍和使用

什么是Nginx

  1. Nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。

  2. Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。

  3. 可以使静态资源虚拟化,可以缓存服务器静态资源

  4. Nginx是一款轻量级的Web服务器/反向代理服务器以及电子邮件代理服务器,并在一个BSD-like协议下发行。

  5. 由俄罗斯的程序设计师lgor Sysoev所开发,供俄国大型的入口网站及搜索引擎Rambler使用。

  6. 其特点是占有内存少,并发能力强,事实上Nginx的并发能力确实在同类型的网页服务器中表现较好。

  7. Nginx相较于Apache\lighttpd具有占有内存少,稳定性高等优势,并且依靠并发能力强,丰富的模块库以及友好灵活的配置而闻名。

  8. 在Linux操作系统下,Nginx使用epoll事件模型,得益于此,Nginx在Linux操作系统下效率相当高。同时Nginx在OpenBSD或FreeBSD操作系统上采用类似于Epoll的高效事件模型kqueue。

  9. Nginx作为负载均衡服务:Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务,也可以支持作为 HTTP代理服务对外进行服务。Nginx采用C进行编写,不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多。

  10. 反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。

    参考资料:

    https://zhuanlan.zhihu.com/p/71323442

常见的服务器

  1. MS IIS 微软的,通常发布一些asp.net项目
  2. Weblogic Jboss 用于传统行业 ERP/物流/电信/金融等
  3. Tomcat Jetty 通常用于J2EE项目的
  4. Apache Nginx 用于静态服务虚拟化,反向代理,负载均衡等
  5. Netty 高性能服务器编程框架

什么是正向代理和反向代理

  1. 正向代理:客户端想要访问一个服务器,但是它可能无法直接访问这台服务器,这时候这可找一台可以访问目标服务器的另外一台服务器,而这台服务器就被当做是代理人的角色 ,称之为代理服务器,于是客户端把请求发给代理服务器,由代理服务器获得目标服务器的数据并返回给客户端。客户端是清楚目标服务器的地址的,而目标服务器是不清楚来自客户端,它只知道来自哪个代理服务器,所以正向代理可以屏蔽或隐藏客户端的信息。

  2. 反向代理:从上面的正向代理,你会大概知道代理服务器是为客户端作代理人,它是站在客户端这边的。其实反向代理就是代理服务器为服务器作代理人,站在服务器这边,它就是对外屏蔽了服务器的信息,常用的场景就是多台服务器分布式部署,像一些大的网站,由于访问人数很多,就需要多台服务器来解决人数多的问题,这时这些服务器就由一个反向代理服务器来代理,客户端发来请求,先由反向代理服务器,然后按一定的规则分发到明确的服务器,而客户端不知道是哪台服务器。常常用nginx来作反向代理。

  3. 正向代理即是客户端代理, 代理客户端, 服务端不知道实际发起请求的客户端,反向代理即是服务端代理, 代理服务端, 客户端不知道实际提供服务的服务端
    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第1张图片

    参考资料:

    https://blog.csdn.net/aqleung/article/details/80923470

    https://www.cnblogs.com/taostaryu/p/10547132.html

下载Nginx

  • Nginx官网:http://nginx.org/

  • Nginx下载地址:http://nginx.org/en/download.html
    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第2张图片

  • Mainline 开发版、最新版 ,Stable 稳定版 ,Legacy 历史版本

使用源码编译安装Nginx

  1. 把下载好的Nginx安装包,源码包结构如下:
    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第3张图片

  2. 安装Nginx依赖环境

    1. 安装gcc环境:yum install gcc-c++
    2. 安装PCRE库,用于解析正则表达式:yum install -y pcre pcre-devel
    3. zlib压缩和解压缩依赖:yum install -y zlib zlib-devel
    4. SSL 安全的加密的套接字协议层,用于HTTP安全传输,也就是https:yum install -y openssl openssl-devel
  3. 上传并解压,需要注意,解压后得到的是源码,源码需要编译后才能安装(安装使用的是1.16版本

    tar -zxvf nginx-1.16.1.tar.gz

  4. 编译之前,先创建nginx临时目录,如果不创建,在启动nginx的过程中会报错

    mkdir /var/temp/nginx -p

  5. 在nginx目录,输入如下命令进行配置,目的是为了创建makefile文件

    ./configure \

    –prefix=/usr/local/nginx \

    –pid-path=/var/run/nginx/nginx.pid \

    –lock-path=/var/lock/nginx.lock \

    –error-log-path=/var/log/nginx/error.log \

    –http-log-path=/var/log/nginx/access.log \

    –http-client-body-temp-path=/var/tmp/nginx/client \

    –http-proxy-temp-path=/var/tmp/nginx/proxy \

    –http-fastcgi-temp-path=/var/tmp/nginx/fcgi \

    –http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \

    –http-scgi-temp-path=/var/tmp/nginx/scgi \

    –with-pcre \

    –with-http_v2_module \

    –with-http_ssl_module \

    –with-http_realip_module \

    –with-http_addition_module \

    –with-http_sub_module \

    –with-http_dav_module \

    –with-http_flv_module \

    –with-http_mp4_module \

    –with-http_gunzip_module \

    –with-http_gzip_static_module \

    –with-http_random_index_module \

    –with-http_secure_link_module \

    –with-http_stub_status_module \

    –with-http_auth_request_module \

    –with-mail \

    –with-mail_ssl_module \

    –with-file-aio \

    –with-ipv6 \

    –with-http_v2_module \

    –with-threads \

    –with-stream \

    –with-stream_ssl_module

    注:\ 代表在命令行中换行,用于提高可读性

    命令 解释
    –prefix nginx的安装目录,默认为/usr/local/nginx
    –sbin-path nginx可执行文件路径,若没有设置则依赖于–prefix
    –conf-path 设置nginx.conf配置文件路径,若没有设置则依赖于–prefix,nginx启动时可以通过-c参数指定配置文件
    –error-log-path 错误日志路径
    –http-log-path http主请求日志文件
    –pid-path 存放nginx进程的pid号
    –lock-path 共享存储器互斥锁文件路径
    –http-client-body-temp-path 客户端收到请求后,临时存放请求体目录
    –http-proxy-temp-path 使用代理后,通过该项设置存放请求体路径
    –http-fastcgi-temp-path 设置FastCGI临时文件的目录
    –http-uwsgi-temp-path 设置uWSGI临时文件的目录
    –http-scgi-temp-path 设置SCGI临时文件的目录
    –user 指定nginx运行的用户
    –group 指定nginx运行的用户组
    –with-pcre 设置PCRE库的源码路径
    –with-http_v2_module 用来支持 HTTP 2.0 的
    –with-http_ssl_module 如果需要对流量进行加密,可以使用该选项,再URLs中开始部分将会是https(需要OpenSSL库)
    –with-http_gzip_static_module 启用gzip模块,在线实时压缩输出数据流
  6. make编译

    make

  7. 安装

    make install

    6、7 步可以整合一条命令 make && make install

    使用 whereis nginx 可以查看nginx安装目录(–prefix指定)

    配置文件在安装目录下的conf文件夹下

    启动文件在安装目录下的sbin文件夹下

    访问Nginx时默认的首页在安装目录下的html文件夹下

  8. 进入nginx安装目录下的sbin目录启动nginx

    启动:./nginx

    停止:./nginx -s stop

    重新加载:./nginx -s reload

    测试配置文件是否正确:./nginx -t

  9. 打开浏览器,访问虚拟机所处内网ip即可打开Nginx默认页面(http://服务器ip:80/)

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第4张图片

注意事项:

  1. 如果在云服务器安装,需要开启默认的nginx端口:80

  2. 如果在虚拟机安装,需要关闭防火墙

  3. 本地win或mac需要关闭防火墙

    参考链接:https://www.cnblogs.com/weibanggang/p/11484970.html

使用yum安装Nginx

  1. 更新yum

    yum update -y

  2. 打开 http://nginx.org/packages/centos/ 找到自己想要下载的版本rpm文件

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第5张图片

  3. 手动下载rpm文件或者复制下载文件地址例如:http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.20.2-1.el7.ngx.x86_64.rpm

    服务器没有网络可以先下载rpm包然后上传之后安装,服务器连上网可以直接复制下载地址直接用下载地址安装

  4. 安装Nginx

    rpm -ivh http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.20.2-1.el7.ngx.x86_64.rpm

    地址可以替换为手动上传的rpm包文件

  5. 查看Nginx安装信息以及使用Nginx

    nginx -V

    默认配置文件在:/etc/nginx/nginx.conf

    Nginx常用命令:

    systemctl start nginx 启动

    systemctl stop nginx 停止

    systemctl restart nginx 重启

    Nginx默认页面:http://服务器ip:80/

Nginx请求默认页面的流程

  1. Nginx安装完毕之后,默认启动了一个server来监听80端口的所有请求(nginx.conf配置文件可以查看),重点看http配置下的server部分

    #user  nobody;
    worker_processes  1; #工作进程:数目。根据硬件调整,通常等于cpu数量或者2倍cpu数量。
     
    #错误日志存放路径
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
     
    #pid        logs/nginx.pid; # nginx进程pid存放路径
     
     
    events {
        worker_connections  1024; # 工作进程的最大连接数量
    }
     
     
    http {
        include       mime.types; #指定mime类型,由mime.type来定义
        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; #用log_format指令设置日志格式后,需要用access_log来指定日志文件存放路径
                        
        sendfile        on; #指定nginx是否调用sendfile函数来输出文件,对于普通应用,必须设置on。
                如果用来进行下载等应用磁盘io重负载应用,可设着off,以平衡磁盘与网络io处理速度,降低系统uptime。
        #tcp_nopush     on; #此选项允许或禁止使用socket的TCP_CORK的选项,此选项仅在sendfile的时候使用
     
        #keepalive_timeout  0;  #keepalive超时时间
        keepalive_timeout  65;
     
        #gzip  on; #开启gzip压缩服务
     
        #虚拟主机
        server {
            listen       80;  #配置监听端口号
            server_name  localhost; #配置访问域名,域名可以有多个,用空格隔开
     
            #charset koi8-r; #字符集设置
     
            #access_log  logs/host.access.log  main;
     
            location / { #映射的路由
                root   html; #相对路径html文件夹
                index  index.html index.htm; #默认加载的html文件
            }
            #错误跳转页
            #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$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
            #    root           html; #根目录
            #    fastcgi_pass   127.0.0.1:9000; #请求转向定义的服务器列表
            #    fastcgi_index  index.php; # 如果请求的Fastcgi_index URI是以 / 结束的, 该指令设置的文件会被附加到URI的后面并保存在变量$fastcig_script_name中
            #    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; # ssl_prefer_server_ciphers  on; #
     
     
        #    location / {
        #        root   html;
        #        index  index.html index.htm;
        #    }
        #}
     
    }
    
  2. 浏览器输入 http://服务器ip:80/ 访问时最后一个/被映射为根路由,会按配置文件中的配置进行转发,配置了一个location当请求路径为/是会被直接映射到相对于conf文件夹的相对路径下html文件夹中的index.html文件。

Nginx的进程模型

  1. Nginx分master进程和work进程,master只有一个,work可以有多个,在ngxin.conf中配置,一般我们会设置与机器cpu核数一致

    worker_processes  1;
    
  2. master进程主要用来管理worker进程,管理包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。

  3. 基本的网络事件,则是放在worker进程中来处理了。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。

  4. 通过master来接收外界的信号,然后将任务分配给worker去做。比如接受一个nginxup -s reload信号后,交给worker去重启,而且当有work进程正在处理请求,那么此work进程还可以延后重启动作。

    参考资料:

    https://blog.csdn.net/No_Game_No_Life_/article/details/104223604

    https://blog.csdn.net/qq_39110766/article/details/81209529

Nginx处理http请求的模型

  1. 当有一个http请求过来时,而且有多个work进程,所有的work进程会有一个抢占机制,这个机制基于一个互斥锁,只有抢到这个锁的work进程才能处理这个请求
    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第6张图片

  2. 传统服务器的请求处理:work进程处理请求是同步阻塞的。当有多个请求过来时,一个work进程处理请求时阻塞了,master会fork出另一个work进程处理后面的请求,这个进程也被阻塞时,master就会继续fork新的进程来处理;这样的话当并发量特别大时,master会fork出非常多的work进程,这样对服务器的性能影响是非常大的。
    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第7张图片

  3. Nginx的请求处理:Nginx的work进程是异步非阻塞的。当有多个请求过来时,一个work进程处理请求时阻塞了,它会去处理下一个请求,这里work进程用了linux的epoll模型。采用了epoll模型,一个worker大概可以处理6-8万的请求。所以,CPU越多,并发越大,处理几十万到几百万的请求是没有问题的。
    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第8张图片

    events {
    	# 默认使用epoll,所以实际上可以不配置use epoll
    	use epoll;
    	# 每个worker允许连接的请求最大数目
    	# 不能盲目修改增大,要跟着硬件走,否则请求会产生卡顿
        worker_connections  1024;
    }
    

Nginx的配置结构

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第9张图片

  1. 全局块(main):配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。

  2. events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。

  3. http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。

  4. server块:配置虚拟主机的相关参数,一个http中可以有多个server。最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或IP配置。

  5. location块:一个 server 块可以配置多个 location 块。 这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称(也可以是IP别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

  6. main部分设置将会影响其他所有设置,server部分的指令主要用于指定主机和端口。upstream指令主要用于负载均衡,设置一系列的后端服务器,location部分主要用于匹配网页位置。四者的关系如下:server继承main,location继承server,upstream既不继承其他设置,也不被设置所继承

  7. 指令由分号结束;一个大括号包含的一些指令是一个指令块,大括号后方没有分号结尾;注释使用#号;$代表引用一个参数变量;参数和值需要有空格隔开。

    参考地址:

    https://www.cnblogs.com/knowledgesea/p/5175711.html

    https://www.cnblogs.com/badaoliumangqizhi/p/11768875.html

    https://www.linuxidc.com/Linux/2013-11/92594.htm

核心配置文件详解

  1. user:配置了work进程运行使用的用户,默认是nobody,可以修改为root;master进程运行使用的用户是root

  2. worker_processes:配置work进程的数量一般是cpu的核心数或者是核心数减一

  3. error_log:配置错误日志的路径以及日志级别,日志路径一般在编译阶段会指定;Nginx的日志级别有 debug、info、notice、warn、error、crit,信息最详细的是debug

  4. pid:配置Nginx的进程号,一般在编译阶段会指定

  5. events指令块:配置事件处理的一些参数

    1. use:配置work进程处理事件的模型,一般根据服务器系统来配置,Linux使用epoll模型
    2. worker_connections:配置work进程允许连接的客户端最大连接数,根据硬件配置来决定
  6. http指令块:配置http网络传输相关的一些参数

    1. include:导入外部的一个文件,也可以将一个server的配置文件写到外部,使用这个命令来导入conf文件;默认导入了mime.types文件,这个文件定义了常用的mime类型,和用于表示的简写。

    2. default_type:默认的类型,application/octet-stream

    3. log_format:定义日志文件格式化的格式

      参数名 参数意义
      $remote_addr 客户端ip
      $remote_user 远程客户端用户名,一般为:‘-’
      $time_local 时间和时区
      $request 请求的url以及method
      $status 响应状态码
      $body_bytes_send 响应客户端内容字节数
      $http_referer 记录用户从哪个链接跳转过来的
      $http_user_agent 用户所使用的代理,一般来时都是浏览器
      $http_x_forwarded_for 通过代理服务器来记录客户端的ip

      参考地址:

      https://blog.51cto.com/professor/1706535

    4. access_log:定义请求日志文件的地址,一般在编译时定义

    5. sendfile:配置是否高效传输文件

    6. tcp_nopush:配置是不是把数据包累积到一定大小再发送,要先开启sendfile才会生效

    7. keepalive_timeout:配置客户端连接服务器的超时时间,http请求和服务器建立连接之后,完成请求不会马上断开,有新的请求过来时会复用这个连接,只有超时时间到了这个连接才会断开。若需要客户端每次都建立新的连接则设置参数值为0

    8. gzip:配置是否开启数据压缩

    9. server指令块:配置一个虚拟主机或虚拟服务

      1. listen:配置虚拟主机监听的端口号

      2. server_name:配置监听的主机名,可以是localhost,也可以是域名,当请求的host和端口与配置的虚拟主机相匹配之后就会使用此虚拟主机中的配置

      3. localhost:配置路由的匹配规则,/代表的是根路径

        1. root:配置映射目录的上级目录,并且该上级目录要含有location指定名称的同名目录。

        2. alias:配置映射目录的绝对路径

          参考资料:

          root和alias的区别:https://www.jb51.net/article/94367.htm

        3. index:配置访问此location若没有指定具体访问的页面时,则默认打开的页面。

      4. error_page:配置拦截访问报错时默认跳转的页面

Nginx报错pid找不到的解决办法

在这里插入图片描述

  1. 检查此文件的父文件夹是否存在,若不存在就创建一个

    mkdir -p pid文件夹路径

  2. 尝试重启Nginx

    ./nginx -s reload

  3. 若报错为下面这个,则尝试指定配置文件启动

    在这里插入图片描述

    ./nginx -c 配置文件地址

    启动完成后尝试访问Nginx

  4. 若还是不行,则尝试使用配置文件中的pid路径配置

    打开主要配置文件,在worker_processes下添加:

    pid /pid文件夹路径/nginx.pid

    此路径必须为nginx可以访问的路径,再重新执行1、2、3步

Nginx常用命令

  1. ./nginx -s stop:强制停止Nginx,若有黑客正在拉取数据可以使用此命令
  2. ./nginx -s quit:正常退出Nginx,若有进程正在处理http请求,则会等待请求处理完成才会退出。
  3. ./nginx -t:监测配置文件是否正确
  4. ./nginx -v:查看Nginx的版本
  5. ./nginx -V:查看Nginx的详细信息
  6. ./nginx -h或者 ./nginx -?:查看Nginx的帮助信息
  7. ./nginx -c 配置文件路径:手动指定启动时加载的配置文件

Nginx的日志切割

​现有的日志都会存在 access.log 文件中,但是随着时间的推移,这个文件的内容会越来越多,体积会越来越大,不便于运维人员查看,所以我们可以通过把 文件切割为多份不同的小文件作为日志,切割规则可以以 天 为单位,如果每天有几百G或者几个T的日志的话,则可以按需以 每半天 或者 每小时 对日志切割一次。

  1. 找到Nginx的日志位置

    ./nginx -V
    编译时所设置的位置是:

    /var/log/nginx/error.log

    /var/log/nginx/access.log

  2. 一般Nginx的sbin路径下创建一个shell可执行文件:cut_my_log.sh,内容为:

    参考地址:

    https://blog.51cto.com/devin223/1664928

    https://www.cnblogs.com/etwits/p/11378947.html

    #!/bin/bash
    LOG_PATH="/var/log/nginx/"
    RECORD_TIME=$(date -d "yesterday" +%Y-%m-%d+%H:%M)
    # nginx进程号位置
    PID=/var/run/nginx/nginx.pid
    mv ${LOG_PATH}/access.log ${LOG_PATH}/access.${RECORD_TIME}.log
    mv ${LOG_PATH}/error.log ${LOG_PATH}/error.${RECORD_TIME}.log
    
    #向Nginx主进程发送信号,用于重新打开日志文件 
    kill -USR1 `cat $PID`
    
  3. 为 cut_my_log.sh 添加可执行的权限:

    chmod +x cut_my_log.sh

  4. 测试执行脚本:

    ./cut_my_log.sh

    运行之后查看切割内容

  5. Linux安装定时任务

    yum install crontabs

  6. crontab -e 编辑并且添加一行新的任务:

    定时任务时间表达式+执行任务的脚本:0 1 * * * /usr/local/nginx/sbin/cut_my_log.sh

    Cron表达式是,分为5或6个域,每个域代表一个含义,如下所示:

    星期几 年(可选)
    取值范围 0-59 0-23 1-31 1-12 1-7 2019/2020/2021/…

    常用表达式:

    • 每分钟执行:*/1 * * * *
    • 每日凌晨(每天晚上23:59)执行:59 23 * * *
    • 每日凌晨1点执行:0 1 * * *

    参考链接:

    linux定时任务(crontab):https://blog.csdn.net/XUEYUTIANQI/article/details/113976558

    每天定时为数据库备份:https://www.cnblogs.com/leechenxiang/p/7110382.html

  7. 重启定时任务:

    service crond restart(或者使用systemctl restart crond)

    常用定时任务命令:

    service crond start | systemctl start crond //启动服务

    service crond stop | systemctl stop crond //关闭服务

    service crond restart | systemctl restart crond //重启服务

    service crond reload | systemctl reload crond //重新载入配置

    crontab -e // 编辑任务

    crontab -l // 查看任务列表

Nginx为静态资源提供服务

  1. 上传静态资源到服务器,可以上传到服务器任意位置或者Nginx的html文件夹下,若上传到html文件夹下,若没有删除或修改Nginx的默认虚拟主机,则可以直接通过:域名+端口+静态资源路径 访问了,因为html文件夹已经被Nginx默认转发了

  2. 进入nginx.conf所在的文件夹,创建一个port8888.conf,若不需要创建新的虚拟主机则直接跳到6

    #虚拟主机
    server {
        listen       8888;  #配置监听端口号,配置为自己想要使用的端口
        server_name  localhost; #配置访问域名,域名可以有多个,用空格隔开
     
        location /web/ { #映射的路由
            alias  /opt/web/; #绝对路径html文件夹,是自己上传的静态文件的文件夹路径,我这里用/opt/web/举例,最后的/要加上
            index  index.html; #默认加载的html文件,没有则可以不用配置
        }
    }
    
  3. 在主配置文件中引入这个.conf文件

    在server指令块下方加入(要和server指令块同一级):

    include port8888.conf; # 这里使用的是相对路径,也可以使用绝对路径

  4. 重启Nginx

    ./nginx -s reload

    注意:防火墙要关闭或者防火墙允许此端口被访问

  5. 尝试访问静态内容:http://服务器ip:8888/web/静态资源文件路径

  6. 在主配置文件中找到现有的server指令块,在location指令块下方再新增一个location(和原来的location同一级)

    location /web/ { #映射的路由,路由规则不能重复
        alias  /opt/web/; #绝对路径html文件夹,是自己上传的静态文件的文件夹路径,我这里用/opt/web/举例,最后的/要加上
        index  index.html; #默认加载的html文件,没有则可以不用配置
    }
    
  7. 重启Nginx

    ./nginx -s reload

    注意:防火墙要关闭或者防火墙允许此端口被访问

  8. 尝试访问静态内容:http://服务器ip:虚拟主机端口/web/静态资源文件路径

    location中除了使用alias之外还可以使用root参数,这两者的用法区别在于对URI的处理方法不同。

    假如服务器路径为:/home/imooc/files/img/face.png

    • root 路径完全匹配访问,配置的时候为:

      location /imooc {
      	root /home
      }
      

      用户访问的时候请求为: url:port/imooc/files/img/face.png

    • alias 可以为你的路径做一个别名,对用户透明,配置的时候为:

      location /hello {
      	root /home/imooc
      }
      

      用户访问的时候请求为: url:port/hello/files/img/face.png ,如此相当于为目录 imooc 做一个自定义的别名。

    参考链接:

    https://www.jianshu.com/p/2200eefa0985

    https://www.cnblogs.com/hanxiaohui/p/8488563.html

Nginx使用Gzip压缩数据提高传输效率

  1. 打开nginx.conf文件,在http指令块中配置gzip功能(这段配置和server同一级,放到server之前)

    gzip on; # 开启压缩功能

    gzip_min_length 1; # 限制最小压缩,小于1字节文件不会压缩

    gzip_comp_level 3; # 定义压缩级别(1-9,压缩比,文件越大,压缩越多,但是消耗cpu性能越多)

    gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json; # 定义压缩文件的类型

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第10张图片

    参考链接:

    https://cloud.tencent.com/developer/article/1374023

  2. 重启Nginx

    ./nginx -s reload

  3. 访问页面,打开F12,查看network中获取数据时,返回数据的大小

location的匹配规则

  1. 空格 :默认匹配,普通匹配

    location / {
    	root /home;
    }
    
  2. = :精确匹配

    location = /imooc/img/face1.png {
    	root /home;
    }
    
  3. ~* :匹配正则表达式,不区分大小写

    #符合图片的显示
    location ~ \.(GIF|jpg|png|jpeg) {
    	root /home;
    }
    
  4. ~ :匹配正则表达式,区分大小写

    #GIF必须大写才能匹配到
    location ~ \.(GIF|jpg|png|jpeg) {
    	root /home;
    }
    
  5. ^~ :以某个字符路径开头

    location ^~ /imooc/img {
    	root /home;
    }
    

    修改配置文件之后都需要重启Nginx

    参考链接:

    https://developer.aliyun.com/article/753379

    https://www.cnblogs.com/yuncong/p/12427480.html

DNS解析域名的流程

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第11张图片
【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第12张图片

一. 根域

就是所谓的“.”,其实我们的网址www.baidu.com在配置当中应该是www.baidu.com.(最后有一点),一般我们在浏览器里输入时会省略后面的点,而这也已经成为了习惯。

根域服务器我们知道有13台,但是这是错误的观点。

根域服务器只是具有13个IP地址,但机器数量却不是13台,因为这些IP地址借助了任播的技术,所以我们可以在全球设立这些IP的镜像站点,你访问到的这个IP并不是唯一的那台主机。

具体的镜像分布可以参考维基百科。这些主机的内容都是一样的

二. 域的划分

根域下来就是顶级域或者叫一级域,

有两种划分方式,一种互联网刚兴起时的按照行业性质划分的com.,net.等,一种是按国家划分的如cn.,jp.,等。

具体多少你可以自己去查,我们这里不关心。

每个域都会有域名服务器,也叫权威域名服务器。

一级域之后还有二级域,三级域,只要我买了一个顶级域,并且我搭建了自己BIND服务器(或者其他软件搭建的)注册到互联网中,那么我就可以随意在前面多加几个域了(当然长度是有限制的)。

baidu.com 是二级域(.baidu 是二级域名), www.baidu.com 算是三级域了(.www是三级域名),他是在baidu.com 这个域里的一叫做www的主机。

比如a.www.baidu.com,在这个网址中,www.baidu.com变成了一个三级域而不是一台主机,主机名是a。

三. 域名服务器

能提供域名解析的服务器,上面的记录类型可以是A(address)记录,NS记录(name server),MX(mail),CNAME等。

(详解参见博客:域名解析中A记录、CNAME、MX记录、NS记录的区别和联系)

A记录是什么意思呢,就是记录一个IP地址和一个主机名字,比如我这个域名服务器所在的域test.baidu.com,我们知道这是一个二级的域名,然后我在里面有一条A记录,记录了主机为a的IP,查到了就返回给你了。

如果我现在要想baidu.com这个域名服务器查询a.test.baidu.com,那么这个顶级域名服务器就会发现你请求的这个网址在test.baidu.com这个域中,我这里记录了这个二级域的域名服务器test.baidu.com的NS的IP。我返回给你这个地址你再去查主机为a的主机把。

这些域内的域名服务器都称为权威服务器,直接提供DNS查询服务。(这些服务器可不会做递归哦)

四. 解析流程

  1. 浏览器先检查自身缓存中有没有被解析过的这个域名对应的ip地址,如果有,解析结束。同时域名被缓存的时间也可通过TTL属性来设置。

  2. 如果浏览器缓存中没有(专业点叫还没命中),浏览器会检查操作系统缓存中有没有对应的已解析过的结果。而操作系统也有一个域名解析的过程。在windows中可通过c盘里一个叫hosts的文件来设置,如果你在这里指定了一个域名对应的ip地址,那浏览器会首先使用这个ip地址。但是这种操作系统级别的域名解析规程也被很多黑客利用,通过修改你的hosts文件里的内容把特定的域名解析到他指定的ip地址上,造成所谓的域名劫持。所以在windows7中将hosts文件设置成了readonly,防止被恶意篡改。

  3. 如果至此还没有命中域名,才会真正的请求本地域名服务器(LDNS)来解析这个域名,这台服务器一般在你的城市的某个角落,距离你不会很远,并且这台服务器的性能都很好,一般都会缓存域名解析结果,大约80%的域名解析到这里就完成了。

  4. 如果LDNS仍然没有命中,就直接跳到Root Server 域名服务器请求解析

  5. 根域名服务器返回给LDNS一个所查询域的主域名服务器(gTLD Server,国际顶尖域名服务器,如.com .cn .org等)地址

  6. 此时LDNS再发送请求给上一步返回的gTLD

  7. 接受请求的gTLD查找并返回这个域名对应的Name Server的地址,这个Name Server就是网站注册的域名服务器

  8. Name Server根据映射关系表找到目标ip,返回给LDNS

  9. LDNS缓存这个域名和对应的ip

  10. LDNS把解析的结果返回给用户,用户根据TTL值缓存到本地系统缓存中,域名解析过程至此结束

    参考链接:

    https://zhuanlan.zhihu.com/p/27290218

    https://www.jianshu.com/p/03015813f61a

    http://c.biancheng.net/view/6455.html

    https://blog.csdn.net/buaa_shang/article/details/8998972

    https://blog.csdn.net/whoim_i/article/details/104265312

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第13张图片

使用hosts文件模仿域名访问

Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应网页,如果没有找到,则系统会再将网址提交DNS域名解析服务器进行IP地址的解析。需要注意的是,Hosts文件配置的映射是静态的,如果网络上的计算机更改了请及时更新IP地址,否则将不能访问。

  1. 找到Hosts文件

    hosts文件在不同操作系统(甚至不同Windows版本)的位置都不大一样,以下为hosts文件在不同系统中所处的目录:

    Windows XP/2000/Vista/7/8/8.1/10:C:\windows\system32\drivers\etc\

    (XP系统无法使用bat批处理命令直接替换hosts,需手动替换后重新插拔网线或重启方使hosts生效)

    (可更改\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DataBasePath项修改host位置)

    Windows 95/98/Me:%WinDir%\ (其实就是C:\WINDOWS)

    Linux及其他类Unix操作系统:/etc/

    Mac OS 9及更早的系统:System Folder: Preferences或System folder(文件格式可能与Windows和Linux所对应的文件不同)

    Mac OS X:/private/etc(使用BSD风格的hosts文件)

    OS/2及eComStation:“bootdrive”:\mptn\etc\

    Android:/system/etc/

    Symbian第1/2版手机:C:\system\data\

    Symbian第3版手机:C:\private\10000882\(能使用兼容AllFiles的文件浏览器访问。)

    iPhone OS:/etc/(需要越狱)

    iPad OS:/private/etc

    webOS:/etc

  2. 修改Hosts文件映射信息,以Windows为例:

    在文件末尾新增映射关系:

    x.x.x.x www.imooc.com # 格式为ip + 空格 + 域名

  3. 访问服务器时尝试将ip替换为域名访问(端口不能替换)

Nginx解决跨域问题

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第14张图片

什么是跨域

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。

所谓同源是指,域名,协议,端口均相同,不明白没关系,举个栗子:

http://www.123.com/index.html 调用 http://www.123.com/server.php (非跨域)

http://www.123.com/index.html 调用 http://www.456.com/server.php (主域名不同:123/456,跨域)

http://abc.123.com/index.html 调用 http://def.123.com/server.php (子域名不同:abc/def,跨域)

http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)

http://www.123.com/index.html 调用 https://www.123.com/server.php (协议不同:http/https,跨域)

请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。

浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。

参考链接:

https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy

https://segmentfault.com/a/1190000015597029

https://zhuanlan.zhihu.com/p/46649733

解决跨域的几种方式

  1. jsonp

    参考链接:

    https://www.cnblogs.com/itmacy/p/6958181.html

  2. 服务端拦截器(直接复制进去就可以生效)

    import org.springframework.stereotype.Component;
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @author maolinyuan
     * @version 1.0
     * @date 2021/2/1 13:49
     */
    @Component
    @WebFilter("/*")
    public class CrossFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            //都允许跨域
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
            response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With, Authentication, Token");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            //如果是OPTIONS请求就return 往后执行会到业务代码中 他不带参数会产生异常
            if ("OPTIONS".equals(request.getMethod())) {
                return;
            }
            //第二次就是POST请求 之前设置了跨域就能正常执行代码了
            filterChain.doFilter(servletRequest, servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
  3. 使用Nginx配置,把以下配置放到server指令块内部location之前,和location同一级(跨域配置只需要在请求链路中设置一次,设置多次会报错)

    # 允许跨域请求的域,*代表所有

    add_header ‘Access-Control-Allow-Origin’ *;

    # 允许带上cookie请求

    add_header ‘Access-Control-Allow-Credentials’ ‘true’;

    # 允许请求的方法,比如 GET/POST/PUT/DELETE

    add_header ‘Access-Control-Allow-Methods’ *;

    # 允许请求的header

    add_header ‘Access-Control-Allow-Headers’ *;

Nginx配置静态资源防盗链

为什么要设置防盗链

假设B站点作为一个商业网站,有很多自主版权的图片,自身展示用于商业目的。而A站点,希望在自己的网站上面也展示这些图片,直接使用:

<img src="http://b.com/photo.jpg"/>

这时大量的客户端在访问A站点时,实际上消耗了B站点的流量,而A站点却从中达成商业目的,从而不劳而获。这样的A站点着实令B站点不快的。

参考链接:

https://www.jianshu.com/p/0a1338db6cab

https://blog.csdn.net/qq_41071876/article/details/112691210

如何配置

  1. 把一下配置放到server指令块内部location之前,和location同一级

    # 对源站点验证

    valid_referers *.imooc.com;

    # 非法引入会进入下方判断

    if ($invalid_referer) {

    ​ return 403;

    }

  2. 重启Nginx

    ./nginx -s reload

  3. 验证是否生效

Nginx的模块化体系

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第15张图片

模块简介

  1. nginx core 实现了一些通讯协议,提供其他模块的运行时环境,协调其他模块,类似于jvm

  2. http和mail 位于nginx core和各功能模块的中间层,这2个模块在nginx core之上实现了另外一层抽象,分别处理与http协议和email相关协议(SMTP/IMAP/POP3)有关的事件,并且确保这些事件能被以正确的顺序调用其它的一些功能模块。

  3. event module 搭建了独立于操作系统的事件处理机制的框架,以及提供了各具体事件的处理,包括ngx_event_module、ngx_event_core_module和ngx_epoll_module等,Nginx具体使用何种事件处理模块,这依赖于具体的操作系统和编译选项。

  4. phase handler 此类型的模块也被直接称为handler模块,主要负责处理客户端请求并产生待响应内容,比如ngx_http_module模块,负责客户端的静态页面请求处理并将对应的磁盘文件准备为响应内容输出。

  5. output filter 也称为filter模块,主要是负责对输出的内容进行处理,可以对输出进行修改,比如可以实现对输出的所有html页面增加预定义的footbar一类的工作,或者对输出的图片的URL进行替换之类的工作。

  6. upstream 实现反向代理功能,将真正的请求转发到后端服务器上,并从后端服务器上读取响应,发回客户端,upstream模块是一种特殊的handler,只不过响应内容不是真正由自己产生的,而是从后端服务器上读取的。

  7. load-balancer 负载均衡模块,实现特定的算法,在众多的后端服务器中,选择一个服务器出来作为某个请求的转发服务器。

  8. extend module 根据特定业务需要编写的第三方模块。

    参考链接:

    https://www.cnblogs.com/xiao-xue-di/p/13131083.html

目录解释

进入Nginx源码包,查看目录

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第16张图片

  1. auto 使nginx能自动识别操作系统,然后执行对应的脚本

  2. CHANGES 展示了Nginx更新迭代的内容以及历史版本号

  3. CHANGES.ru 俄罗斯语言版本

  4. conf 安装完成会把这个目录的拷贝到安装目录的conf内

  5. configura 编译命令,可以加入参数做编译配置

  6. contrib 工具包
    在这里插入图片描述

    1. geo2nginx.pl 提供地理位置生成工具
    2. README 说明文档
  7. html 提供一些模板html文件,安装完成会拷贝到安装目录的html目录下

  8. LICENSE 定义了一些协议以及版权说明等

  9. Makefile 编译完毕会生成这个文件,使用make install安装Nginx

  10. man 提供Nginx的一些手册

  11. objs 整合或实现一些第三方模块或插件安装完毕之后,会在这里面的ngx_modules.c文件中找到

  12. README 说明文档

  13. src 源码,内部目录对应Nginx的几大模块
    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第17张图片

Nginx对应用集群的负载均衡

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第18张图片

传统架构的优缺点

优点:

  1. 易于开发:开发的方式简单,方便运行也容易调试。
  2. 易于测试。
  3. 易于部署。

缺点:

  1. 项目过于臃肿,维护成本大,出现bug难定位。
  2. 资源无法隔离:共享一个数据库,或者一块内存。如果一个功能模块突然访问量过大,可能影响整个系统的性能。
  3. 无法灵活扩展:单体系统也可以集群部署,但是不够灵活,我明明只是订单系统遇到了瓶颈,只需要将订单模块水平扩展就行,但现在要将整个系统水平扩展。不灵活!
  4. 交付周期长:所有功能得一起上线,一起构建,一起部署。任何一个环节出错,都可能影响交付。

分布式架构的优缺点

优点:

  1. 增大系统容量:垂直或是水平拆分业务系统,让其变成一个分布式的架构

  2. 加强系统可用:通过分布式架构来冗余系统以消除单点故障,从而提高系统的可用性

  3. 模块重用度高

  4. 软件服务模块被拆分,开发和发布速度可以并行而变得更快

  5. 系统扩展性更高

  6. 团队协作流程改善

缺点:

  1. 架构设计变得复杂(尤其是其中的分布式事务)
  2. 部署单个服务会比较快,但是如果一次部署需要多个服务,流程会变得复杂
  3. 系统的吞吐量会变大,但是响应时间会变长
  4. 运维复杂度会因为服务变多而变得很复杂
  5. 架构复杂导致学习曲线变大
  6. 测试和查错的复杂度增大
  7. 技术多元化,这会带来维护和运维的复杂度
  8. 管理分布式系统中的服务和调度变得困难和复杂

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第19张图片

服务集群的优势

  1. 强扩展能力。其他扩展技术,通常仅能支持儿十个CPU 的扩展,扩展能力有限。而采用集群技术的集群系统则可以扩展到包括成百上千个CPU的多台服务穗,扩展能力具有明显优势。集群服务还可不断进行调整,以满足不断增长的应用需求。当集群的整体负荷超过集群的实际能力时,还可以添加额外的节点。

  2. 实现方式容易。服务器集群技术相对其他扩展技术来说更加容易实现,主要是通过软件进行的。在硬件上可以把多台性能较低、价格便宜的服务器,通过集群服务集中连接在一起即可实现整个服务器系统成倍,甚至几十、几百倍地增长。无论是从软硬件构成成本上来看,还是从技术实现成本上来看都较其他扩展方式低。

  3. 高可用性。使用集群服务拥有整个集群系统资源的所有权。如磁盘驱动器和IP地址将自动地从有故障的服务器上转移到可用的服务器上。当集群中的系统或应用程序出现故障时,集群软件将在可用的服务器上,重启失效的应用程序,或将失效节点上的工作分配到剩余的节点上。在切换过程中,用户只是觉得服务暂时停顿了一下。

  4. 易管理性。可以使用集群管理器来管理集群系统的所有服务器资源和应用程序,就像它们都运行在同一个服务器上一样。可以通过拖放集群对象,在集群里的不同服务器间移动应用程序,也可以通过同样的方式移动数据,还可以通过这种方式来手工地平衡服务器负荷、卸载服务器,从而方便地进行维护。同时,还可以从网络的任意地方的节点和资源处,监视集群的状态。当失效的服务器连回来时,将自动返回工作状态,集群技术将自动在集群中平衡负荷,而不需要入工干预。

什么是负载均衡

​ 负载均衡(Load Balance)建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。

​ 负载均衡有两方面的含义:首先,大量的并发访问或数据流量分担到多台节点设备上分别处理,减少用户等待响应的时间;其次,单个重负载的运算分担到多台节点设备上做并行处理,每个节点设备处理结束后,将结果汇总,返回给用户,系统处理能力得到大幅度提高。

负载均衡分类

  1. 二层负载均衡(mac)
    根据OSI模型分的二层负载,一般是用虚拟mac地址方式,外部对虚拟MAC地址请求,负载均衡接收后分配后端实际的MAC地址响应.
  2. 三层负载均衡(ip)
    一般采用虚拟IP地址方式,外部对虚拟的ip地址请求,负载均衡接收后分配后端实际的IP地址响应. (即一个ip对一个ip的转发, 端口全放开)
  3. 四层负载均衡(tcp)
    在三次负载均衡的基础上,即从第四层"传输层"开始, 使用"ip+port"接收请求,再转发到对应的机器。
  4. 七层负载均衡(http)
    从第七层"应用层"开始, 根据虚拟的url或IP,主机名接收请求,再转向相应的处理服务器。

四层和七层负载均衡

运维中最常见的四层和七层负载均衡,这里重点说下这两种负载均衡:

四层:

  1. 四层的负载均衡就是基于IP+端口的负载均衡:在三层负载均衡的基础上,通过发布三层的IP地址(VIP),然后加四层的端口号,来决定哪些流量需要做负载均衡,对需要处理的流量进行NAT处理,转发至后台服务器,并记录下这个TCP或者UDP的流量是由哪台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理。
  2. 对应的负载均衡器称为四层交换机(L4 switch),主要分析IP层及TCP/UDP层,实现四层负载均衡。此种负载均衡器不理解应用协议(如HTTP/FTP/MySQL等等)。
  3. 实现四层负载均衡的软件有:
    • F5:硬件负载均衡器,功能很好,但是成本很高。
    • lvs:重量级的四层负载软件
    • nginx:轻量级的四层负载软件,带缓存功能,正则表达式较灵活
    • haproxy:模拟四层转发,较灵活

七层:

  1. 七层的负载均衡就是基于虚拟的URL或主机IP的负载均衡:在四层负载均衡的基础上(没有四层是绝对不可能有七层的),再考虑应用层的特征,比如同一个Web服务器的负载均衡,除了根据VIP加80端口辨别是否需要处理的流量,还可根据七层的URL、浏览器类别、语言来决定是否要进行负载均衡。举个例子,如果你的Web服务器分成两组,一组是中文语言的,一组是英文语言的,那么七层负载均衡就可以当用户来访问你的域名时,自动辨别用户语言,然后选择对应的语言服务器组进行负载均衡处理。

  2. 对应的负载均衡器称为七层交换机(L7 switch),除了支持四层负载均衡以外,还有分析应用层的信息,如HTTP协议URI或Cookie信息,实现七层负载均衡。此种负载均衡器能理解应用协议。

  3. 实现七层负载均衡的软件有:

    • haproxy:天生负载均衡技能,全面支持七层代理,会话保持,标记,路径转移;
    • nginx:只在http协议和mail协议上功能比较好,性能与haproxy差不多;
    • apache:功能较差
    • Mysql proxy:功能尚可。

总的来说,一般是lvs做4层负载;nginx做7层负载(也能做4层负载, 通过stream模块);haproxy比较灵活,4层和7层负载均衡都能做

参考连接:

https://www.cnblogs.com/kevingrace/p/6137881.html

https://cloud.tencent.com/developer/article/1082047

DNS地域负载均衡

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第20张图片

所谓DNS地域是基于地理的负载均衡

例子: 北方的用户访问北京的机房, 南方的用户访问深圳的机房,DNS负载均衡的本质是DNS解析同一个域名可以访问不同的IP地址

例如: 同样是www.baidu.com,北京用户解析后获取的地址是61.135.165.224(北京机房IP),南方用户解析后获取的地址是14.215.177.38(深圳机房IP)

DNS负载均衡实现简单,成本低,但也存在粒度太粗、负载均衡算法少等缺点。

优点:

  1. 简单、成本低: 负载均衡工作交给DNS服务器处理,无须自己开发或者维护负载均衡设备
  2. 就近访问,提升访问速度: DNS解析时可以根据请求来源IP 解析成距离用户最近的服务器地址,可以加快访问速度,改善性能。

缺点:

  1. 更新不及时:DNS缓存带时间比较长,修改DNS配置厚,由于缓存的原因,还有有很多用户会继续访问修改前的IP,这样带访问会失败, 达不到负载均衡带目的,并且也会影响用户正常的使用。
  2. 扩展性差: DNS负载均衡的控制权在域名商那里,无法根据业务特点针对其做更多的定制化功能和扩展特性。
  3. 分配策略比较简单:DNS负载均衡支持带算法少, 不能区分服务器的差异(无法根据系统与服务状态来判断负载),也无法感知后端服务器带状态。

针对DNS负载均衡带一些缺点,对于延时和故障敏感的业务,有一些公司自己实现了HTTP-DNS的功能

使用Nginx构建服务集群

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第21张图片

upstream指令块的使用

upstream属于handler,只是他不产生自己的内容,而是通过请求后端服务器得到内容,所以才称为upstream(上游)。请求并取得响应内容的整个过程已经被封装到nginx内部,所以upstream模块只需要开发若干回调函数,完成构造请求和解析响应等具体的工作。

  1. 测试三台tomcat是否可以访问

  2. 打开nginx.conf配置文件,再http指令块内部配置upstream指令块(和server同一级)

    # 配置上游服务器

    upstream tomcats {

    ​ # 集群默认负载均衡的策略是轮询,可以在server指令之后加上weight参数变成加权轮询,例如:server 192.168.1.173:8080 weight=3;

    ​ server 192.168.1.173:8080;

    ​ server 192.168.1.174:8080;

    ​ server 192.168.1.175:8080;

    }

  3. 配置一个新的server(可以按需在原来上改)

    server {

    ​ listen 80;

    ​ server_name www.tomcats.com; # 和Hosts文件映射的一致

    ​ location / {

    ​ proxy_pass http://tomcats; # 设置upstream指令块的name

    ​ }

    }

  4. 配置Hosts文件

    在Hosts文件新增或修改以下配置:

    192.168.1.172 www.tomcats.com

  5. 测试访问集群服务

    参考链接:

    upstream官房文档:http://nginx.org/en/docs/stream/ngx_stream_upstream_module.html

    upstream中常用的参数:

    格式:server ip:prot [参数=参数值 ]… ;

    server:负载均衡后端的服务器的IP或域名,不写端口默认是80,高并发场景用域名,再通过DNS进行负载均衡

    weight:后端服务器的权重,默认为1,权重越大接收的请求越多,例如:weight=5

    max_fails:检查节点的健康状态并允许请求失败的次数,达到该次数将节点下线,默认为1,0表示禁止失败尝试,例如:max_fails=2

    fail_timeout:max_fails失败次数达到限制后暂停该节点服务器时间,默认是10秒。

    backup:热备配置,当服务池中所有的服务器出现问题后会自动上线backup服务器。

    down:标志服务器不可用,不参与负载均衡,这个参数通常配合IP_HASH使用。

    max_conns:限制最大连接数,通常对后端服务器硬件不一致的情况进行配置。例如:server 192.168.1.173:8080 max_conns=3;

    slow_start:缓慢启动,服务慢慢的加入集群,不会一下子加入到集群之中,有一个流量从少到多的过程

    keepalive:限制空闲长连接的最大数量。减少连接的创建和关闭,可以提高吞吐量

    修改配置:
    upstream tomcats {
    server 192.168.1.173:8080;

    ​ server 192.168.1.174:8080;

    ​ server 192.168.1.175:8080;

    ​ # 配置保持连接的时间

    ​ keepalive 32;

    }

    server {

    ​ listen 80;

    ​ server_name www.tomcats.com; # 和Hosts文件映射的一致

    ​ location / {

    ​ proxy_pass http://tomcats; # 设置upstream指令块的name

    ​ proxy_http_version 1.1; # 设置http的版本,默认是1.0不支持长连接

    ​ proxy_set_header Connection “”; # 清楚Connection的一些信息

    ​ }

    }

    keepalive_timeout:空闲长连接的最长保持时间。

    keepalive_requests:每个长连接最多可以处理的请求数。

使用ip_hash负载均衡

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第22张图片

  • ip_hash是根据用户请求过来的ip,然后映射成hash值,然后分配到一个特定的服务器里面;
  • 使用ip_hash这种负载均衡以后,可以保证用户的每一次会话都只会发送到同一台特定的Tomcat里面,它的session不会跨到其他的tomcat里面去的;

算法原理

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第23张图片

  • 首先通过将ip地址映射成一个hash值,然后将hash值对Tomcat的数量3取模,得到Tomcat的索引0、1、2;
  • 比如:5%3=2,则把这个请求发送到Tomcat3服务器,以此类推;
  • 这样一来,只要用户的IP不发生改变,当前用户的会话就能够一直保持;
  • nginx的ip_hash算法是取ip地址的前三段数字进行hash映射,如果只有最后一段不一样,也会发送到同一个Tomcat里面

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第24张图片

在upstream中配置ip_hash

upstream tomcats {

​ # 直接添加ip_hash关键字即可,后续同一ip的访问将只会请求同一个服务器。

​ ip_hash; # 新版本中使用 hash $remote_addr;

​ server 192.168.1.173:8080;

​ server 192.168.1.174:8080;

​ server 192.168.1.175:8080;

}

使用ip_hash注意事项

  • 一旦使用了ip_hash,当我们需要移除一台服务器的时候,不能直接删除这个配置项,而是需要在这台服务器配置后面加上关键字down,表示不可用;
  • 因为如果直接移除配置项,会导致hash算法发生更改,后续所有的请求都会发生混乱;

参考链接:

https://blog.csdn.net/qq_36986015/article/details/106373762

hash算法带来的问题

  • 当集群服务的数量发生了变化,则hash算法中取模的值相应会变化,使得每个请求的目标服务真实ip要重新计算

  • 在分布式的存储系统中,要将数据存储到具体的节点上,如果我们采用普通的hash算法进行路由,将数据映射到具体的节点上,如key%N,key是数据的key,N是机器节点数,如果有一个机器加入或退出这个集群,则所有的数据映射都无效了,如果是持久化存储则要做数据迁移,如果是分布式缓存,则其他缓存就失效了。

  • 一致性哈希提出了在动态变化的Cache环境中,哈希算法应该满足的4个适应条件:

均衡性(Balance)

平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。很多哈希算法都能够满足这一条件。

单调性(Monotonicity)

单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲区加入到系统中,那么哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲区中去,而不会被映射到旧的缓冲集合中的其他缓冲区。(这段翻译信息有负面价值的,当缓冲区大小变化时一致性哈希(Consistent hashing)尽量保护已分配的内容不会被重新映射到新缓冲区。)

分散性(Spread)

在分布式环境中,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况显然是应该避免的,因为它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。

负载(Load)

负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第25张图片

  • 按照常用的hash算法来将对应的key哈希到一个具有2^32次方个节点的空间中,即0 ~ (2^32)-1的数字空间中。现在我们可以将这些数字头尾相连,想象成一个闭合的环形。
  • 所有的服务器(Node)的ip地址经过hash之后,分布在环上固定位置,请求用户的ip也hash之后在环上的某一位置,用户被负载均衡访问大于他hash值的第一个节点(顺时针方向第一个)
  • 减少服务器时,访问此节点的所有用户会迁移到此节点的下一个节点,变动的只会有此节点所连接的用户

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第26张图片

  • 新增服务器时,两个节点之间的一部分用户会去访问新的节点

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第27张图片

参考连接:

https://zhuanlan.zhihu.com/p/98030096

使用url_hash负载均衡

把请求的url进行hash然后取模节点数,使访问同一个url的连接都会到固定的服务

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第28张图片

修改配置:

upstream tomcats {

​ hash $request_uri;

​ server 192.168.1.173:8080;

​ server 192.168.1.174:8080;

​ server 192.168.1.175:8080;

}

使用least_conn负载均衡

用户请求会被转发到请求数量最少的服务

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第29张图片

修改配置:

upstream tomcats {

​ least_conn;

​ server 192.168.1.173:8080;

​ server 192.168.1.174:8080;

​ server 192.168.1.175:8080;

}

使用JMeter进行服务压力测试

  • JMeter官网:https://jmeter.apache.org/
  • JMeter下载地址:https://jmeter.apache.org/download_jmeter.cgi

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第30张图片

  1. 下载至本地后,解压压缩包,点击进入bin文件夹,双击jmeter.bat文件,会启动JMeter GUI工具

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第31张图片

  1. 选择Options --> Choose Language --> Chinese(Simplified),设置语言为中文简体
  2. 创建线程组

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第32张图片

  1. 设置线程组参数

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第33张图片

线程数:同时开启的线程数量

循环次数:所有线程进行循环的数量

  1. 设置取样器

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第34张图片

  1. 设置http请求的内容

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第35张图片

协议:http或https

服务器名称或IP:服务所在服务器的ip

端口:服务的端口

HTTP请求:设置请求的类型,get/post/delete/put等

路径:这个请求的路径

参数:设置请求携带的参数

  1. 创建监听器,用于查看测试结果或测试报告

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第36张图片

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第37张图片

创建查看结果树、聚合报告、用表格查看结果三个监听器

  1. 保存测试计划,点击播放按钮开始测试,点击监听器查看测试结果,点击扫帚清除测试结果

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第38张图片

  1. 使用JMeter测试单个服务和集群服务会发现异常率大幅度降低

参考链接:

https://blog.csdn.net/tianqingmuyu/article/details/108401543

Nginx控制浏览器缓存

什么是缓存

前端缓存可分为两大类:http缓存和浏览器缓存。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第39张图片

浏览器缓存就是把一个已经请求过的Web资源(如html页面,图片,js,数据等)拷贝一份副本储存在浏览器中。缓存会根据进来的请求保存输出内容的副本。当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。

比如说,在页面请求之后,web资源都被缓存了,在后面的重复请求中,许多资源都是直接从缓存中读取的(from cache),而不是重新去向服务器请求。

http缓存指的是: 当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提取而不是从原始服务器中提取这个资源。

常见的http缓存只能缓存get请求响应的资源,对于其他类型的响应则无能为力,所以后续说的请求缓存都是指GET请求。

http缓存都是从第二次请求开始的。第一次请求资源时,服务器返回资源,并在respone header头中回传资源的缓存参数;第二次请求时,浏览器判断这些请求参数,命中强缓存就直接200,否则就把请求参数加到request header头中传给服务器,看是否命中协商缓存,命中则返回304,否则服务器会返回新的资源。

参考连接:

https://blog.csdn.net/weixin_43277643/article/details/84143239

https://www.jianshu.com/p/227cee9c8d15

尝试访问Nginx中的静态资源

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第40张图片

当请求Nginx转发的静态资源时,响应头里会有几个参数:

  • Cache-Control 缓存时间
  • Expires 过期时间(Expires = Date + Cache-Control)
  • Date 当前时间
  • Last-Modified 最后一次修改时间

当第一次请求的时候,network中返回的是200,再次请求,缓存没有过期,返回的是304;浏览器debug的时候可以选Disable cache来禁用缓存,这样每次请求都会是重新到服务器获取最新文件

Nginx设置静态资源缓存到浏览器

  1. 打开nginx.conf配置文件

  2. 找到需要配置的server指令块里面的location指令块

    修改配置,加入以下配置:

    location / {

    ​ root html;

    ​ index index.html index.htm;

    ​ expires 10s; # 设置浏览器访问这个location的资源时缓存10s expires [time]

    }

  3. 尝试访问静态资源,会发现响应头里面Cache-Control参数已经根据相应配置发生了变化

    expires 设置缓存的多种方式:

    格式 解释
    expires [time] 设置缓存在time持续时间后失效
    expires @[time] 设置缓存在time时间点后失效
    expires -[time] 设置缓存在time时间之前失效,Cache-Control值会变成no-cache,表示缓存失效
    expires epoch 设置缓存失效,Cache-Control值会变成no-cache
    expires off 默认设置,代表关闭缓存设置,浏览器也有默认的缓存机制
    expires max 设置过期时间为最长

Nginx设置上游服务器静态资源缓存到Nginx

  1. 打开nginx.conf配置文件

  2. 找到server指令块,在指令块上方加入配置:

    # proxy_cache_path 设置缓存保存的目录

    # keys_zone 设置共享内存以及占用空间大小

    # max_size 设置缓存大小

    # inactive 超过此时间,则缓存自动清理

    # use_temp_path 关闭临时目录,开启可能会对性能有影响

    proxy_cache_path /usr/local/nginx/upstream_cache keys_zone=mycache:5m max_size=1g inactive=8h use_temp_path=off

  3. 设置需要使用缓存的server指令块,在内部location指令块之前加入配置:

    # 开启并且使用缓存,是刚才定义的keys_zone参数值内容

    proxy_cache mycache;

    # 针对200和304状态码的缓存设置过期时间

    proxy_cache_valid 200 304 8h;

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第41张图片

Nginx配置HTTPS域名证书

超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此,HTTP协议不适合传输一些敏感信息,比如:信用卡号、密码等支付信息。

为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS,为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。而且应用商店上架应用需要要求https。

HTTP和HTTPS的基本概念

HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

HTTP与HTTPS的区别

HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。

HTTPS和HTTP的区别主要如下:

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

HTTPS的工作原理

HTTPS能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第42张图片

(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。

(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。

(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。

(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。

(5)Web服务器利用自己的私钥解密出会话密钥。

(6)Web服务器利用会话密钥加密与客户端之间的通信。

参考资料:

https://www.cnblogs.com/wqhwe/p/5407468.html

申请证书并配置Nginx配置文件

  1. 打开腾讯云可以查看帮助文档

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第43张图片

  1. 登录用户进入控制台,在云产品中找到SSL证书,在申请证书之前需要有一个域名,证书和域名是绑定在一起的

  2. 点击申请免费证书,免费证书只能为一级域名提供服务,二级域名和三级域名都不行;付费证书则没有这个限制,功能更强大

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第44张图片

  1. 一般选择申请亚洲诚信的证书,也可以选择自己喜欢的,之后输入相关信息或选择对应的选项

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第45张图片

  1. 证书申请审核完成之后,可以下载证书
  2. 解压并选择自己需要配置使用证书的服务,这里使用Nginx

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第46张图片

  1. 上传证书文件到Nginx的conf目录下

  2. 进入到Nginx安装时解压后的文件夹目录下,进入objs,打开ngx_modules.c文件,搜索关键字ssl(输入/ssl),搜索得到说明安装时已经安装了ssl模块,没有搜索到说明未安装相应模块。已安装则跳转到12步

  3. 重新配置并编译Nginx参数(原来的configure命令最后加上 –with-http_ssl_module

    举例:

    ./configure \

    –prefix=/usr/local/nginx \

    –pid-path=/var/run/nginx/nginx.pid \

    –lock-path=/var/lock/nginx.lock \

    –error-log-path=/var/log/nginx/error.log \

    –http-log-path=/var/log/nginx/access.log \

    –with-http_gzip_static_module \

    –http-client-body-temp-path=/var/temp/nginx/client \

    –http-proxy-temp-path=/var/temp/nginx/proxy \

    –http-fastcgi-temp-path=/var/temp/nginx/fastcgi \

    –http-uwsgi-temp-path=/var/temp/nginx/uwsgi \

    –http-scgi-temp-path=/var/temp/nginx/scgi \

    –with-http_ssl_module

  4. 编译安装:make && make install

  5. 重新查看ngx_modules.c里面是否有ssl模块,或者使用./nginx -V查看

  6. 配置nginx.conf配置文件,拷贝需要配置https的server到原来的server配置下方,修改监听端口为443(固定)

  7. 在新的server内server_name参数下方加入以下配置

    参考腾讯云配置ssl教程:

    # 开启ssl

    ssl on;

    # 配置ssl证书路径(相对路径或绝对路径)

    ssl_certificate xxxxx.crt;

    # 配置证书密钥

    ssl_certificate_key xxxxx.key;

    # ssl会话cache

    ssl_session_cache chared:SSL:1m;

    # ssl会话超时时间

    ssl_session_timeout 5m;

    # 配置加密套件,,写法遵循openssl标准

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;

    ssl_prefer_server_ciphers on;

  8. 重启Nginx,尝试使用https访问服务

    ./nginx -s reload

Nginx动静分离

什么是动静分离

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第47张图片

动静分离是指在web服务器架构中,将静态页面与动态页面或者静态内容接口和动态内容接口分开不同系统访问的架构设计方法,进而提升整个服务访问性能和可维护性。静态资源包括:html/css/js/图片/音视频等,你想要其展示不同的内容必须手动去修改文件的东西。动态资源包括:模板引擎/动态接口等,根据传入参数不同返回不同的数据。对于前后端分离的架构,前后端分离之后,一般情况下动态资源和静态资源自然也就分离了。

动静分离和前后分离的区别

动静分离:动态资源(jsp、ftl、thymeleaf)与静态资源(js、css、img)分开部署。

前后分离:接口与视图分开部署,专业的人做专业的事情。例如:前端使用vue.js,后端只需要提供接口即可。前端项目与后端项目都是独立部署的。

如果我们静态资源与动态资源存放在同一台服务器上面,当静态资源不断增多的时候,我们的服务器访问是扛不住,因为静态资源消耗过多的带宽,导致静态资源无法访问或者访问非常的慢。在一个网站中,静态资源(js、css、img)是比较占宽带资源的,动态资源占带宽很小。1M带宽=128k/s

使用CDN动静分离

传统的http访问过程是用户在浏览器填入要访问的域名,浏览器调用域名解析函数库对域名进行解析,以得到此域名对应的IP地址;

再通过IP地址向域名的服务主机发出数据访问请求,得到请求数据,最终返回所需要的内容。

CDN的基本思路则是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,通过在网络各处放置节点服务器构成在现有互联网基础之上的智能虚拟网络。

CDN系统能够实时地根据网络流量和各节点的连接、负载状况,以及到用户的距离和响应时间等综合信息,将用户的请求重新导向离用户最近的服务节点。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第48张图片

CDN访问具体流程

  1. 当浏览器调用域名解析库对域名进行解析,由于CDN对域名解析过程进行了调整,所以解析函数库一般得到的是该域名对应的CNAME记录,为了得到实际IP地址,浏览器需要再次对获得的CNAME域名进行解析以得到实际的IP地址

  2. 在此过程中,使用全局负载均衡DNS解析,并根据地理位置信息解析对应的IP地址,使得用户能就近访问

  3. 此次解析得到CDN缓存服务器的IP地址,浏览器在得到实际的IP地址以后,向缓存服务器发出访问请求;

  4. 缓存服务器根据浏览器提供的要访问的域名,通过Cache内部专用DNS解析得到此域名的实际IP地址,再由缓存服务器向此实际IP地址提交访问请求;

  5. 缓存服务器从实际IP地址得到内容以后,一方面在本地进行保存,以备以后使用,另一方面把获取的数据返回给客户端,完成数据服务过程;

  6. 客户端得到由缓存服务器返回的数据后显示出来并完成整个浏览的数据请求过程。

CDN的关键技术

典型的CDN系统由分发服务系统,负载均衡系统和运营管理系统组成,其中最核心的当属负载均衡系统。

负载均衡系统负责对所有发起服务请求的用户进行访问调度,确定提供给用户的最终实际访问地址。两级调度体系分为全局负载均衡本地负载均衡

全局负载均衡主要根据用户就近性原则,通过对每个服务节点进行“最优”判断,确定向用户提供服务的cache的物理位置。本地负载均衡主要负责节点内部的设备负载均衡。

当下的视频、直播等内容分发渠道已成为企业争夺流量的主战场,CDN作为网络基础应用设施,自始至终都发挥着不可或缺的作用。

CDN不仅可以降低延时,提高稳定性,还起到了缓解服务器带宽压力和保护源站服务器的作用。即便是针对动态内容的恶意请求,CDN的调度系统也可以卸载源站服务器压力,维护系统平稳。

使用Nginx动静分离

用户请求Nginx时有多种请求,一级域名(www.imooc.com)访问时获取的都是静态数据,二级域名(api.imooc.com)访问时获取的都是动态数据(接口数据)。

静态资源数据可以直接放在Nginx中,也可以用Nginx的upstream再挂一组Nginx的上游服务器,可以实现静态资源的负载均衡和集群。

Nginx还可以让二级域名所访问的内容跳转到Tomcat组建集群的上游服务器。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第49张图片

  1. 安装Nginx(参考之前内容)

  2. 配置反向代理api接口(详细配置解释请看之前内容)

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第50张图片

  1. 配置代理转发静态资源(详细配置解释请看之前内容)

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第51张图片

  1. 假如刚才配置是独立的配置文件,则需要在主配置文件中引入(这里使用的是相对路径)

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第52张图片

  1. 测试转发服务是否能正常使用,接口是否能请求成功,若有跨域等问题请查看前方内容

Keepalived的介绍和使用

网络设备、服务器、应用、数据库等的规划建设时,必须要考虑软硬件系统的冗余度和高可用性,避免出现单点故障的情况。

通过nginx代理服务器,可以对后端的具体应用实现反向代理或负载均衡等功能,并且nginx可以对应用进行健康检查,将故障节点从负载均衡池中排出,从而实现对后端应用的高可用性保障。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第53张图片

但是,如果nginx服务器出现问题,则无法对外提供服务。因此,我们要考虑到nginx服务的高可用性,采用主-备,或主-主的形式安装部署nginx服务,nginx的主备高可用性,依靠keepalived组件实现。

主机不仅负责对后端两台服务进行健康检查,并且对外提供服务,接受客户端的请求,如图中红线所示;备机尽对后端服务进行健康检查,不对外提供服务,当主机故障发生切换时,才接管工作,客户端访问nginx服务器集群的虚拟IP。

综上所述,nginx的主备高可用性需要:

  1. 两台Nginx服务器

  2. 服务器都需要安装keepalived组件

  3. 对外提供服务的虚拟IP地址

什么是keepalived

Keepalived是Linux下一个轻量级别的高可用解决方案。高可用(High Avalilability,HA),其实两种不同的含义:广义来讲,是指整个系统的高可用行,狭义的来讲就是之主机的冗余和接管。

它与HeartBeat RoseHA 实现相同类似的功能,都可以实现服务或者网络的高可用,但是又有差别,HeartBeat是一个专业的、功能完善的高可用软件,它提供了HA 软件所需的基本功能,比如:心跳检测、资源接管,检测集群中的服务,在集群节点转移共享IP地址的所有者等等。HeartBeat功能强大,但是部署和使用相对比较麻烦,与HeartBeat相比,Keepalived主要是通过虚拟路由冗余来实现高可用功能,虽然它没有HeartBeat功能强大,但是Keepalived部署和使用非常的简单,所有配置只需要一个配置文件即可以完成。

总结:

  1. 可以解决单点故障
  2. 组件免费
  3. 可以实现高可用HA机制
  4. 基于VRRP协议

参考连接:

https://www.cnblogs.com/yanjieli/p/10683751.html

https://www.cnblogs.com/AbnerLc/p/11898289.html

https://blog.csdn.net/LLcmpgheng/article/details/100118829

keepalived的工作原理

keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议。

虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个master和多个backup,master上面有一个对外提供服务的vip(该路由器所在局域网内其他机器的默认路由为该vip),master会发组播,当backup收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master。这样的话就可以保证路由器的高可用了。

keepalived主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第54张图片

虚拟路由冗余协议VRRP

VRRP全称Virtual Router Redundancy Protocol

主机将发送给外部网络的报文发送给网关,由网关传递给外部网络,从而实现主机与外部网络的通信。正常的情况下,主机可以完全信赖网关的工作,但是当网关坏掉时,主机与外部的通信就会中断。要解决网络中断的问题,可以依靠再添加网关的方式解决,不过由于大多数主机只允许配置一个默认网关,此时需要网络管理员进行手工干预网络配置,才能使得主机使用新的网关进行通信;有时,人们运用动态路由协议的方法来解决网络出现故障这一问题,如运行RIP、OSPF等,或者使用IRDP。然而,这些协议由于配置过于复杂,或者安全性能不好等原因都不能满足用户的需求。

为了更好地解决网络中断的问题,网络开发者提出了VRRP,它既不需要改变组网情况,也不需要在主机上做任何配置,只需要在相关路由器上配置极少的几条命令,就能实现下一跳网关的备份,并且不会给主机带来任何负担。和其他方法比较起来,VRRP更加能够满足用户的需求。

VRRP是一种路由容错协议,也可以叫做备份路由协议。一个局域网络内的所有主机都设置缺省路由,当网内主机发出的目的地址不在本网段时,报文将被通过缺省路由发往外部路由器,从而实现了主机与外部网络的通信。当缺省路由器down掉(即端口关闭)之后,内部主机将无法与外部通信,如果路由器设置了VRRP时,那么这时,虚拟路由将启用备份路由器,从而实现全网通信。

在VRRP协议中,有两组重要的概念:VRRP路由器和虚拟路由器,主控路由器和备份路由器。VRRP路由器是指运行VRRP的路由器,是物理实体;虚拟路由器是指VRRP协议创建的,是逻辑概念。一组VRRP路由器协同工作,共同构成一台虚拟路由器。该虚拟路由器对外表现为一个具有唯一固定的IP地址和MAC地址的逻辑路由器。处于同一个VRRP组中的路由器具有两种互斥的角色:主控路由器和备份路由器,一个VRRP组中有且只有一台处于主控角色的路由器,可以有一个或者多个处于备份角色的路由器VRRP协议从路由器组中选出一台作为主控路由器,负责ARP解析和转发IP数据包,组中的其他路由器作为备份的角色并处于待命状态,当由于某种原因主控路由器发生故障时,其中的一台备份路由器能在瞬间的时延后升级为主控路由器,由于此切换非常迅速而且不用改变IP地址和MAC地址,故对终端使用者系统是透明的。

总结:

  1. 这是一种容错协议,目的是解决网络中单点故障的问题
  2. 主备路由器使用时,需要配置虚拟出一个相同的IP地址(VIP)并和此节点绑定在一起,用于作为网络访问的入口,正常情况下主节点获得所有的访问流量,备用节点没有流量
  3. 当主节点失效时候,多个备用节点通过选举机制选出下一个主节点(可以配置权重)
  4. 原来的主节点重新加入时,当前主节点失效,所有的流量又会回到原来的主节点
  5. 主备节点之间是通过心跳机制来检测节点是否失效

参考连接:

https://blog.csdn.net/zhongzh86/article/details/81537644

https://baike.baidu.com/item/%E8%99%9A%E6%8B%9F%E8%B7%AF%E7%94%B1%E5%99%A8%E5%86%97%E4%BD%99%E5%8D%8F%E8%AE%AE/2991482?fromtitle=VRRP&fromid=932628&fr=aladdin

安装并配置Keepalived

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第55张图片

准备两台服务器171、172里面安装好Nginx,分别给两台服务器装好Keepalived之后会设定虚拟ip为161。

下载keepalived

  1. 进入官网https://www.keepalived.org/

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第56张图片

  1. 点击download(https://www.keepalived.org/download.html),选择任意版本

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第57张图片

  1. 检查压缩包里面是否有一个configure文件

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第58张图片

安装keepalived

  1. 上传tar包到服务器

  2. 解压tar包

    tar -zxvf keepalived-2.0.18.tar.gz

  3. 进入解压好的文件夹

    cd keepalived-2.0.18/

  4. 配置编译参数,生成Makefile文件

    ./configure --prefix=/usr/local/keepalived --sysconf=/etc

    命令 解释
    –prefix keepalived安装位置
    –sysconf 核心配置文件地址,必须在/etc。若不在/etc下,会在日志文件中报错提示:在/etc下找不到配置文件
  5. 配置过程中可能会出现一个警告,提示需要安装libnl/libnl-3的依赖,安装一下即可

    yum -y install libnl libnl-devel

  6. 编译安装keepalived

    make && make install

  7. 检查keepalived安装位置

    whereis keepalived

    一般会返回两个位置:

    /usr/local/keepalived 启动命令sbin文件夹所在的文件夹

    /etc/keepalived 核心配置文件所在的文件夹

使用yum安装keepalived

  1. 安装依赖包

    yum install -y curl gcc openssl-devel libnl3-devel net-snmp-devel

  2. 安装keepalived

    yum install -y keepalived

    相关命令:

    systemctl start keepalived //启动keepalived

    systemctl enable keepalived //加入开机启动keepalived

    systemctl restart keepalived //重新启动keepalived

    systemctl status keepalived //查看keepalived状态

    参考链接:

    https://blog.csdn.net/qq_28834355/article/details/109106807

配置主节点keepalived

  1. 进入/etc/keepalived文件夹

  2. 打开配置文件

    vim /etc/keepalived/keepalived.conf

    
    # 全局配置
    global_defs {
       # 邮件通知信息
       notification_email {
         # 定义收件人
         acassen@firewall.loc
       }
       # 定义发件人
       notification_email_from Alexandre.Cassen@firewall.loc
       # SMTP服务器地址
       smtp_server 192.168.200.1
       smtp_connect_timeout 30
       # 路由器标识,一般不用改,也可以写成每个主机自己的主机名
       router_id LVS_DEVEL
       # VRRP的ipv4和ipv6的广播地址,配置了VIP的网卡向这个地址广播来宣告自己的配置信息,下面是默认值
       vrrp_mcast_group4 224.0.0.18
       vrrp_mcast_group6 ff02::12
    }
    
    # 定义用于实例执行的脚本内容,比如可以在线降低优先级,用于强制切换
    vrrp_script SCRIPT_NAME {
    
    }
    
    # 一个vrrp_instance就是定义一个虚拟路由器的,实例名称
    vrrp_instance VI_1 {
        # 定义初始状态,可以是MASTER或者BACKUP
        state MASTER
        # 工作接口,通告选举使用哪个接口进行
        interface ens33
        # 虚拟路由ID,如果是一组虚拟路由就定义一个ID,如果是多组就要定义多个,而且这个虚拟
        # ID还是虚拟MAC最后一段地址的信息,取值范围0-255
        virtual_router_id 51
        # 使用哪个虚拟MAC地址
        use_vmac XX:XX:XX:XX:XX
        # 监控本机上的哪个网卡,网卡一旦故障则需要把VIP转移出去
        track_interface {
            eth0
            ens33
        }
        # 如果你上面定义了MASTER,这里的优先级就需要定义的比其他的高
        priority 100
        # 通告频率,单位为秒
        advert_int 1
        # 通信认证机制,这里是明文认证还有一种是加密认证
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        # 设置虚拟VIP地址,一般就设置一个,在LVS中这个就是为LVS主机设置VIP的,这样你就不用自己手动设置了
        virtual_ipaddress {
            # IP/掩码 dev 配置在哪个网卡
            192.168.200.16/24 dev eth1
            # IP/掩码 dev 配置在哪个网卡的哪个别名上
            192.168.200.17/24 dev label eth1:1
        }
        # 虚拟路由,在需要的情况下可以设置lvs主机 数据包在哪个网卡进来从哪个网卡出去
        virtual_routes {
            192.168.110.0/24 dev eth2
        }
        # 工作模式,nopreempt表示工作在非抢占模式,默认是抢占模式 preempt
        nopreempt|preempt
        # 如果是抢占默认则可以设置等多久再抢占,默认5分钟
        preempt delay 300
        # 追踪脚本,通常用于去执行上面的vrrp_script定义的脚本内容
        track_script {
    
        }
        # 三个指令,如果主机状态变成Master|Backup|Fault之后会去执行的通知脚本,脚本要自己写
        notify_master ""
        notify_backup ""
        notify_fault ""
    }
    
    # 定义LVS集群服务,可以是IP+PORT;也可以是fwmark 数字,也就是防火墙规则
    # 所以通过这里就可以看出来keepalive天生就是为ipvs而设计的
    virtual_server 10.10.10.2 1358 {
        delay_loop 6
        # 算法
        lb_algo rr|wrr|lc|wlc|lblc|sh|dh 
        # LVS的模式
        lb_kind NAT|DR|TUN
        # 子网掩码,这个掩码是VIP的掩码
        nat_mask 255.255.255.0
        # 持久连接超时时间
        persistence_timeout 50
        # 定义协议
        protocol TCP
        # 如果后端应用服务器都不可用,就会定向到那个服务器上
        sorry_server 192.168.200.200 1358
    
        # 后端应用服务器 IP PORT
        real_server 192.168.200.2 1358 {
            # 权重
            weight 1
            # MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET这些都是
            # 针对应用服务器做健康检查的方法
            MISC_CHECK {}
            # 用于检查SMTP服务器的
            SMTP_CHEKC {}
    
            # 如果应用服务器不是WEB服务器,就用TCP_CHECK检查
            TCP_CHECK {
              # 向哪一个端口检查,如果不指定默认使用上面定义的端口
              connect_port <PORT>
              # 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
              bindto <IP>
              # 连接超时时间
              connect_timeout 3
            }
    
            # 如果对方是HTTPS服务器就用SSL_GET方法去检查,里面配置的内容和HTTP_GET一样
            SSL_GET {}
    
            # 应用服务器UP或者DOWN,就执行那个脚本
            notify_up "这里写的是路径,如果脚本后有参数,整体路径+参数引起来"
            notify_down "/PATH/SCRIPTS.sh 参数"
    
            # 使用HTTP_GET方法去检查
            HTTP_GET {
                # 检测URL
                url { 
                  # 具体检测哪一个URL
                  path /testurl/test.jsp
                  # 检测内容的哈希值
                  digest 640205b7b0fc66c1ea91c463fac6334d
                  # 除了检测哈希值还可以检测状态码,比如HTTP200 表示正常,两种方法二选一即可
                  status_code 200
                }
                url { 
                  path /testurl2/test.jsp
                  digest 640205b7b0fc66c1ea91c463fac6334d
                }
                url { 
                  path /testurl3/test.jsp
                  digest 640205b7b0fc66c1ea91c463fac6334d
                }
                # 向哪一个端口检查,如果不指定默认使用上面定义的端口
                connect_port <PORT>
                # 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
                bindto <IP>
                # 连接超时时间
                connect_timeout 3
                # 尝试次数
                nb_get_retry 3
                # 每次尝试之间间隔几秒
                delay_before_retry 3
            }
        }
    
        real_server 192.168.200.3 1358 {
            weight 1
            HTTP_GET {
                url { 
                  path /testurl/test.jsp
                  digest 640205b7b0fc66c1ea91c463fac6334c
                }
                url { 
                  path /testurl2/test.jsp
                  digest 640205b7b0fc66c1ea91c463fac6334c
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
            }
        }
    }
    

    keepalived的配置文件都是以块的形式组织的,每个块的内容包含在{}中,配置分为三类:全局配置,VRRPD配置和LVS配置。


    全局配置:对整个keepalived都生效的配置

    global_defs {
         notification_email {
         acassen@firewall.loc
         failover@firewall.loc
         sysadmin@firewall.loc
       }
         notification_email_from Alexandre.Cassen@firewall.loc
         smtp_server 192.168.200.1
         smtp_connect_timeout 30
         router_id LVS_DEVEL
    }
    
    1. global_defs指令块:配置全局配置
      1. notification_email:设置报警邮件地址即报警邮件接收者,可设置多个,每行一个;如果要开启邮件报警功能,需要开启本机的postfix或者sendmail服务;当master出现故障时backup进行切换时,会向配置的邮件地址发送通知;除了配置邮件地址之外,下方还要配置邮件发送的协议等配置。
      2. notification_email_from:用于设置邮件的发送地址,即报警邮件发送者;
      3. smtp_server:用于设置邮件的SMTP Server地址;
      4. smtp_connect_timeout:设置连接SMTP Server的超时时间;
      5. router_id:表示运行keepalived服务器的一个标识,是发邮件时显示在邮件主题中的信息;

    VRRPD配置:这时keepalived的核心,主要用来实现keepalived的高可用功能。VRRPD配置又可分为VRRP同步组配置和VRRP实例配置

    vrrp_sync_group G1 {
        group {
            VI_1
            VI_2
            VI_5
        }
        notify_backup "/usr/local/bin/vrrp.bak arg1 arg2"
        notify_master "/usr/local/bin/vrrp.mast arg1 arg2"
        notify_fault "/usr/local/bin/vrrp.fault arg1 arg2"
        notify_stop "/usr/local/bin/vrrp.stop arg1 arg2"
    }
    vrrp_sync_group G2 {
        group {
            VI_3
            VI_4
        }
    }
    其中:
    G1同步组包含VI_1VI_2VI_5三个VRRP实例,G2同步组包含VI_3VI_4两个实例,这5个实例将在vrrp_instance段进行定义
    
    1. vrrp_sync_group:VRRP同步组
      同步组是相对于多个VRRP实例而言的,在多个VRRP实例的环境中,每个VRRP实例所对应的网络环境会有所不同,假设一个实例处于网段A,另一个实例处于网段B,而如果VRRPD只配置了A网段的检测,那么当B网段主机出现故障时,VRRPD会认为自己仍处于正常状态,不会进行主备节点切换,这样问题就出现了。而同步组会将所有VRRP实例都加入同步组中,这样任何一个实例出现问题,都会导致keepalived进行主备切换;
      1. keepalived配置中的一个通知机制,也是keepalived包含的四种状态:
      2. notify_master:指定当keepalived进入MASTER状态时要执行的脚本,这个脚本可以是一个状态报警脚本,也可以是一个服务管理脚本,允许传入参数;
      3. notify_backup:指定当keepalived进入BACKUP状态时要执行的脚本;
      4. notify_fault:指定当keepalived进入FAULT状态时要执行的脚本;
      5. notify_stop:指定当keepalived程序终止时需要执行的脚本;
    vrrp_instance VI_1 {
        state MASTER
        interface eth0
        virtual_router_id 51
        priority 100
        advert_int 1
        mcast_src_ip
        garp_master_delay 10
    
        track_interface {
            eth0
            eth1
        }
    
        authentication {
            auth_type PASS
            auth_pass 1111
        }
    
        virtual_ipaddress {
            192.168.200.16
            192.168.200.17 dev eth1
            192.168.200.18 dev eth2
        }
    
        virtual_routers {
            src 192.168.100.1 to 192.168.109.0/24 via 192.168.200.254 dev eth1
            192.168.110.0/24 via 192.168.200.254 dev eth1
            192.168.111.0/24 dev eth2
            192.168.112.0/24 via 192.168.100.254
            192.168.113.0/24 via 192.168.100.252 or 192.168.100.253
        }
    
        nopreempt
        preemtp_delay 300
    }
    
    1. vrrp_instance:VRRP实例配置即keepalived的高可用功能
      VRRP实例段主要用来配置节点角色(主从),实例绑定端口,节点间验证机制,集群服务IP等
      1. vrrp_instance:是VRRP实例的标识,后跟VRRP实例名称;
      2. state:用于指定keepalived的角色,MASTER表示主服务器,BACKUP表示备用服务器;
      3. interface:用于指定HA监测网络的接口;
      4. virtual_router_id:虚拟路由标识,是一个数字,同一个VRRP实例使用唯一的标识,即在同一个vrrp_instance下,MASTER和BACKUP必须是一致的;
      5. priority:节点优先级,数字越大优先级越高(在一个VRRP_instance下,MASTER的优先级必须大于BACKUP的优先级);
      6. advert_int:用于设定MASTER与BACKUP主机之间同步检查的时间间隔,单位秒;
      7. mcast_src_ip:用于设置发送多播包的地址,若不设置,将使用绑定网卡对应的IP地址;
      8. garp_master_delay:用于设置在切换到MASTER状态后延时进行Gratuitous arp请求的时间;
      9. track_interface:用于设置一些额外的网络监控接口,其中任何一个接口出现故障,keepalived都会进入FAULT状态;
      10. authentication:用于设定节点间通信验证码类型和密码 ,主要类型有PASS和AH两种,在一个vrrp_instance下,MASTER和BACKUP必须使用相同的密码才能正常通信;
      11. virtual_ipaddress:用于设置虚拟IP地址(VIP),可设置多个,每行一个;keepalived通过ip address add命令的形式将VIP添加进系统中,而且IP形式可多样;
      12. virtual_routers:和virtual_ipaddress段一样,用来设置在切换时添加或删除相关路由信息;
      13. nopreempt:设置高可用集群不抢占功能;在使用不抢占时,只能在state状态为BACKUP的节点上设置,而且这个节点的优先级必须高于其他节点
      14. preemtp_delay:用于设置抢占的延时时间,单位秒,如系统启动或重启之后网络需要经过一段时间才能正常工作,这时进行主备切换是没有必要的,此选项就是来设置这种情况发生的时间间隔;

    keepalived的LVS配置:LVS配置段以virtual_server为开始标识,此段分为两部分:real_server段和健康检测段

    virtual_server 192.168.12.200 80 {
        delay_loop 6 
        lb_algo rr
        lb_kind DR
        persistence_timeout 50 
        persistence_granularity
        protocol TCP
        ha_suspend
        virtualhost
        sorry_server
        real_server 192.168.12.132 80 {
            weight 3
            inhibit_on_failure
            TCP_CHECK {
                connect_port 80
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
            }
            notify_up ''
            notify_down ''
            
            HTTP_GET | SSL_GET {
                url {
                    path /index.html
                    digest e6c271eb5f017f280cf97ec2f51b02d3
                    status_code 200 
                }
                connect_port 80
                bindto 192.168.12.80
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 2
            }
        }
    }
    
    1. virtual_server:配置lvs服务

      1. virtual_server:设置虚拟服务器开始的标识,后跟虚拟IP地址空格符服务端口;
      2. delay_loop:设置健康检查的时间间隔,单位秒;
      3. lb_algo:设置负载调度算法,常用的有rr,wrr,lc,wlc等;
      4. lb_kind:设置LVS实现负载均衡的机制,有NAT,TUN和DR模式;
      5. persistence_timeout:会话保持时间,单位秒,该选项使用户的请求会一直分发到某个服务节点,直到超过这个会话的保持时间;
      6. persistence_granularity:配合persistence_timeout使用,后面跟的值是子网掩码,表示持续连接的粒度,默认是255.255.255.255即一个单独的客户端IP,如果改为255.255.255.0那么客户端所在的整个网段的请求都会分发到同一台realserver上;
      7. protocol:指定转发协议类型,有TCP和UDP两种选型;
      8. ha_suspend:节点状态从MASTER到BACKUP切换时,暂不启用real server节点的健康检查;
      9. virtualhost:再通过HTTP_GET/SSL_GET做健康检测时,指定的web服务器的虚拟主机地址;
      10. sorry_server:相当于一个备用节点,在所有realserver失效后,启用这个节点,
      11. real_server:随之real_server段开始的标识,用来指定real server节点,后跟real server的真实IP地址和端口(有空格)
        1. weight:配置real server节点的权值,数字越大权值越高;
        2. inhibit_on_failure:表示在检测到real server节点失效后,把他的weight值置为0,而不是从IPVS中删除;
        3. TCP_CHECK:健康检测段的检查方式,常见的有HTTP_GET,SSL_GET,TCP_CHECK,SMTP_CHECK,MISC_CHECK
          1. connect_port:健康状态检查的端口,如果不指定,默认是real_server指定的端口;
          2. connect_timeout:表示无响应超时时间,单位秒;
          3. nb_get_retry:重试次数;
          4. delay_before_retry:重试间隔时间;
        4. notify_up:和notify_master相同,后跟一个脚本,表示在检测到real server节点服务处于UP状态后只执行的脚本;
        5. notify_down:表示在检测到real server节点服务处于DOWN状态后只执行的脚本;
        6. HTTP_GET和SSL_GET检测方式
          1. url:用来指定HTTP/SSL检查的URL信息,可指定多个URL;
          2. path:后跟详细的URL路径;
          3. digest:SSL检查后的摘要信息,可通过genhash命令获取,如genhash -s 192.168.12.80 -p 80 -u /index.html
          4. status_code:指定HTTP检查返回正常状态吗的类型,一般为200;
          5. bindto:表示通过此地址来发送请求对服务器进行健康检查;
    2. 补充:

      1. keepalived集群中MASTER和BACKUP角色选举策略:

        • 在keepalived集群中,其实并没有严格意义上的主备节点,虽然可以在配置文件中设置MASTER状态,但是这并不意味着此节点一直就是MASTER状态。控制节点角色的是配置文件中的priority值,但它并不控制所有节点的角色,另一个能改变角色的是在vrrp_script模块中设置的weight值,这两个选项的值嗾使整数值(weight可以为负整数),一个节点在集群中的角色就是通过这两个值的大小决定的;在vrrp_script模块中,如果不设置weight的值,那么集群优先级的选择将由配置文件中的priority值决定;
      2. 使用vrrp_script模块时集群角色的选举算法

        1. weight值为正数时
          在vrrp_script中指定的脚本如果检测成功,那么MASTER节点的权值将是weight值与priority值之和;如果检测失败,那么MASTER节点的权值保持为priority值,因此,切换策略为:

          • MASTER节点vrrp_script脚本检测失败时,如果MASTER节点priority值小于BACKUP节点weight值与priority值之和,将发生主备切换;
          • MASTER节点vrrp_script脚本检测成功时,如果MASTER节点weight值与priority之和大于BACKUP节点weight值与priority值之和,主节点依然为主节点,不发生切换;
        2. weight值为负数时
          在vrrp_script中指定的脚本如果检测成功,那么MASTER节点的权值仍是priority值;如果检测失败,那么MASTER节点的权值将是priority值与weight值之差,因此,切换策略为:

          • MASTER节点vrrp_script脚本检测失败时,如果MASTER节点priority值与weight值之差小于BACKUP节点的priority值,将发生主备切换;
          • MASTER节点vrrp_script脚本检测成功时,如果MASTER节点priority值大于BACKUP节点priority值时,主节点依然为主节点,不发生切换;

    参考链接:

    https://www.cnblogs.com/yanjieli/p/10683751.html

    https://www.cnblogs.com/yanjieli/p/10687701.html

    https://www.cnblogs.com/rexcheny/p/10778567.html

    https://blog.csdn.net/xyang81/article/details/52554398

    http://blog.chinaunix.net/uid-30212356-id-5548409.html

  3. 配置全局块

    global_defs {
    	# 删除不需要的配置项
    	# 路由id:当前安装的keepalived节点主机的标识符,全局唯一
    	router_id keep_171
    }
    
  4. 配置vrrp实例块

    vrrp_instance VI_1 {
    	# 表示此实例的状态,当前171为nginx的主节点,MASTER/BACKUP
        state MASTER
        # 当前实例绑定的网卡(虚拟ip要和网卡绑定在一起,可以通过ip addr命令查看,每个人linux系统网卡名称可能不同)
        interface ens33
        # 虚拟路由ip,保证主备节点一致(在同一个路由器组中)
        virtual_router_id 51
        # 优先级/权重,谁的优先级高,在MASTER宕机之后,就能成为MASTER
        priority 100
        # 主备之间同步检查的时间间隔,默认1s
        advert_int 1
    
    	# 认证授权的密码,防止非法节点进入,主备之间要一模一样
        authentication {
            auth_type PASS
            auth_pass 1111
        }
    	# 配置虚拟ip
        virtual_ipaddress {
            192.168.1.161
        }
    }
    
  5. virtual_server(虚拟主机)配置可以先注释,不用管

  6. 进入/usr/local/keepalived启动keepalived

    cd /usr/local/keepalived

    ./keepalived

  7. 检查网卡上是否有虚拟ip

    ip addr

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第59张图片

  8. 检查是否有keepalived相关进程

    ps -ef | grep keepalived

  9. 测试访问192.168.1.161和192.168.1.171访问Nginx,能发现返回同样的内容,想要关闭keepalived可以使用kill命令

将源码安装的keepalived注册为系统服务

  1. 进入keepalived的安装包目录

  2. 进入安装包目录内部的keepalived文件夹

  3. 进入此文件夹内部的etc目录

  4. 此文件夹内部有init.d文件夹和sysconfig文件夹,拷贝其中文件到系统内部

    cp ./init.d/keepalived /etc/init.d/

    cp ./sysconfig/keepalived /etc/sysconfig/

  5. 刷新系统配置

    systemctl daemon-reload

    systemctl start keepalived // 启动keepalived

    systemctl stop keepalived // 停止keepalived

    systemctl restart keepalived // 重启keepalived

安装并配置备用节点keepalived

  1. 安装keepalived

  2. 编辑配置文件

    vim /etc/keepalived/keepalived.conf

  3. 配置全局块

    global_defs {
    	# 删除不需要的配置项
    	# 路由id:当前安装的keepalived节点主机的标识符,全局唯一
    	router_id keep_172
    }
    
  4. 配置vrrp实例块

    vrrp_instance VI_1 {
    	# 表示此实例的状态,当前172为nginx的备用节点,MASTER/BACKUP
        state BACKUP
        # 当前实例绑定的网卡(虚拟ip要和网卡绑定在一起,可以通过ip addr命令查看,每个人linux系统网卡名称可能不同)
        interface ens33
        # 虚拟路由ip,保证主备节点一致(在同一个路由器组中)
        virtual_router_id 51
        # 优先级/权重,谁的优先级高,在MASTER宕机之后,就能成为MASTER
        priority 80
        # 主备之间同步检查的时间间隔,默认1s
        advert_int 1
    
    	# 认证授权的密码,防止非法节点进入,主备之间要一模一样
        authentication {
            auth_type PASS
            auth_pass 1111
        }
    	# 配置虚拟ip
        virtual_ipaddress {
            192.168.1.161
        }
    }
    
  5. virtual_server(虚拟主机)配置可以先注释,不用管

  6. 进入/usr/local/keepalived启动keepalived

  7. 检查网卡上是否有虚拟ip

    ip addr

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第60张图片

    发现并没有虚拟ip,因为MASTER节点正常运行,BACKUP未启用

  8. 检查是否有keepalived相关进程

  9. 尝试通过ip地址192.168.1.161访问Nginx,发现能成功访问到171服务器;停止主节点keepalived服务之后,再通过此ip访问Nginx则发现访问到了172服务器的Nginx,而且查看172服务器的网卡配置则发现虚拟ip已经生效

    ip addr

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第61张图片

  10. 重新启动MASTER节点的keepalived服务(模拟节点修复),检查网卡信息则会发现,虚拟ip(161)又和171服务器网卡绑定在一起了,而172的网卡信息上虚拟ip的信息则没有了,再次通过虚拟ip访问Nginx时则会请求到171服务器上面的Nginx。

keepalived配置自动重启Nginx实现7*24小时不间断服务

  1. 进入keepalived核心配置文件所在的文件夹

    cd /etc/keepalived

  2. 新建并编辑脚本文件

    vim check_nginx_alive_or_not.sh

  3. 输入以下内容

    #!/bin/bash
    
    A=`ps -C nginx --no-header |wc -l`
    # 判断nginx是否宕机,如果宕机了,尝试重启
    if [ $A -eq 0 ];then
    	/usr/local/nginx/sbin/nginx
    	# 等待一小会再次检查nginx,如果没有启动成功,则停止keepalived,使其启动备用机
    	sleep 3
    	if [ `ps -C nginx --no-header |wc -l` -eq 0 ];then
    		killall keepalived
    	fi
    fi
    
  4. 给脚本文件添加运行权限

    chmod +x /etc/keepalived/check_nginx_alive_or_not.sh

  5. 配置keepalived配置文件监听此脚本

    1. 在global_defs全局块下方添加脚本指令块

      vrrp_script check_nginx_alive {
      	script "/etc/keepalived/check_nginx_alive_or_not.sh"
      	interval 2 # 每隔两秒运行上一行脚本
      	weight 10 # 如果脚本运行成功,则升级权重+10
          # weight -10 # 如果脚本运行失败,则降低权重-10
      }
      
    2. 在vrrp_instance实例块中调用此方法

      # 可以写到authentication指令块下方
      track_script {
      	check_nginx_alive # 追踪 nginx 脚本
      }
      
  6. 重启keepalived使配置生效

    systemctl restart keepalived

keepalived配置双主热备

两台keepalived双机主备会使MASTER获得所有流量,而BACKUP在MASTER正常的情况下不会有流量,这样就会有一台服务器大量时间空闲。为了解决这个问题,可以让两台服务器的keepalived互为主备,形成双机热备架构

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第62张图片

设置DNS轮询
  1. 打开腾讯云进入云解析选项卡
  2. 找到想要配置的域名,点击解析

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第63张图片

  1. 在跳转页面添加记录,主机记录必须是WWW,记录类型必须是A

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第64张图片

  1. 配置好之后,点击负载均衡选项卡会看到,负载均衡生效的域名

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第65张图片

  1. 点击详情可以配置负载均衡算法和权重

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第66张图片

  1. 配置好之后,可以尝试访问网站测试效果,每次轮询切换可能有十分钟的间隔时间
配置171节点keepalived
  1. 打开核心配置文件

    vim /etc/keepalived/keepalived.conf

  2. 找到vrrp_instance实例块

  3. 复制一份放于原实例块下方

    # 实例名称不能重复
    vrrp_instance VI_2 {
    	# 171现在是BACKUP
        state BACKUP
        # 当前实例绑定的网卡(虚拟ip要和网卡绑定在一起,可以通过ip addr命令查看,每个人linux系统网卡名称可能不同)
        interface ens33
        # 虚拟路由ip,保证主备节点一致(在同一个路由器组中)
        virtual_router_id 52
        # 优先级/权重,BACKUP一般是80
        priority 80
        # 主备之间同步检查的时间间隔,默认1s
        advert_int 1
    
    	# 认证授权的密码,防止非法节点进入,主备之间要一模一样
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        
        track_script {
    		check_nginx_alive # 追踪 nginx 脚本
    	}
    	# 配置第二个虚拟ip
        virtual_ipaddress {
            192.168.1.162
        }
    }
    
  4. 重启keepalived服务

    systemctl restart keepalived

  5. 查看网卡配置可以发现,171和161绑定在一起的

配置172节点keepalived
  1. 打开核心配置文件

    vim /etc/keepalived/keepalived.conf

  2. 找到vrrp_instance实例块

  3. 复制一份放于原实例块下方

    # 实例名称不要重复
    vrrp_instance VI_2 {
    	# 原来第一个实例是BACKUP,第二个实例是MASTER
        state MASTER
        interface ens33
        # 虚拟路由ip,不能和原来一样
        virtual_router_id 52
        # 优先级/权重,MATER一般是100
        priority 100
        # 主备之间同步检查的时间间隔,默认1s
        advert_int 1
    
    	# 认证授权的密码,防止非法节点进入,主备之间要一模一样
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        
        track_script {
    		check_nginx_alive # 追踪 nginx 脚本
    	}
    	# 配置第二个虚拟ip
        virtual_ipaddress {
            192.168.1.162
        }
    }
    
  4. 重启keepalived服务

    systemctl restart keepalived

  5. 查看网卡配置172和162绑定在一起了

  6. 测试关闭171的keepalived服务,此时不管访问161或者162,都会访问到172的服务器,查看网卡配置也会发现,172绑定了两个虚拟ip161和162

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第67张图片

LVS的介绍和使用

什么是LVS

LVS,全称 Linux Virtual Server,即Linux虚拟服务器。

它是一个基于四层模型的负载均衡调度器,是一个虚拟的服务器集群系统,使用负载均衡技术将多台真实服务器组成一个虚拟的服务器集群。在众多解决高并发问题的方案中,这是一个易于扩展并且价格相对低廉的方案。服务器集群对用户来说是透明的,用户只用访问LVS即可。

LVS是基于IP和基于请求内容分发的负载平衡调度方法,将一组服务器构成一个可以实现高可伸缩、高可用的虚拟服务器。一组服务器通过高速的局域网或者地理分布的广域网相互连接,在它们的前端有一个负载调度器(Load Balancer,简称LB)。LB能无缝地将客户端发来的请求调度到提供真实服务的服务器上,此外可以通过在集群中添加节点的方式来提高系统的可伸缩性,通过对服务器状态的检测,及时重置系统,提高系统的高可用。

本项目是在1998年时,由章文嵩博士成立的,是中国最早出现的自由软件项目之一,从linux2.4开始已经被收录到linux核心中。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第68张图片

LVS官网:

www.linux-vs.org/index.html

LVS中文文档:

http://www.linuxvirtualserver.org/zh/index.html

LVS的一些术语:

VS:Virtual Server       虚拟服务器,通常是分发器 
RS:Real Server          实际提供服务器的真实服务器
CIP:Client IP           客户的客户端IP
VIP:Virtual Server IP   虚拟服务器的IP 
RIP:Real Server IP      真实服务器的IP
DIP:Director IP         分发器的IP
CIP <--> VIP == DIP <--> RIP      客户端访问VIPDIP将请求转发到RIP

LVS的三种工作模式

NAT地址转换模式

NAT地址转换模式是最为简单的一种模式,它的原理如下图所示:

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第69张图片

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第70张图片

NAT其实就是通过网络地址转换来实现负载均衡的,下面是它的请求流程:

  1. 分发服务器Director Server(后面简称DS)接受到请求后,通过分发策略得出要将此请求分发到Real Server1。于是将请求报文的目的地址改为RIP1,发送出去。
  2. Real Server1收到一个目标地址为自己的数据包,于是接受并进行处理。
  3. 处理完成后,Real Server1将RIP1——>CIP的数据包发送出去。
  4. DS接收到RIP1——>CIP的数据包后,将源地址改为VIP,然后发送出去:VIP——>CIP。

这个过程中,DS仅仅起到一个地址转换和分发的作用。
在NAT模式中,请求和响应报文都要通过DS,当真实服务器的数量越来越多时,分发器DS将会成为整个集群系统的性能瓶颈。下面的DR模式解决这个问题。

总结:请求和响应都要通过DS进行转发,当用户和RS越来越多之后,DS将会出现性能瓶颈。这个很象 Nginx 的 7 层调度,所以大约能支持的后端机器只有 10 台的样子。

DR直接路由模式

互联网应用中存在一个规律:请求报文较短而响应报文往往包含大量的数据。如果能将请求和响应分开处理,即在负载调度器(Director)中只负责调度请求而响应直接由RealServer返回给客户,将极大地提高整个集群系统的吞吐量。RS响应时会通过VIP来进行响应,这样服务器真实ip不会暴露在公网。这就是DR的实现原理,原理图如下所示:

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第71张图片

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第72张图片

在DR模型中,只有在请求的时候会经过DR,响应的数据包由Real Server直接返回给用户,该模式是3中模式中最常用的。它的请求过程如下所示:

  1. DR接受到请求后,通过分发策略得出要将此请求分发到Real Server2。DS就将数据帧中的目标MAC地址修改为Real Server2的MAC地址,然后再将数据帧发送出去。(为什么要用MAC地址?因为此时Real Server也有配置有VIP)
  2. 当Real Server2 收到一个源地址为CIP目标地址为VIP的数据包时,Real Server2发现目标地址为VIP,而VIP是自己,于是接受数据包并给予处理。
  3. Real Server2处理完成后,会将一个源地址为VIP而目标地址为CIP的数据包发送出去,此时的响应请求就不会再经过DS,而是直接响应给用户了。

在这个过程中存在一个问题,由于RealServer也配置了VIP,那么当CIP——>VIP的数据包到达服务局域网,进行广播时,所有的服务器都会进行应答,此时先应答的服务器就会收到数据包,这样就失去了负载均衡的能力。因此在使用DR模式时,通常会采用一些方式来确保请求数据包只会由DS接收,例如抑制Real Server对广播的应答,或者直接在路由器中对DS进行绑定等。

总结:DS只转发请求,响应是RS直接响应到客户端,这样使LVS的性能上限大大提高,能承载更大的吞吐量。

TNU隧道模式

TNU模式与DR模式非常相似,它同样是只有请求信息会经过DS,应答信息由Real Server直接返回给用户。不过DR模式中,要求DS和所有的Real Server必须在一个局域网中,而TNU模式去掉了这个限制,但是TUN要求每个节点必须要有一个网卡,而且RS是暴露在公网的。TNU模式原理图如下所示:

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第73张图片

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第74张图片

在TNU模式中,DS与Real Server不必在一个网络中。DS在接到请求报文之后,在报文的上面再加一层源地址为DIP,目的地址为RIP2的IP首部,然后通过广域网发送到Real Server2。
Real Server2收到报文,拆掉报文以后发现了里面还有一个封装,它就知道了,这就是隧道。后续的过程就与DR一样了。
总结:在DS转发到RS的过程中再封装一层,这样可以通过广域网找到RS,RS处理完请求直接响应到客户端。

LVS的优缺点

优点

  1. 工作在网络层,可以实现高性能、高可用的服务器集群技术。
  2. 廉价,可把许多低性能的服务器组合在一起形成一个水平扩展的集群服务器。
  3. 易用,配置非常简单,且有多重负载均衡的方法
  4. 稳定可靠,即使集群中的一台服务器挂掉,也不影响整体服务效果。
  5. 可扩展性好,可以用户透明地进行水平扩展,加减机器非常方便。

缺点

  1. 由于是通用组件,因此不能对特定业务进行针对优化。
  2. 对于长连接无法进行负载均衡。
  3. 自身没有健康状态检查,需要结合脚本或者Keepalived等软件实现。

参考链接:

https://blog.csdn.net/zhoucheng05_13/article/details/81190608

http://www.uml.org.cn/zjjs/201211083.asp

https://www.cnblogs.com/Rivend/p/12071156.html

https://blog.csdn.net/qq_41602468/article/details/118468855

为什么要使用LVS+Nginx

  1. LVS基于四层负载均衡,工作效率高;Nginx基于七层,接收到请求之后还要解析请求,效率没有LVS高

  2. 单个Nginx承受不了压力,需要做Nginx集群

  3. LVS可以充当Nginx集群的调度者,Nginx集群之前不能再使用Nginx了,只能使用性能比Nginx更高的负载均衡调度器

  4. Nginx接受请求并返回响应,LVS可以只接受请求,响应直接由真实服务器响应到客户端,这样大大提高了并发性能

LVS和Nginx的区别

lvs和nginx都可以用作多机负载方案,他们各有优缺点,在生产环境中需要好好分析实际情况并加以利用。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第75张图片

LVS的优势

  1. 抗负载能力强、是工作在网络4层之上仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu资源消耗比较低。
  2. 配置性比较低,这是一个缺点也是一个优点,因为没有可太多配置的东西,所以并不需要太多接触,大大减少了人为出错的几率。
  3. 工作稳定,因为其本身抗负载能力很强,自身有完整的双机热备方案,如LVS+Keepalived,不过我们在项目实施中用得最多的还是LVS/DR+Keepalived。
  4. 无流量,LVS只分发请求,而流量并不从它本身出去,这点保证了均衡器IO的性能不会收到大流量的影响。
  5. 应用范围比较广,因为LVS工作在4层,所以它几乎可以对所有应用做负载均衡,包括http、数据库、在线聊天室等等。

另外:lvs也不是完全能判别节点故障的,比如在wlc分配方式下,集群里有一个节点没有配置vip,会使整个集群不能使用,这时使用wrr分配方式则会丢掉一台机器。目前这个问题还在进一步测试中。所以用lvs也得多多当心为妙。

LVS的缺点

  1. 软件本身不支持正则表达式处理,不能做动静分离;而现在许多网站在这方面都有较强的需求,这个是Nginx/HAProxy+Keepalived的优势所在。

  2. 如果是网站应用比较庞大的话,LVS/DR+Keepalived实施起来就比较复杂了,特别后面有Windows Server的机器的话,如果实施及配置还有维护过程就比较复杂了,相对而言,Nginx/HAProxy+Keepalived就简单多了。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第76张图片

Nginx的优势

  1. 工作在网络的7层之上,可以针对http应用做一些分流的策略,比如针对域名、目录结构,它的正则规则比HAProxy更为强大和灵活,这也是它目前广泛流行的主要原因之一,Nginx单凭这点可利用的场合就远多于LVS了。

  2. Nginx对网络稳定性的依赖非常小,理论上能ping通就就能进行负载功能,这个也是它的优势之一;相反LVS对网络稳定性依赖比较大,这点本人深有体会;

  3. Nginx安装和配置比较简单,测试起来比较方便,它基本能把错误用日志打印出来。LVS的配置、测试就要花比较长的时间了,LVS对网络依赖比较大。

  4. 可以承担高负载压力且稳定,在硬件不差的情况下一般能支撑几万次的并发量,负载度比LVS相对小些。

  5. Nginx可以通过端口检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点,不过其中缺点就是不支持url来检测。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而不满。

  6. Nginx不仅仅是一款优秀的负载均衡器/反向代理软件,它同时也是功能强大的Web应用服务器。LNMP也是近几年非常流行的web架构,在高流量的环境中稳定性也很好。

  7. Nginx现在作为Web反向加速缓存越来越成熟了,速度比传统的Squid服务器更快,可以考虑用其作为反向代理加速器。

  8. Nginx可作为中层反向代理使用,这一层面Nginx基本上无对手,唯一可以对比Nginx的就只有lighttpd了,不过lighttpd目前还没有做到Nginx完全的功能,配置也不那么清晰易读,社区资料也远远没Nginx活跃。

  9. Nginx也可作为静态网页和 图片服务器,这方面的性能也无对手。还有Nginx社区非常活跃,第三方模块也很多。

Nginx的缺点

  1. Nginx仅能支持http、https和Email协议,这样就在适用范围上面小些,这个是它的缺点。

  2. 对后端服务器的健康检查,只支持通过端口来检测,不支持通过url来检测。不支持Session的直接保持,但能通过ip_hash来解决。

Nginx和LVS作对比的结果

  1. Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、目录结构等,相比之下LVS并不具备这样的功能,所以Nginx单凭这点可利用的场合就远多于LVS了;但Nginx有用的这些功能使其可调整度要高于LVS,所以经常要去触碰触碰,触碰多了,人为出问题的几率也就会大。

  2. Nginx对网络稳定性的依赖较小,理论上只要ping得通,网页访问正常,Nginx就能连得通,这是Nginx的一大优势!Nginx同时还能区分内外网,如果是同时拥有内外网的节点,就相当于单机拥有了备份线路;LVS就比较依赖于网络环境,目前来看服务器在同一网段内并且LVS使用direct方式分流,效果较能得到保证。另外注意,LVS需要向托管商至少申请多一个ip来做Visual IP,貌似是不能用本身的IP来做VIP的。要做好LVS管理员,确实得跟进学习很多有关网络通信方面的知识,就不再是一个HTTP那么简单了。

  3. Nginx安装和配置比较简单,测试起来也很方便,因为它基本能把错误用日志打印出来。LVS的安装和配置、测试就要花比较长的时间了;LVS对网络依赖比较大,很多时候不能配置成功都是因为网络问题而不是配置问题,出了问题要解决也相应的会麻烦得多。

  4. Nginx也同样能承受很高负载且稳定,但负载度和稳定度差LVS还有几个等级:Nginx处理所有流量所以受限于机器IO和配置;本身的bug也还是难以避免的。

  5. Nginx可以检测到服务器内部的故障,比如根据服务器处理网页返回的状态码、超时等等,并且会把返回错误的请求重新提交到另一个节点。目前LVS中 ldirectd也能支持针对服务器内部的情况来监控,但LVS的原理使其不能重发请求。比如用户正在上传一个文件,而处理该上传的节点刚好在上传过程中出现故障,Nginx会把上传切到另一台服务器重新处理,而LVS就直接断掉了,如果是上传一个很大的文件或者很重要的文件的话,用户可能会因此而恼火。

  6. Nginx对请求的异步处理可以帮助节点服务器减轻负载,假如使用apache直接对外服务,那么出现很多的窄带链接时apache服务器将会占用大 量内存而不能释放,使用多一个Nginx做apache代理的话,这些窄带链接会被Nginx挡住,apache上就不会堆积过多的请求,这样就减少了相当多的资源占用。这点使用squid也有相同的作用,即使squid本身配置为不缓存,对apache还是有很大帮助的。

  7. Nginx能支持http、https和email(email的功能比较少用),LVS所支持的应用在这点上会比Nginx更多。在使用上,一般最前端所采取的策略应是LVS,也就是DNS的指向应为LVS均衡器,LVS的优点令它非常适合做这个任务。重要的ip地址,最好交由LVS托管,比如数据库的 ip、webservice服务器的ip等等,这些ip地址随着时间推移,使用面会越来越大,如果更换ip则故障会接踵而至。所以将这些重要ip交给 LVS托管是最为稳妥的,这样做的唯一缺点是需要的VIP数量会比较多。

  8. Nginx可作为LVS节点机器使用,一是可以利用Nginx的功能,二是可以利用Nginx的性能。当然这一层面也可以直接使用squid,squid的功能方面就比Nginx弱不少了,性能上也有所逊色于Nginx。Nginx也可作为中层代理使用,这一层面Nginx基本上无对手,唯一可以撼动Nginx的就只有lighttpd了,不过lighttpd目前还没有能做到 Nginx完全的功能,配置也不那么清晰易读。另外,中层代理的IP也是重要的,所以中层代理也拥有一个VIP和LVS是最完美的方案了。具体的应用还得具体分析,如果是比较小的网站(日PV小于1000万),用Nginx就完全可以了,如果机器也不少,可以用DNS轮询,LVS所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候,要多多考虑利用LVS。

在使用上,一般最前端所采取的的策略应是lvs,也就是dns的指向应为lvs均衡器,lvs的优点另它非常适合做这个任务。

重要的ip地址,最好交由lvs托管,比如数据库的ip、webservice服务器的ip等等,这些ip地址随着时间推移,使用面会越来越大,如果更换ip则故障会接踵而来。所以将这些重要ip交给lvs托管式最为稳妥的,这样做的唯一缺点是需要VIP数量会比较多。

nginx可以作为lvs节点机器使用,一是可以利用nginx的功能,二是可以利用nginx的性能。当然这一层面也可以直接使用squid,squid的功能方面就比nginx弱不少,性能上也有所逊色于nginx。

nginx也可以作为中层代理使用,这一层面nginx基本上无对手,唯一可以撼动nginx的就只有lighttpd了,不过lighttpd目前还没有能做到nginx完全的功能,配置也不那么清晰易读。另外,中层代理的ip也是重要的,所以中层代理业拥有一个VIP和lvs是最完美的方案了。

Nginx和LVS在web服务中的应用

nginx也可以作为网页静态服务器。

具体的应用还得具体分析,如果是比较小的网站(日pv<1000万),用nginx就完全可以了,如果机器也不少,可以用dns轮询,lvs所耗费的机器还是比较多的;大型网站或者重要的服务,机器不发愁的时候要多多考虑利用lvs。

提出一个问题:使用nginx+keepalived实现负载均衡,解决单点与高流量并发问题。为什么要用nginx而不用lvs?

7个理由

  1. 高并发连接:官方测试能够支撑5万并发连接,在实际生产环境中跑到2——3万并发连接数。

  2. 内存消耗少:在3万并发连接数下,开启的10个nginx进程才消耗150M内存(150*10=150M)。

  3. 配置文件非常简单:风格跟程序一样通俗易懂。

  4. 成本低廉:nginx为开源软件,可以免费使用。而购买F5 big-ip、netscaler等硬件负载均衡交换机则需要十多万至几十万人民币。

​ (使用nginx做七层负载均衡的理由?)

  1. 支持rewrite重写规则:能够根据域名、url的不同,将http请求分到不同的后端服务器群组。

  2. 内置的健康检查功能:如果nginx proxy后端的某台web服务器宕机了,不会影响前端访问。

  3. 节省带宽:支持gzip压缩,可以添加浏览器本地缓存的header头。

进一步说明

  • keepalived是linux下面实现vrrp备份路由的高可靠性运行件。基于keepalived设计的服务模式能够真正做到主服务器和备份服务器故障时ip瞬间无缝交接。

  • nginx是基于linux2.6内核中epoll模型http服务器,与Apache进程派生模式不同的是nginx进程基于master+slave多进程模型,自身具有非常稳定的子进程管理功能。在master进程分配模式下,master进程永远不进行业务处理,只是进行任务分发,从而达到master进程的存活高可靠性,slave进程所有的业务信号都由主进程发出,slave进城所有的超时任务都会被master终止,属于阻塞式人物模型。

  • 服务器ip存活检测是由keepalived自己本身完成的,将2台服务器配置成keepalived互为主辅关系,任意一方机器故障对方都能够将ip接管过去。

  • keepalived的服务器ip通过其配置文件进行管理,依靠其自身的进程去确定服务器的存活状态,如果在需要对服务器进程在线维护的情况下,只需要停掉被维护机器的keepalived服务进程,另外一台服务器就能够接管该台服务器的所有应用。

现在对网络负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术:

  • 第一阶段:利用Nginx或HAProxy进行单点的负载均衡,这一阶段服务器规模刚脱离开单服务器、单数据库的模式,需要一定的负载均衡,但是仍然规模较小没有专业的维护团队来进行维护,也没有需要进行大规模的网站部署。这样利用Nginx或HAproxy就是第一选择,此时这些东西上手快, 配置容易,在七层之上利用HTTP协议就可以。这时是第一选择。

  • 第二阶段:随着网络服务进一步扩大,这时单点的Nginx已经不能满足,这时使用LVS或者商用Array就是首要选择,Nginx此时就作为LVS或者Array的节点来使用,具体LVS或Array的是选择是根据公司规模和预算来选择,Array的应用交付功能非常强大,本人在某项目中使用过,性价比也远高于F5,商用首选!但是一般来说这阶段相关人才跟不上业务的提升,所以购买商业负载均衡已经成为了必经之路。

  • 第三阶段:这时网络服务已经成为主流产品,此时随着公司知名度也进一步扩展,相关人才的能力以及数量也随之提升,这时无论从开发适合自身产品的定制,以及降低成本来讲开源的LVS,已经成为首选,这时LVS会成为主流。

最终形成比较理想的基本架构为:Array/LVS — Nginx/Haproxy — Squid/ Varnish — AppServer。

参考链接:

https://blog.51cto.com/luxiangyu/1871833

https://www.cnblogs.com/zhaojingyu/p/9013677.html

安装配置LVS的DR模式

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第77张图片

  • 所有计算机节点关闭网络配置管理器,因为有可能会和网络接口冲突

    systemctl stop NetworkManager

    systemctl disable NetworkManager

在151配置虚拟ip并安装ipvsadm

  1. 进入网卡配置的文件夹,找到自己的网卡(每个人可能不一样,这里是ens33)

    cd /etc/sysconfig/network-scripts/

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第78张图片

  2. 拷贝一份配置文件

    cp ifcfg-ens33 ifcfg-ens33:1

    注:数字1为别名,可以任取其他数字都行

  3. 修改新的网卡配置文件,构建虚拟ip

    vim ifcfg-ens33:1

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第79张图片

    1. 修改DEVICE为:DEVICE=“ens33:1”
    2. 修改ONBOOT为:NOBOOT=“yes”
    3. 修改IPADDR为:IPADDR=192.168.1.150
    4. 删除其他配置项,保留BOOTPROTO DEVICE ONBOOT IPADDR NETMASK

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第80张图片

    最后,保存此文件

  4. 刷新服务器网络配置,可以重启也可以使用以下命令

    service network restart

  5. 查看网卡信息

    ip addr

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第81张图片

  6. 安装ipvsadm

    yum install ipvsadm

  7. 查看ipvsadm的版本和配置的RS集群列表

    ipvsadm -Ln

    注意:阿里云可能不支持虚拟ip的服务,想要使用虚拟ip必须购买它特有的服务;腾讯云支持,但是也要付费。

在171配置虚拟ip

  1. 进入网卡配置的文件夹,找到自己lo结尾的配置文件(回环接口),我们构建的虚拟ip仅仅只用于返回数据,而不能被用户访问到

    cd /etc/sysconfig/network-scripts/

  2. 拷贝一份配置文件

    cp ifcfg-lo ifcfg-lo:1

  3. 修改新的配置文件,构建虚拟ip

    vim ifcfg-lo:1

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第82张图片

    1. 修改DEVICE为:DEVICE=“lo:1”
    2. 修改IPADDR为:IPADDR=192.168.1.150
    3. 修改NETMASK为:NETMASK=255.255.255.255

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第83张图片

    最后,保存配置文件

  4. 刷新配置文件

    ifup lo # 也可以使用重启网络配置命令

  5. 查看网卡信息,检查配置是否生效

    ip addr

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第84张图片

在172配置虚拟ip

  1. 进入网卡配置的文件夹,找到自己lo结尾的配置文件

    cd /etc/sysconfig/network-scripts/

  2. 拷贝一份配置文件

    cp ifcfg-lo ifcfg-lo:1

  3. 修改新的配置文件,构建虚拟ip

    vim ifcfg-lo:1

    1. 修改DEVICE为:DEVICE=“lo:1”
    2. 修改IPADDR为:IPADDR=192.168.1.150
    3. 修改NETMASK为:NETMASK=255.255.255.255

    最后,保存配置文件

  4. 刷新配置文件

    ifup lo # 也可以使用重启网络配置命令

  5. 查看网卡信息,检查配置是否生效

    ip addr

为两台RS配置ARP响应行为和通告级别

arp_ignore和arp_announce介绍

arp_ignore和arp_announce参数都和ARP协议相关,主要用于控制系统返回arp响应和发送arp请求时的动作。这两个参数很重要,特别是在LVS的DR场景下,它们的配置直接影响到DR转发是否正常。

首先看一下Linux内核文档中对于它们的描述:

arp_ignore - INTEGER

Define different modes for sending replies in response to
received ARP requests that resolve local target IP addresses:
0 - (default): reply for any local target IP address, configured
on any interface

1 - reply only if the target IP address is local address
configured on the incoming interface

2 - reply only if the target IP address is local address
configured on the incoming interface and both with the
sender’s IP address are part from same subnet on this interface

3 - do not reply for local addresses configured with scope host,
only resolutions for global and link addresses are replied

4-7 - reserved

8 - do not reply for all local addresses

The max value from conf/{all,interface}/arp_ignore is used
when ARP request is received on the {interface}

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第85张图片

arp_ignore参数的作用是控制系统在收到外部的arp请求时,是否要返回arp响应。

arp_ignore参数常用的取值主要有0,1,2,3~8较少用到:

0:响应任意网卡上接收到的对本机IP地址的arp请求(包括环回网卡上的地址),而不管该目的IP是否在接收网卡上。

1:只响应目的IP地址为接收网卡上的本地地址的arp请求。

2:只响应目的IP地址为接收网卡上的本地地址的arp请求,并且arp请求的源IP必须和接收网卡同网段。

3:如果ARP请求数据包所请求的IP地址对应的本地地址其作用域(scope)为主机(host),则不回应ARP响应数据包,如果作用域为全局(global)或链路(link),则回应ARP响应数据包。

4~7:保留未使用

8:不回应所有的arp请求

sysctl.conf中包含all和eth/lo(具体网卡)的arp_ignore参数,取其中较大的值生效。

arp_announce - INTEGER

Define different restriction levels for announcing the local
source IP address from IP packets in ARP requests sent on
interface:

0 - (default) Use any local address, configured on any interface

1 - Try to avoid local addresses that are not in the target’s
subnet for this interface. This mode is useful when target
hosts reachable via this interface require the source IP
address in ARP requests to be part of their logical network
configured on the receiving interface. When we generate the
request we will check all our subnets that include the
target IP and will preserve the source address if it is from
such subnet. If there is no such subnet we select source
address according to the rules for level 2.

2 - Always use the best local address for this target.
In this mode we ignore the source address in the IP packet
and try to select local address that we prefer for talks with
the target host. Such local address is selected by looking
for primary IP addresses on all our subnets on the outgoing
interface that include the target IP address. If no suitable
local address is found we select the first local address
we have on the outgoing interface or on all other interfaces,
with the hope we will receive reply for our request and
even sometimes no matter the source IP address we announce.
The max value from conf/{all,interface}/arp_announce is used.

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第86张图片

arp_announce的作用是控制系统在对外发送arp请求时,如何选择arp请求数据包的源IP地址。(比如系统准备通过网卡发送一个数据包a,这时数据包a的源IP和目的IP一般都是知道的,而根据目的IP查询路由表,发送网卡也是确定的,故源MAC地址也是知道的,这时就差确定目的MAC地址了。而想要获取目的IP对应的目的MAC地址,就需要发送arp请求。arp请求的目的IP自然就是想要获取其MAC地址的IP,而arp请求的源IP是什么呢? 可能第一反应会以为肯定是数据包a的源IP地址,但是这个也不是一定的,arp请求的源IP是可以选择的,控制这个地址如何选择就是arp_announce的作用)

arp_announce参数常用的取值有0,1,2。

0:允许使用任意网卡上的IP地址作为arp请求的源IP,通常就是使用数据包a的源IP。

1:尽量避免使用不属于该发送网卡子网的本地地址作为发送arp请求的源IP地址。

2:忽略IP数据包的源IP地址,选择该发送网卡上最合适的本地地址作为arp请求的源IP地址。
sysctl.conf中包含all和eth/lo(具体网卡)的arp_ignore参数,取其中较大的值生效。

arp_ignore和arp_announce参数示例

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第87张图片

  1. 当arp_ignore参数配置为0时,eth1网卡上收到目的IP为环回网卡IP的arp请求,但是eth1也会返回arp响应,把自己的mac地址告诉对端。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第88张图片

  1. 当arp_ignore参数配置为1时,eth1网卡上收到目的IP为环回网卡IP的arp请求,发现请求的IP不是自己网卡上的IP,不会回arp响应。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第89张图片

  1. 当arp_announce参数配置为0时,系统要发送的IP包源地址为eth1的地址,IP包目的地址根据路由表查询判断需要从eth2网卡发出,这时会先从eth2网卡发起一个arp请求,用于获取目的IP地址的MAC地址。该arp请求的源MAC自然是eth2网卡的MAC地址,但是源IP地址会选择eth1网卡的地址。

【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第90张图片

  1. 当arp_announce参数配置为2时,eth2网卡发起arp请求时,源IP地址会选择eth2网卡自身的IP地址。
arp_ignore和arp_announce参数在DR模式下的作用
  1. arp_ignore:

    • 因为DR模式下,每个真实服务器节点都要在环回网卡上绑定虚拟服务IP。这时候,如果客户端对于虚拟服务IP的arp请求广播到了各个真实服务器节点,如果arp_ignore参数配置为0,则各个真实服务器节点都会响应该arp请求,此时客户端就无法正确获取LVS节点上正确的虚拟服务IP所在网卡的MAC地址。假如某个真实服务器节点A的网卡eth1响应了该arp请求,客户端把A节点的eth1网卡的MAC地址误认为是LVS节点的虚拟服务IP所在网卡的MAC,从而将业务请求消息直接发到了A节点的eth1网卡。这时候虽然因为A节点在环回网卡上也绑定了虚拟服务IP,所以A节点也能正常处理请求,业务暂时不会受到影响。但时此时由于客户端请求没有发到LVS的虚拟服务IP上,所以LVS的负载均衡能力没有生效。造成的后果就是,A节点一直在单节点运行,业务量过大时可能会出现性能瓶颈。
    • 所以DR模式下要求arp_ignore参数要求配置为1。
  2. arp_announce

    • 每个机器或者交换机中都有一张arp表,该表用于存储对端通信节点IP地址和MAC地址的对应关系。当收到一个未知IP地址的arp请求,就会再本机的arp表中新增对端的IP和MAC记录;当收到一个已知IP地址(arp表中已有记录的地址)的arp请求,则会根据arp请求中的源MAC刷新自己的arp表。
    • 如果arp_announce参数配置为0,则网卡在发送arp请求时,可能选择的源IP地址并不是该网卡自身的IP地址,这时候收到该arp请求的其他节点或者交换机上的arp表中记录的该网卡IP和MAC的对应关系就不正确,可能会引发一些未知的网络问题,存在安全隐患。
    • 所以DR模式下要求arp_announce参数要求配置为2。
arp_ignore和arp_announce参数的配置方法

arp_ignore和arp_announce参数分别有all,default,lo,eth1,eth2…等对应不同网卡的具体参数。当all和具体网卡的参数值不一致时,取较大值生效。

一般只需修改all和某个具体网卡的参数即可(取决于你需要修改哪个网卡)。下面以修改lo网卡为例:

  1. 修改/etc/sysctl.conf文件,然后sysctl -p刷新到内存。

    net.ipv4.conf.all.arp_ignore=1

    net.ipv4.conf.lo.arp_ignore=1

    net.ipv4.conf.all.arp_announce=2

    net.ipv4.conf.lo.arp_announce=2

  2. 使用sysctl -w直接写入内存:

    sysctl -w net.ipv4.conf.all.arp_ignore=1

    sysctl -w net.ipv4.conf.lo.arp_ignore=1

    sysctl -w net.ipv4.conf.all.arp_announce=2

    sysctl -w net.ipv4.conf.lo.arp_announce=2

  3. 修改/proc文件系统:

    echo “1”>/proc/sys/net/ipv4/conf/all/arp_ignore

    echo “1”>/proc/sys/net/ipv4/conf/lo/arp_ignore

    echo “2”>/proc/sys/net/ipv4/conf/all/arp_announce

    echo “2”>/proc/sys/net/ipv4/conf/lo/arp_announce

    参考链接:

    https://www.cnblogs.com/lipengxiang2009/p/7451050.html

给171和172配置ARP参数
  1. 在171上编辑sysctl.conf文件

    vim /etc/sysctl.conf

  2. 复制粘贴以下内容

    net.ipv4.conf.all.arp_ignore=1 # 所有网卡

    net.ipv4.conf.default.arp_ignore=1 # 默认网卡

    net.ipv4.conf.lo.arp_ignore=1 # 回环网卡

    net.ipv4.conf.all.arp_announce=2

    net.ipv4.conf.default.arp_announce=2

    net.ipv4.conf.lo.arp_announce=2

  3. 保存并刷新配置

    sysctl -p

  4. 在172上重复以上1-3步骤

  5. 为171配置路由,接受数据报文之后交给lo:1进行处理

    route add -host 192.168.1.150 dev lo:1

  6. 查看配置是否生效

    route -n

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第91张图片

  7. 在172上重复以上5-6步骤

  8. 以上route配置重启服务器之后会失效,所以要把此命令放到开机自启动配置文件中

    在171和172服务器上执行:

    echo “route add -host 192.168.1.150 dev lo:1” >> /etc/rc.local # 把此命令追加到/etc/rc.local文件尾部

配置151的LVS集群的规则

ipvsadm命令解释

ipvsadm -h

man ipvsadm

对ipvsadm 的命令参考,并根据自己使用的经验,进行了一个简单的翻译,希望
对ipvsadm 的使用者有一定的帮助。

为了更好的让大家理解这份命令手册,将手册里面用到的几个术语先简单的介绍
一下:

  1. virtual-service-address:是指虚拟服务器的ip 地址
  2. real-service-address:是指真实服务器的ip 地址
  3. scheduler:调度方法

ipvsadm 的用法和格式如下:

ipvsadm -A|E -t|u|f virutal-service-address:port [-s scheduler] [-p[timeout]] [-M netmask]

ipvsadm -D -t|u|f virtual-service-address

ipvsadm -C

ipvsadm -R

ipvsadm -S [-n]

ipvsadm -a|e -t|u|f service-address:port -r real-server-address:port [-g|i|m] [-w weight]

ipvsadm -d -t|u|f service-address -r server-address

ipvsadm -L|l [options]

ipvsadm -Z [-t|u|f service-address]

ipvsadm --set tcp tcpfin udp

ipvsadm --start-daemon state [–mcast-interface interface]

ipvsadm --stop-daemon

ipvsadm -h

命令选项解释:

有两种命令选项格式,长的和短的,具有相同的意思。在实际使用时,两种都可
以。

-A --add-service 在内核的虚拟服务器表中添加一条新的虚拟服务器记录。也
就是增加一台新的虚拟服务器。

-E --edit-service 编辑内核虚拟服务器表中的一条虚拟服务器记录。

-D --delete-service 删除内核虚拟服务器表中的一条虚拟服务器记录。

-C --clear 清除内核虚拟服务器表中的所有记录。

-R --restore 恢复虚拟服务器规则

-S --save 保存虚拟服务器规则,输出为-R 选项可读的格式

-a --add-server 在内核虚拟服务器表的一条记录里添加一条新的真实服务器
记录。也就是在一个虚拟服务器中增加一台新的真实服务器

-e --edit-server 编辑一条虚拟服务器记录中的某条真实服务器记录

-d --delete-server 删除一条虚拟服务器记录中的某条真实服务器记录

-L|-l --list 显示内核虚拟服务器表

-Z --zero 虚拟服务表计数器清零(清空当前的连接数量等)

–set tcp tcpfin udp 设置连接超时值

–start-daemon 启动同步守护进程。他后面可以是master 或backup,用来说
明LVS Router 是master 或是backup。在这个功能上也可以采用keepalived 的
VRRP 功能。

–stop-daemon 停止同步守护进程

-h --help 显示帮助信息

其他的选项:

-t --tcp-service service-address 说明虚拟服务器提供的是tcp的服务[vip:port] or [real-server-ip:port]

-u --udp-service service-address 说明虚拟服务器提供的是udp 的服务[vip:port] or [real-server-ip:port]

-f --fwmark-service fwmark 说明是经过iptables 标记过的服务类型。

-s --scheduler scheduler 使用的调度算法,有这样几个选项rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq,默认的调度算法是wlc.

-p --persistent [timeout] 持久稳固的服务。这个选项的意思是来自同一个客户的多次请求,将被同一台真实的服务器处理。timeout 的默认值为300 秒。

-M --netmask netmask persistent granularity mask

-r --real-server server-address 真实的服务器[Real-Server:port]

-g --gatewaying 指定LVS 的工作模式为直接路由模式(也是LVS 默认的模式)

-i --ipip 指定LVS 的工作模式为隧道模式

-m --masquerading 指定LVS 的工作模式为NAT 模式

-w --weight weight 真实服务器的权值

–mcast-interface interface 指定组播的同步接口

-c --connection 显示LVS 目前的连接 如:ipvsadm -L -c

–timeout 显示tcp tcpfin udp 的timeout 值 如:ipvsadm -L --timeout

–daemon 显示同步守护进程状态

–stats 显示统计信息

–rate 显示速率信息

–sort 对虚拟服务器和真实服务器排序输出

–numeric -n 输出IP 地址和端口的数字形式

参考链接:

http://zh.linuxvirtualserver.org/node/5

https://www.jianshu.com/p/4a3496b8006a

https://www.cnblogs.com/b02330224/p/14450719.html

构建LVS的集群配置
  1. 添加一个集群

    ipvsadm -A -t 192.168.1.150:80 -s rr

    -A 新增一个集群

    -t 说明虚拟服务器提供的是tcp的服务

    -s 负载均衡算法是轮询(rr)

  2. 查看集群列表

    ipvsadm -Ln

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第92张图片

  3. 给集群添加真实服务器(171和172)

    ipvsadm -a -t 192.168.1.150:80 -r 192.168.1.171:80 -g

    ipvsadm -a -t 192.168.1.150:80 -r 192.168.1.172:80 -g

    -a 添加真实服务器

    -t 提供tcp服务

    -r 真实服务器的ip端口

    -g 转发的模式

  4. 再次查看集群列表

    ipvsadm -Ln

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第93张图片

  5. 测试访问150,能不能访问到171或172服务器

  6. 查看LVS转发请求之后,响应会不会再次通过LVS

    ipvsadm -Ln --stats

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第94张图片

    InPkts 上行,请求

    OutPkts 下行,响应

  7. 当我们多次请求时发现,只会访问到同一台服务器,似乎负载均衡策略未生效,其实时LVS有持久化的机制。当用户发起多次请求时,同一个用户的请求会被转发到第一次请求的真实服务器,默认时间是300秒(保持默认即可)

  8. 修改LVS的持久化时间

    ipvsadm -E -t 192.168.1.150:80 -s rr -p 5

    -E 编辑一个集群

    -p 持久化时间,单位秒

  9. 查看新的配置是否生效

    ipvsadm -Ln

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第95张图片

  10. 再次重新请求发现负载均衡还是没有生效,那是因为LVS还有一个超时时间(保持默认即可)

  11. 设置tcp连接超时值

    ipvsadm --set 1 1 1

  12. 重新请求看负载均衡策略是否生效,可以通过命令查看请求持久化的信息

    ipvsadm -Lnc

    在这里插入图片描述

    expire 失效时间

    source 源地址

    virtual 虚拟ip地址

    destination 目标地址

Keepalived+LVS高可用

keepalived本身就是为了LVS而设计的,提供了很多增强功能,它们的匹配度结合度都非常的高。可以对LVS集群中的真实服务器进行健康检查,通过keepalived就能配置LVS和RS的关系,比如说负载均衡的算法,持久化链接,健康检查配置等。

服务器配置:

  1. 192.168.1.151:LVS的MASTER

  2. 192.168.1.152:LVS的BACKUP

  3. 192.168.1.171:LVS的第一个RS,装有Nginx

  4. 192.168.1.172:LVS的第二个RS,装有Nginx

通过Keepalived配置LVS

  1. 给151和150安装keepalived

  2. 打开151的keepalived核心配置文件

    vim /etc/keepalived/keepalived.conf

  3. 配置全局块

    global_defs {
    	# 删除不需要的配置项
    	# 路由id:当前安装的keepalived节点主机的标识符,全局唯一
    	router_id LVS_151
    }
    
  4. 配置vrrp实例块

    vrrp_instance VI_1 {
    	# 表示此实例的状态,当前151LVS的主节点,MASTER/BACKUP
        state MASTER
        # 当前实例绑定的网卡(虚拟ip要和网卡绑定在一起,可以通过ip addr命令查看,每个人linux系统网卡名称可能不同)
        interface ens33
        # 虚拟路由ip,保证主备节点一致(在同一个路由器组中)
        virtual_router_id 51
        # 优先级/权重,谁的优先级高,在MASTER宕机之后,就能成为MASTER
        priority 100
        # 主备之间同步检查的时间间隔,默认1s
        advert_int 1
    
    	# 认证授权的密码,防止非法节点进入,主备之间要一模一样
        authentication {
            auth_type PASS
            auth_pass 1111
        }
    	# 配置虚拟ip
        virtual_ipaddress {
            192.168.1.150
        }
    }
    
  5. 配置虚拟服务块

    # 定义LVS集群服务,可以是IP+PORT;也可以是fwmark 数字,也就是防火墙规则,端口和Nginx保持一致都是80IP和端口之间用空格隔开
    # 所以通过这里就可以看出来keepalive天生就是为ipvs而设计的
    virtual_server 192.168.1.150 80 {
        # 健康检查的时间,单位秒
    	delay_loop 6
     	# 负载均衡的算法,默认是轮询
    	lb_algo rr
    	# LVS的模式 NAT|DR|TUN
    	lb_kind DR
    	# 子网掩码,这个掩码是VIP的掩码
    	nat_mask 255.255.255.0
    	# 设置会话持久连接超时时间
    	persistence_timeout 50
    	# 定义协议 -t
    	protocol TCP
    	# 如果后端应用服务器都不可用,就会定向到那个服务器上
    	sorry_server 192.168.1.181 80
    
        # RS真实服务器,也就是Nginx节点的具体的真实ip地址,后端应用服务器 IP PORT
        real_server 192.168.1.171 80 {
            # 权重
        	weight 1
            # MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET这些都是
            # 如果应用服务器不是WEB服务器,就用TCP_CHECK检查
            TCP_CHECK {
                # 向哪一个端口检查,如果不指定默认使用上面定义的端口
                connect_port 80
                # 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
                bindto 192.168.1.171
                # 连接检查的超时时间 3s
                connect_timeout 3
                # 重试次数 2次
                nb_get_retry 2
                # 间隔时间 3s
                delay_before_retry 3
            }
    	}
        
        # 配置第二台Nginx节点
        real_server 192.168.1.172 80 {
            # 权重
        	weight 1
            # MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET这些都是
            # 如果应用服务器不是WEB服务器,就用TCP_CHECK检查
            TCP_CHECK {
                # 向哪一个端口检查,如果不指定默认使用上面定义的端口
                connect_port 80
                # 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
                bindto 192.168.1.172
                # 连接检查的超时时间 3s
                connect_timeout 3
                # 重试次数 2次
                nb_get_retry 2
                # 间隔时间 3s
                delay_before_retry 3
            }
    	}
    }
    
  6. 清除151原来配置的LVS规则信息

    ipvsadm -C

    -C 清除所有的LVS规则

  7. 重启keepalived并查看LVS配置是否生效

    ipvsadm -Ln

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第96张图片

  8. 测试访问虚拟ip150能不能访问到Nginx

  9. 打开152的keepalived核心配置文件

    vim /etc/keepalived/keepalived.conf

  10. 配置全局块

    global_defs {
    	# 删除不需要的配置项
    	# 路由id:当前安装的keepalived节点主机的标识符,全局唯一
    	router_id LVS_152
    }
    
  11. 配置vrrp实例块

    vrrp_instance VI_1 {
    	# 表示此实例的状态,当前152LVS的备用节点,MASTER/BACKUP
        state BACKUP
        # 当前实例绑定的网卡(虚拟ip要和网卡绑定在一起,可以通过ip addr命令查看,每个人linux系统网卡名称可能不同)
        interface ens33
        # 虚拟路由ip,保证主备节点一致(在同一个路由器组中)
        virtual_router_id 51
        # 优先级/权重,谁的优先级高,在MASTER宕机之后,就能成为MASTER,官方建议是相差50
        priority 50
        # 主备之间同步检查的时间间隔,默认1s
        advert_int 1
    
    	# 认证授权的密码,防止非法节点进入,主备之间要一模一样
        authentication {
            auth_type PASS
            auth_pass 1111
        }
    	# 配置虚拟ip
        virtual_ipaddress {
            192.168.1.150
        }
    }
    
  12. 配置虚拟服务块

    # 定义LVS集群服务,可以是IP+PORT;也可以是fwmark 数字,也就是防火墙规则,端口和Nginx保持一致都是80IP和端口之间用空格隔开
    # 所以通过这里就可以看出来keepalive天生就是为ipvs而设计的
    virtual_server 192.168.1.150 80 {
        # 健康检查的时间,单位秒
    	delay_loop 6
     	# 负载均衡的算法,默认是轮询
    	lb_algo rr
    	# LVS的模式 NAT|DR|TUN
    	lb_kind DR
    	# 子网掩码,这个掩码是VIP的掩码
    	nat_mask 255.255.255.0
    	# 设置会话持久连接超时时间
    	persistence_timeout 50
    	# 定义协议 -t
    	protocol TCP
    	# 如果后端应用服务器都不可用,就会定向到那个服务器上
    	sorry_server 192.168.1.181 80
    
        # RS真实服务器,也就是Nginx节点的具体的真实ip地址,后端应用服务器 IP PORT
        real_server 192.168.1.171 80 {
            # 权重
        	weight 1
            # MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET这些都是
            # 如果应用服务器不是WEB服务器,就用TCP_CHECK检查
            TCP_CHECK {
                # 向哪一个端口检查,如果不指定默认使用上面定义的端口
                connect_port 80
                # 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
                bindto 192.168.1.171
                # 连接检查的超时时间 3s
                connect_timeout 3
                # 重试次数 2次
                nb_get_retry 2
                # 间隔时间 3s
                delay_before_retry 3
            }
    	}
        
        # 配置第二台Nginx节点
        real_server 192.168.1.172 80 {
            # 权重
        	weight 1
            # MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET这些都是
            # 如果应用服务器不是WEB服务器,就用TCP_CHECK检查
            TCP_CHECK {
                # 向哪一个端口检查,如果不指定默认使用上面定义的端口
                connect_port 80
                # 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
                bindto 192.168.1.172
                # 连接检查的超时时间 3s
                connect_timeout 3
                # 重试次数 2次
                nb_get_retry 2
                # 间隔时间 3s
                delay_before_retry 3
            }
    	}
    }
    
  13. 清除152原来配置的LVS规则信息

    ipvsadm -C

  14. 重启keepalived并查看LVS配置是否生效

    ipvsadm -Ln

  15. 关闭MASTER节点的keepalived,检查BACKUP节点能不能和虚拟ip150绑定在一起(ip漂移技术)

    ip addr

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第97张图片

  16. 重新尝试访问Nginx,并查看结果

  17. 恢复MASTER的keepalived,检查151是否和150绑定在一起

    ip addr

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第98张图片

  18. 关闭171服务器的Nginx,模拟Nginx宕机,查看虚拟ip访问结果和LVS的RS列表,可以看到171的Nginx服务已经从LVS的RS集群中被剔除出去了(通过端口检查)

    171服务器执行:/usr/local/nginx/sbin/nginx -s stop

    151服务器执行:ipvsadm -Ln

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第99张图片

  19. 重启171服务器的Nginx,模拟Nginx恢复,查看虚拟ip访问结果和LVS的RS列表,可以看到171的Nginx服务已经被重新添加到了LVS的RS集群中

    171服务器执行:/usr/local/nginx/sbin/nginx

    151服务器执行:ipvsadm -Ln

    【7W字长文】使用LVS+Keepalived实现Nginx高可用,一文搞懂Nginx_第100张图片

至此完毕

万分感谢此篇文章中所引用链接的所有作者

转载链接:https://blog.csdn.net/weixin_45405982/article/details/122905763

你可能感兴趣的:(高可用架构,nginx,运维,lvs)