Nginx综述

俞飞鸣
2023-12-01

nginx使用综述

1.什么是正向代理服务器和反向代理服务器?
1.1 正向代理服务器
客户端和目标服务器之间的服务器,客户端向代理发送一个请求指定目标服务器,然后代理向目标服务器请求并获得内容,并返回给客户端,平时说的代理服务器一般是正向代理服务器,如跳板机(知道自己要访问什么)。
1.2 反向代理服务器
客户端和目标服务器之间的服务器,客户端向代理发送一个请求,然后代理向目标服务器请求并获得内容,并返回给客户端。反向代理隐藏了真实的服务器(真实要访问的被隐藏),如访问taobao,但不知道该域名打到背后哪台资源。

2.Nginx目录文件讲解
2.1 默认目录

/usr/local/nginx

2.2 目录核心

conf  #所有配置文件目录
  nginx.conf    #默认的主要的配置文件
  nginx.conf.default  #默认模板
​
html  # 这是编译安装时Nginx的默认站点目录
  50x.html #错误页面
  index.html #默认首页
  
logs  # nginx默认的日志路径,包括错误日志及访问日志
  error.log  #错误日志
  nginx.pid  #nginx启动后的进程id
  access.log #nginx访问日志
​
sbin  #nginx命令的目录
  nginx  #启动命令

2.3 常见的命令

./nginx  #默认配置文件启动
​
./nginx -s reload #重启,加载默认配置文件
​
./nginx -c /usr/local/nginx/conf/nginx.conf #启动指定某个配置文件
​
./nginx -s stop #停止
​
#关闭进程,nginx有master process 和worker process,关闭master即可
ps -ef | grep "nginx" 
kill -9 PID 

2.4 nginx.conf文件

# 每个配置项由配置指令和指令参数 2 个部分构成
#user  nobody;  # 指定Nginx Worker进程运行以及用户组
worker_processes  1;   # 正常情况下与CPU核数一致
​
#error_log  logs/error.log;  # 错误日志的存放路径  和错误日志
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
​
#pid        logs/nginx.pid;   # 进程PID存放路径
​
​
# 事件模块指令,用来指定Nginx的IO模型,Nginx支持的有select、poll、kqueue、epoll 等。不同的是epoll用在Linux平台上,而kqueue用在BSD系统中,对于Linux系统,epoll工作模式是首选
events { 
    use epoll; #异步非阻塞(性能会更高,默认没有,可新增)
  # 定义Nginx每个进程的最大连接数, 作为服务器来说: worker_connections * worker_processes,
  # 作为反向代理来说,最大并发数量应该是worker_connections * worker_processes/2。因为反向代理服务器,每个  并发会建立与客户端的连接和与后端服务的连接,会占用两个连接
    worker_connections  1024; 
}
​
​
​
​
http {
    include       mime.types;
    default_type  application/octet-stream;
    # 自定义服务日志
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
​
    #access_log  logs/access.log  main;
​
    # 是否开启高效传输模式 on开启 off关闭
    sendfile        on;
    
    #减少网络报文段的数量
    #tcp_nopush     on;
​
    #keepalive_timeout  0;
    # 客户端连接保持活动的超时时间,超过这个时间之后,服务器会关闭该连接
    keepalive_timeout  65;
​
    #gzip  on;
    
    # 虚拟主机的配置
    server {
        listen       80; # 虚拟主机的服务端口
        server_name  localhost; #用来指定IP地址或域名,多个域名之间用空格分开
​
        #charset koi8-r;
​
        #access_log  logs/host.access.log  main;
​
        #URL地址匹配
        location / {
            root   html;  # 服务默认启动目录
            index  index.html index.htm; #默认访问文件,按照顺序找
        }
​
        #error_page  404              /404.html;   #错误状态码的显示页面
​
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
​
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}
​
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}
​
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
​
​
    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;
​
    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}
​
​
    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;
​
    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;
​
    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;
​
    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;
​
    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}
}

3.access.log日志详解
3.1 access.log日志的用处
统计站点访问ip来源、某个时间段的访问频率
查看访问最频的页面、Http响应状态码、接口性能
接口秒级访问量、分钟访问量、小时和天访问量

默认配置:

#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
#                  '$status $body_bytes_sent "$http_referer" '
#                  '"$http_user_agent" "$http_x_forwarded_for"';

案例:

122.70.148.18 - - [04/Aug/2020:14:46:48 +0800] "GET /user/api/v1/product/order/query_state?product_id=1" 200 48 "https://baidu.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"

解析

$remote_addr 对应的是真实日志里的122.70.148.18,即客户端的IP。
​
$remote_user 对应的是第二个中杠“-”,没有远程用户,所以用“-”填充。
​
[$time_local]对应的是[04/Aug/2020:14:46:48 +0800]。
​
“$request”对应的是"GET /user/api/v1/product/order/query_state?product_id=1"。
​
$status对应的是200状态码,200表示正常访问。
​
$body_bytes_sent对应的是48字节,即响应body的大小。
​
“$http_referer” 对应的是”https://baidu.com/“,若是直接打开域名浏览的时,referer就会没有值,为”-“。
​
“$http_user_agent” 对应的是”Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:56.0) Gecko/20100101 Firefox/56.0”。
​
“$http_x_forwarded_for” 对应的是”-“或者空。

3.2
查看访问最频繁的前100个IP

awk '{print $1}' access_temp.log | sort -n |uniq -c | sort -rn | head -n 100

基础

awk 是文本处理工具,默认按照空格切分,$N 是第切割后第N个,从1开始
​
​
sort命令用于将文本文件内容加以排序,-n 按照数值排,-r 按照倒序来排
  案例的sort -n 是按照第一列的数值大小进行排序,从小到大,倒序就是 sort -rn
​
uniq 去除重复出现的行列, -c 在每列旁边显示该行重复出现的次数。

4。负载均衡配置
4.1 概念
将数据流量分摊到多个服务器执行,减轻每台服务器的压力,从而提高了数据的吞吐量。
4.2 配置策略分析
轮询配置(默认)
简介:每个请求按顺序分配到不同的后端服务器
场景:会造成可靠性低和负载分配不均衡,适合静态文件服务器

upstream lbs {
   server 127.0.0.1:8080;
   server 127.0.0.1:8081;
}
​
location /api/ {
    proxy_pass http://lbs;
    proxy_redirect default;
}

weight 权重配置
简介:weight和访问比率成正比,数字越大,分配得到的流量越高
场景:服务器性能差异大的情况使用

upstream lbs {
   server 127.0.0.1:8080 weight=5;
   server 127.0.0.1:8081 weight=10; 
}

ip_hash(固定分发)
简介:根据请求按访问ip的hash结果分配,这样每个用户就可以固定访问一个后端服务器
场景:服务器业务分区、业务缓存、Session需要单点的情况

upstream lbs {
   ip_hash;
   server 127.0.0.1:8080;
   server 127.0.0.1:8081;
}

down 表示当前的server暂时不参与负载

server 127.0.0.1:8080 down;

backup 其它所有的非backup机器down的时候,会请求backup机器,这台机器压力会最轻,配置也会相对低

server 127.0.0.1:8080 backup;

实践操作:
如果某个应用挂了,请求不应该继续分发过去;
参数解释:

max_fails=N 设定Nginx与后端节点通信的尝试失败的次数。
在fail_timeout参数定义的时间内,如果失败的次数达到此值,Nginx就这个节点不可用。
在下一个fail_timeout时间段到来前,服务器不会再被尝试。
失败的尝试次数默认是1,如果设为0就会停止统计尝试次数,认为服务器是一直可用的。

具体什么是nginx认为的失败呢?
可以通过指令proxy_next_upstream来配置什么是失败的尝试。
注意默认配置时,http_404状态不被认为是失败的尝试。

upstream lbs {
                server 127.0.0.1:8080 max_fails=2 fail_timeout=60s ;
                server 127.0.0.1:8081 max_fails=2 fail_timeout=60s;
}
​
​
location /api/ {
         proxy_pass http://lbs;
         proxy_next_upstream error timeout http_500 http_503 http_404;
}

5.Nginx的经典应用
5.1 全局异常兜底数据返回
任何接口都是可能出错,4xx、5xx等
如果业务没有做好统一的错误管理,直接暴露给用户,无疑是看不懂
所以假如后端某个业务出错,nginx层也需要进行转换
让前端知道Http响应是200,其实是将错误的状态码定向至200,返回了全局兜底数据

location / {
            proxy_pass http://lbs;
            proxy_redirect default;
           
            # 存放用户的真实ip
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;  
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
            
            proxy_next_upstream error timeout http_503 non_idempotent;
​
            #开启错误拦截配置,一定要开启
            proxy_intercept_errors on;
  }
​
# 不加 =200,则返回的就是原先的http错误码;配上后如果出现500等错误都返回给用户200状态,并跳转至/default_api
  error_page  404 500 502 503 504  =200  /default_api;
  location = /default_api {
    default_type application/json;
    return 200 '{"code":"-1","msg":"invoke fail, not found "}';
 }

5.2 Nginx封禁恶意IP
TCP洪水攻击、注入攻击、DOS等
比较难防的有DDOS等
数据安全,防止对手爬虫恶意爬取,封禁IP
linux server的层面封IP:iptables(推荐)
nginx的层面封IP ,方式多种 (但 req还是会打进来, 让nginx 返回 403, 占用资源)

单独网站屏蔽IP的方法,把include xxx; 放到网址对应的在server{}语句块,虚拟主机
所有网站屏蔽IP的方法,把include xxx; 放到http {}语句块。
​
nginx配置如下:
​
http{
    # ....
    include blacklist.conf;
}
​
location / {
                proxy_pass http://lbs;
                proxy_redirect default;
}
​
​
#blacklist.conf目录下文件内容
deny 127.0.0.1;
deny 192.168.159.2;

./nginx -s reload #重新加载配置,不中断服务

拓展-自动化封禁思路
编写shell脚本
AWK统计access.log,记录每秒访问超过60次的ip,然后配合nginx或者iptables进行封禁
crontab定时跑脚本

5.3 Nginx开启浏览器跨域
跨域:协议、域名、端口三个有一个不同
浏览器控制台跨域提示:No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘null’ is therefore not allowed access。
解决方法:
1.JSONP(现在没啥人用了)
2.Http响应头配置允许跨域
2.1 nginx层配置
2.2 程序代码中处理通过拦截器配置

Nginx开启跨域配置
location下配置

location / { 
    add_header 'Access-Control-Allow-Origin' $http_origin;
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS';
​
#如果预检请求则返回成功,不需要转发到后端
  if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Max-Age' 1728000;
      add_header 'Content-Type' 'text/plain; charset=utf-8';
      add_header 'Content-Length' 0;
      return 200;
    }
  
}

5.4 Nginx的locatioin规则应用

^ 以什么开始
$ 以什么结束
​
^/api/user$

location = /uri = 表示精准匹配,只要完全匹配上才能生效;
location /uri 不带任何修饰符,表示前缀匹配(常用);
location ^~ /uri/ 匹配任何已 /uri/ 开头的任何查询并且停止搜索(常用);
location / 通用匹配,任何未匹配到其他location的请求都会匹配到;
正则匹配:
区分大小写匹配(~)
不区分大小写匹配(~*)
优先级(不要写复杂,容易出问题和遗忘)
精准匹配 > 字符串匹配(若有多个匹配项匹配成功,那么选择匹配长的并记录) > 正则匹配

server { 
​
   server_name 127.0.0.1;   
​
   location ~^/api/pub$ { 
      ...
    }
​
}
​
^/api/pub$这个正则表达式表示字符串必须以/开始,以b $结束,中间必须是/api/pub
​
http://127.0.0.1/api/v1 匹配(完全匹配)
​
http://127.0.0.1/API/PUB 不匹配,大小写敏感
​
http://127.0.0.1/api/pub?key1=value1 匹配
​
http://127.0.0.1/api/pub/ 不匹配
​
http://127.0.0.1/api/public 不匹配,不能匹配正则表达式

5.5 rewrite规则和应用(重写-重定向)
rewrite 地址重定向,实现URL重定向的重要指令,他根据regex(正则表达式)来匹配内容跳转到

rewrite ^/(.*)  https://baidu.com/$1 permanent
# 这是一个正则表达式,匹配完整的域名和后面的路径地址
# replacement部分是https://baidu.com/$1,$1是取自regex部分()里的内容

应用场景
非法访问跳转,防盗链
网站更换新域名
http跳转https
不同地址访问同一个虚拟主机的资源

5.6 nginx 配置websocket反向代理

server {
  listen    80;
  server_name baidu.com;
  location / {
   proxy_pass http://lbs;
   proxy_read_timeout 300s; //websocket空闲保持时长
   proxy_set_header Host $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_http_version 1.1;
   
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection $connection_upgrade;
  } 
}

核心是下面的配置 其他和普通反向代理没区别, 表示请求服务器升级协议为WebSocket

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

服务器处理完请求后,响应如下报文# 状态码为101

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: upgrade

6.Nginx缓存配置
6.1常见的开发人员控制的缓存分类
数据库缓存
应用程序缓存
Nginx网关缓存
前端缓存
6.2 关键参数
/root/cache 本地路径,用来设置Nginx缓存资源的存放地址;
levels=1:2 默认所有缓存文件都放在上面指定的根路径中,可能影响缓存的性能,推荐指定为 2 级目录来存储缓存文件;1和2表示用1位和2位16进制来命名目录名称。第一级目录用1位16进制命名,如a;第二级目录用2位16进制命名,如3a。所以此例中一级目录有16个,二级目录有16*16=256个,总目录数为16 * 256=4096个;当levels=1:1:1时,表示是三级目录,且每级目录数均为16个;
key_zone 在共享内存中定义一块存储区域来存放缓存的 key 和 metadata;
max_size 最大 缓存空间, 如果不指定会使用掉所有磁盘空间。当达到 disk 上限后,会删除最少使用 的 cache;
inactive 某个缓存在inactive指定的时间内如果不访问,将会从缓存中删除;
proxy_cache_valid 配置nginx cache中的缓存文件的缓存时间,proxy_cache_valid 200 304 2m 对于状态为200和304的缓存文件的缓存时间是2分钟;
use_temp_path 建议为 off,则 nginx 会将缓存文件直接写入指定的 cache 文件中;
proxy_cache 启用proxy cache,并指定key_zone,如果proxy_cache off表示关闭掉缓存
add_header Nging-Cache “$upstream_cache_status” 用于前端判断是否是缓存,miss、hit、expired(缓存过期)、updating(更新,使用旧的应答).

proxy_cache_path /root/cache levels=1:2 keys_zone=xd_cache:10m max_size=1g inactive=60m use_temp_path=off;
​
server {
​
      location /{
        ...     
        proxy_cache xd_cache;
        proxy_cache_valid 200 304 10m;
        proxy_cache_valid 404 1m; 
        proxy_cache_key $host$uri$is_args$args;
        add_header Nginx-Cache "$upstream_cache_status";
      }
  }

注意:
nginx缓存过期影响的优先级进行排序为:inactvie > 源服务器端Expires/max-age > proxy_cache_valid
如果出现 Permission denied 修改nginx.conf,将第一行修改为 user root
默认情况下GET请求及HEAD请求会被缓存,而POST请求不会被缓存,并非全部都要缓存,可以过滤部分路径不用缓存

缓存清空
直接rm删除
ngx_cache_purge

缓存命中率统计
前端打点日志上报
nginx日志模板增加信息
$upstream_cache_status

Nginx性能优化之静态资源压缩
对文本、js和css文件等进行压缩,一般是压缩后的大小是原始大小的25%

#开启gzip,减少我们发送的数据量
gzip on;
gzip_min_length 1k;
​
#4个单位为16k的内存作为压缩结果流缓存
gzip_buffers 4 16k;
​
#gzip压缩比,可在1~9中设置,1压缩比最小,速度最快,9压缩比最大,速度最慢,消耗CPU
gzip_comp_level 4;
​
#压缩的类型
gzip_types application/javascript text/plain text/css application/json application/xml    text/javascript; 
​
#给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩
gzip_vary on;
​
#禁用IE6以下的gzip压缩,IE某些版本对gzip的压缩支持很不好
gzip_disable "MSIE [1-6].";

压缩是时间换空间,还是空间换时间?
web层主要涉及浏览器和服务器的网络交互,而网络交互显然是耗费时间的。
要尽量减少交互次数。
降低每次请求或响应数据量。
开启压缩
在服务端是时间换空间的策略,服务端需要牺牲时间进行压缩以减小响应数据大小
压缩后的内容可以获得更快的网络传输速度,时间是得到了优化
所以是双向的

7.Nginx配置https证书
删除原先Nginx,新增ssl模块

./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
​
make
​
make install
​
#查看是否成功
/usr/local/nginx/sbin/nginx -V
server {
        listen       443 ssl;
        server_name  16web.net;
​
        ssl_certificate      /usr/local/software/biz/key/4383407_16web.net.pem;
        ssl_certificate_key  /usr/local/software/biz/key/4383407_16web.net.key;
​
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
​
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
​
        location / {
            root   html;
            index  index.html index.htm;
        }
    }

https访问实操

杀掉原先进程

防火墙关闭或者开放443端口

service firewalld stop

网络安全组开放端口

7.Nginx整合OpenResty
什么是OpenResty, 为什么要用OpenResty?

由章亦春发起,是基于Ngnix和Lua的高性能web平台,内部集成精良的LUa库、第三方模块、依赖, 开发者可以方便搭建能够处理高并发、扩展性极高的动态web应用、web服务、动态网关。 
​
OpenResty将Nginx核心、LuaJIT、许多有用的Lua库和Nginx第三方模块打包在一起
​
Nginx是C语言开发,如果要二次扩展是很麻烦的,而基于OpenResty,开发人员可以使用 Lua 编程语言对 Nginx 核心模块进行二次开发拓展
​
性能强大,OpenResty可以快速构造出1万以上并发连接响应的超高性能Web应用系统

什么是ngx_lua?

ngx_lua是Nginx的一个模块,将Lua嵌入到Nginx中,从而可以使用Lua来编写脚本,部署到Nginx中运行,
​
即Nginx变成了一个Web容器;开发人员就可以使用Lua语言开发高性能Web应用了。

Nginx+OpenRestry的例子

#访问 curl 127.0.0.1,如果浏览器访问会出现文件下载,因为没有Html头信息
http{
    # 虚拟机主机块
    server{
        # 监听端口
        listen 80;
        # 配置请求的路由
        location /{
            default_type text/html;
            content_by_lua_block{
                ngx.say("hello world; baidu.com");
            }
        }
    }
}
​
​
#使用其他方式(读取lua文件)
http{
    # 虚拟机主机块,还需要配置lua文件扫描路径
    lua_package_path "$prefix/lualib/?.lua;;";
    lua_package_cpath "$prefix/lualib/?.so;;";
    server{
        # 监听端口
        listen 80;
        # 配置请求的路由
        location /{
            default_type text/html;
            content_by_lua_file lua/xdclass.lua;
        }
    }
}

nginx对于请求的处理分多个阶段,Nginx , 从而让第三方模块通过挂载行为在不同的阶段来控制, 大致如下
初始化阶段(Initialization Phase)
init_by_lua_file
init_worker_by_lua_file
重写与访问阶段(Rewrite / Access Phase)
rewrite_by_lua_file
access_by_lua_file
内容生成阶段(Content Phase)
content_by_lua_file
日志记录阶段(Log Phase)

Nginx+OpenResty +Lua开发内网访问限制
生产环境-管理后台一般需要指定的网络才可以访问,网段/ip等

http{
​
# 这里设置为 off,是为了避免每次修改之后都要重新 reload 的麻烦。
# 在生产环境上需要 lua_code_cache 设置成 on。
​
lua_code_cache off;
​
# lua_package_path可以配置openresty的文件寻址路径,$PREFIX 为openresty安装路径
# 文件名使用“?”作为通配符,多个路径使用“;”分隔,默认的查找路径用“;;”
# 设置纯 Lua 扩展库的搜寻路径
lua_package_path "$prefix/lualib/?.lua;;";
​
# 设置 C 编写的 Lua 扩展模块的搜寻路径(也可以用 ';;')
lua_package_cpath "$prefix/lualib/?.so;;";
​
server {
     location / {
     access_by_lua_file lua/white_ip_list.lua;
     proxy_pass http://lbs;
     }
}

lua/white_ip_list.lua

local black_ips = {["127.0.0.1"]=true}
​
local ip = ngx.var.remote_addr
if true == black_ips[ip] then
    ngx.exit(ngx.HTTP_FORBIDDEN)
    return;
end

Nginx+OpenRestry开发下载限速
Nginx 有一个 $limit_rate,这个反映的是当前请求每秒能响应的字节数, 该字节数默认为配置文件中 limit_rate 指令的设值

#当前请求的响应上限是 每秒 300K 字节
 location /download {
    access_by_lua_block {
       ngx.var.limit_rate = "300K"
    }
​
    alias /usr/local/software/app;
​
 }

8.Ngnix高可用解决方案LVS+KeepAlived
Nginx高可用解决方案-基础

国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系。
​
从低到高分别是:
​
物理层、数据链路层、网络层、传输层、会话层、表示层和应用层
​
四层工作在OSI第四层 也就是传输层
​
七层工作在最高层,也就是应用层

LVS(四层负载 tcp):
用虚拟ip+port接收请求,再转发到对应的真实机器
Nginx(七层负载)
用虚拟的url或主机名接收请求,再转向相应的处理服务器
什么是LVS?

LVS是Linux Virtual Server,Linux虚拟服务器,是一个虚拟的服务器集群系统
​
项目是由章文嵩博士成立,是中国国内最早出现的自由软件项目之一
​
Linux2.4 内核以后,LVS 已经是 Linux 标准内核的一部分
​
软件负载解决的两个核心问题是:选谁、转发

什么是keepalived?
核心:监控并管理 LVS 集群系统中各个服务节点的状态

keepalived是一个类似于交换机制的软件,核心作用是检测服务器的状态,如果有一台web服务器工作出现故障,Keepalived将检测到并将有故障的服务器从系统中剔除,使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成。
​
后来加入了vrrp(虚拟路由器冗余协议),除了为lvs提供高可用还可以为其他服务器比如Mysql、Haproxy等软件提供高可用方案

安装

yum install -y keepalived
​
#路径
cd /etc/keepalived

启动和查看命令

#启动
service keepalived start
​
#停止
service keepalived stop
​
#查看状态
service keepalived status
​
#重启
service keepalived restart
​
#停止防火墙
systemctl stop firewalld.service

注意: 如果有缺少依赖可以执行下面的命令

yum install -y gcc
yum install -y openssl-devel
yum install -y libnl libnl-devel
yum install -y libnfnetlink-devel
yum install -y net-tools
yum install -y vim wget

Keepalived核心配置讲解
配置/etc/keepalived/keepalived.conf

! Configuration File for keepalived
​
global_defs {
​
   router_id LVS_DEVEL # 设置lvs的id,在一个网络内应该是唯一的
   enable_script_security #允许执行外部脚本
}
​
​
#配置vrrp_script,主要用于健康检查及检查失败后执行的动作。
vrrp_script chk_real_server {
#健康检查脚本,当脚本返回值不为0时认为失败
    script "/usr/local/software/conf/chk_server.sh"
#检查频率,以下配置每2秒检查1次
    interval 2
#当检查失败后,将vrrp_instance的priority减小5
    weight -5
#连续监测失败3次,才认为真的健康检查失败。并调整优先级
    fall 3
#连续监测2次成功,就认为成功。但不调整优先级
    rise 2
​
    user root
}
​
​
​
#配置对外提供服务的VIP vrrp_instance配置
​
vrrp_instance VI_1 {
​
#指定vrrp_instance的状态,是MASTER还是BACKUP主要还是看优先级。
    state MASTER
​
#指定vrrp_instance绑定的网卡,最终通过指定的网卡绑定VIP
    interface ens33
​
#相当于VRID,用于在一个网内区分组播,需要组播域内内唯一。
    virtual_router_id 51
​
#本机的优先级,VRID相同的机器中,优先级最高的会被选举为MASTER
    priority 100
​
#心跳间隔检查,默认为1s,MASTER会每隔1秒发送一个报文告知组内其他机器自己还活着。
    advert_int 1
​
    authentication {
        auth_type PASS
        auth_pass 1111
    }
​
#定义虚拟IP(VIP)为192.168.159.100,可多设,每行一个
    virtual_ipaddress {
        192.168.159.100
    }
​
    #本vrrp_instance所引用的脚本配置,名称就是vrrp_script 定义的容器名
  track_script {
      chk_real_server
    }
}
​
# 定义对外提供服务的LVS的VIP以及port
virtual_server 192.168.159.100 80 {
    # 设置健康检查时间,单位是秒
    delay_loop 6
​
    # 设置负载调度的算法为rr
    lb_algo rr
​
    # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
    lb_kind NAT
​
    # 会话保持时间
    persistence_timeout 50
​
   #指定转发协议类型(TCP、UDP)
    protocol TCP
​
    # 指定real server1的IP地址
​
    real_server 192.168.159.146 80 {
        # 配置节点权值,数字越大权重越高
        weight 1
​
        # 健康检查方式
        TCP_CHECK {                  # 健康检查方式
            connect_timeout 10       # 连接超时
            retry 3           # 重试次数
            delay_before_retry 3     # 重试间隔
            connect_port 80          # 检查时连接的端口
        }
​
    }
​
}

配置注意:

router_id后面跟的自定义的ID在同一个网络下是一致的
​
state后跟的MASTER和BACKUP必须是大写;否则会造成配置无法生效的问题
​
interface 网卡ID;要根据自己的实际情况来看,可以使用以下方式查询 ip a  查询
​
在BACKUP节点上,其keepalived.conf与Master上基本一致,修改state为BACKUP,priority值改小即可
​
authentication主备之间的认证方式,一般使用PASS即可;主备的配置必须一致,不能超过8位

准备Nginx+Lvs+KeepAlive相关软件环境
启动keepalived

#启动
service keepalived start
​
#停止
service keepalived stop
​
#查看状态
service keepalived status
​
#重启
service keepalived restart
​
#停止防火墙
systemctl stop firewalld.service

如果某个realServer挂了,比如是Nginx挂了,那对应keepalived节点存活依旧可以转发过去,但是响应失败。
脚本监听

#配置vrrp_script,主要用于健康检查及检查失败后执行的动作。
vrrp_script chk_real_server {
#健康检查脚本,当脚本返回值不为0时认为失败
    script "/usr/local/software/conf/chk_server.sh"
#检查频率,以下配置每2秒检查1次
    interval 2
#当检查失败后,将vrrp_instance的priority减小5
    weight -5
#连续监测失败3次,才认为真的健康检查失败。并调整优先级
    fall 3
#连续监测2次成功,就认为成功。但不调整优先级
    rise 2
​
    user root
}

chk_server.sh脚本内容(需要 chmod +x chk_server.sh)

#!/bin/bash
#检查nginx进程是否存在
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" -eq "0" ]; then
    service keepalived stop
    echo 'nginx server is died.......'
fi

常见问题

vip能ping通,vip监听的端口不通: 第一个原因:nginx1和nginx2两台服务器的服务没有正常启动
​
vip ping不通: 核对是否出现裂脑,常见原因为防火墙配置所致导致多播心跳失败,核对keepalived的配置是否正确

特别注意: 需要关闭selinux,不然sh脚本可能不生效
getenforce 查看
setenforce 0 关闭

 类似资料: