Nginx学习笔记

Nginx全面学习:安装、配置与应用

1.什么是Nginx

1.1.简介

​ Nginx是一个高性能的HTTP反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的http://Rambler.ru站点开发的,第一个公开版本0.1.0发布于2004年10月4日。 其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。

​ Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

​ Nginx在处理高并发方面能力是十分强大的,能经受高负 载的考验,有报告表明能支持高达 50,000 个并发连接数。Nginx支持热部署,启动简单,可以做到7*24不间断运行。几个月都不需要重新启动。Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署。

1.2.特点

  • 高并发、高性能。
  • 模块化架构使得它的扩展性非常好。
  • 异步非阻塞的事件驱动模型这点和 Node.js 相似。
  • 相对于其它服务器来说它可以连续几个月甚至更长而不需要重启服务器使得它具有高可靠性。
  • 热部署、平滑升级。
  • 完全开源,生态繁荣。

2.为什么要使用Nginx

​ Nginx同Apache一样都是一种WEB服务器。基于REST架构风格,以统一资源描述符(Uniform Resources Identifier)URI或者统一资源定位符(Uniform Resources Locator)URL作为沟通依据,通过HTTP协议提供各种网络服务。然而,这些服务器在设计之初受到当时环境的局限,例如当时的用户规模,网络带宽,产品特点等局限并且各自的定位和发展都不尽相同。这也使得各个WEB服务器有着各自鲜明的特点。

​ Apache的发展时期很长,而且是毫无争议的世界第一大服务器。它有着很多优点:稳定、开源、跨平台等等。它出现的时间太长了,它兴起的年代,互联网产业远远比不上现在。所以它被设计为一个重量级的。它不支持高并发的服务器。在Apache上运行数以万计的并发访问,会导致服务器消耗大量内存。操作系统对其进行进程或线程间的切换也消耗了大量的CPU资源,导致HTTP请求的平均响应速度降低。这些都决定了Apache不可能成为高性能WEB服务器轻量级高并发服务器Nginx就应运而生了。

​ 随着当今互联网的迅速发展,单点服务器早已无法承载上万个乃至数十万个用户的持续访问。比如一台Tomcat服务器在理想状态下只能够可以承受住2000个左右的并发量,为了解决这个问题,就需要多台Tomcat服务器来进行负载均衡。那么,应该如何实现负载均衡?Nginx就是其中的一种解决方案,当用户访问网站时,Nginx拦截到这个访问请求,并将其通过轮询等方式均匀地分配到不同的服务器上。

​ 另外,Nginx本身在处理静态资源的访问是一个强项,在当今动静分离项目非常流行的时代,前端静态资源项目大多数都是采用Nginx进行部署的。因为项目中包含大量的html、css、js图像等静态资源,Nginx能非常快速高效的处理这些静态资源请求,大大提高了网站的响应速度,优化了用户体验。

3.Nginx安装

Nginx官网地址:http://nginx.org/

Nginx安装步骤都较为简单。

3.1.Linux安装

先下载所需依赖包:

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

选择稳定版下载后,上传至Linux环境,选择好目录之后直接解压:tar -zxvf 文件名(如果需要解压到指定目录,加上:-C 指定的路径),解压完成后直接进入解压后的目录,依次执行以下命令:

./configure

make

make install (如果报错,执行:sudo make install)

都没有报错即证明安装成功。执行下面命令启动Nginx:

cd /usr/local/nginx/sbin/
./nginx

随后浏览器访问http://ip:80进入下面页面即正常启动:

在这里插入图片描述

  • 访问不了查看网络环境是否通畅。
  • 查看防火墙状态是否开放80端口,或者关闭防火墙。
systemctl status firewalld //查看防火墙状态

systemctl stop firewalld   //关闭防火墙

systemctl disable firewalld //禁用防火墙

3.2.Windows安装

下载压缩包,解压即安装。注意:安装的目录不能有空格和中文字符,点击nginx.exe的时候会报错。

启动方式有两种:

1.直接双击nginx.exe启动。

2.打开cmd命令窗口,切换到nginx解压目录下,输入命令 nginx.exe ,回车即可

同样浏览器访问:http://ip:80访问即可。

4.常用基本命令

启动Nginx:

./nginx

重启Nginx:

#热重启,更新配置文件后不需要停止再启动
./nginx -s reload

停止Nginx:

#快速停止
./nginx -s stop

#处理完请求之后再停止
./nginx -s quit

校验Nginx配置文件语法是否有错误:

./nginx -t

PS:Windows版中命令没有./。

查看Nginx进程:

ps -aux | grep nginx

5.配置文件解析

以Linux版的配置文件举例,先来看一个结构图:

在这里插入图片描述

5.1.默认的配置文件内容

#user  nobody;
worker_processes  1;
 
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
 
#pid        logs/nginx.pid;
 
events {
    worker_connections  1024;
}
 
http {
    include       mime.types;
    default_type  application/octet-stream;
 
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
 
    #access_log  logs/access.log  main;
 
    sendfile        on;
    #tcp_nopush     on;
 
    #keepalive_timeout  0;
    keepalive_timeout  65;
 
    #gzip  on;
 
    server {
        listen       80;
        server_name  localhost;
 
        location / {
            root   html;
            index  index.html index.htm;
        }
 
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
 
    # 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;
    #    }
    #}
}

1.设置worker进程的用户,指的linux中的用户,会涉及到nginx操作目录或文件的一些权限,默认为nobody

user root;

2.worker进程工作数设置,一般来说CPU有几个就设置几个,或者设置为N-1也行,或者设置为自动(auto)

worker_processes 1;

3.nginx 日志级别debug | info | notice | warn | error | crit | alert | emerg,错误级别从左到右越来越大

4.设置nginx进程 pid

pid logs/nginx.pid;

5.设置工作模式

events {
	# 默认使用epoll
	use epoll; 
	# 每个worker允许连接的客户端最大连接数
	worker_connections 1024;
}

6.http 是指令块,针对http网络传输的一些指令配置

http {
 
}

7.include 引入外部配置,提高可读性,避免单个配置文件过大

include mime.types;

8.设定日志格式,main为定义的格式名称,如此 access_log 就可以直接使用这个变量了

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

9.sendfile使用高效文件传输,提升传输性能。启用后才能使用tcp_nopush,是指当数据表累积一定大小后才发送,提高了效率

sendfile on;
 
tcp_nopush on;

10.keepalive_timeout设置客户端与服务端请求的超时时间,保证客户端多次请求的时候不会重复建立新的连接,节约资源损耗。

keepalive_timeout  65;

11.gzip启用压缩,html/js/css压缩后传输会更快

gzip on;

12.server可以在http指令块中设置多个虚拟主机, 用于定义服务,http中可以有多个server块

  • listen 监听端口
  • server_name localhost、ip、域名
  • location 请求路由映射,匹配拦截
  • root 请求位置
  • index 首页设置
server {
     listen       88;
     server_name  localhost;
    
     location / {
         root   html;
         index  index.html index.htm;
     }
}

13.server_name

​ 服务名称,用于配置域名

14.location

​ 用于配置映射路径uri对应的配置,一个server中可以有多个location, location后面跟一个uri,可以是一个正则表达式, / 表示匹配任意路径, 当客户端访问的路径满足这个uri时就会执行location块里面的代码

15.root

​ 根路径,当访问http://localhost/test.html,“/test.html”会匹配到”/”uri, 找到root为/usr/local/var/www/html,用户访问的资源物理地址=root + uri = /usr/local/var/www/html + /test.html=/usr/local/var/www/html/test.html

16.index

​ 设置首页,当只访问server_name时后面不跟任何路径是不走root直接走index指令的;如果访问路径中没有指定具体的文件,则返回index设置的资源,如果访问http://localhost/html/ 则默认返回index.html

5.2.Nginx配置文件规则

location uri的正则表达式

  • . :匹配除换行符以外的任意字符
  • ? :重复0次或1次
  • + :重复1次或更多次
  • * :重复0次或更多次
  • \d :匹配数字
  • ^ :匹配字符串的开始
  • $ :匹配字符串的结束
  • {n} :重复n次
  • {n,} :重复n次或更多次
  • [c] :匹配单个字符c
  • [a-z] :匹配a-z小写字母的任意一个
  • (a|b|c) : 属线表示匹配任意一种情况,每种情况使用竖线分隔,一般使用小括号括住,匹配符合a字符 或是b字符 或是c字符的字符串
  • \ 反斜杠:用于转义特殊字符

​ 小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容。正则里面容易让人困惑的是\转义特殊字符。例如,\d 表示匹配一个数字字符,\s 表示匹配一个空白字符,\w 表示匹配一个单词字符,匹配一个真正的反斜杠字符 \,使用 \\。这些都是由反斜杠 \ 转义了原始字符的特殊序列。

5.3.常见的location路径映射路径

  • = 进行普通字符精确匹配。也就是完全匹配。
  • ^~ 指定一个非正则表达式的优先前缀匹配。如果匹配成功,则不再匹配其他location。
  • ~ 表示执行一个正则匹配,区分大小写
  • ~* 表示执行一个正则匹配,不区分大小写
  • /xxx/ 常规字符串路径匹配
  • / 通用匹配,任何请求都会匹配到

5.4.location优先级

当一个路径匹配多个location时究竟哪个location能匹配到时有优先级顺序的,而优先级的顺序于location值的表达式类型有关,和在配置文件中的先后顺序无关。相同类型的表达式,字符串长的会优先匹配。

以下是按优先级排列说明:

  • 等号类型(=)的优先级最高。一旦匹配成功,则不再查找其他匹配项,停止搜索。
  • ^~类型表达式,不属于正则表达式。一旦匹配成功,则不再查找其他匹配项,停止搜索。
  • 正则表达式类型(~ 和 ~*)的优先级其次。如果有多个location的正则能匹配的话,则使用正则表达式最长的那个。
  • 常规字符串匹配类型。按前缀匹配。例如:/images/ ,请求URI是/images/开头的就会匹配。
  • / 通用匹配,如果以上都没有匹配到,就匹配通用的。

优先级搜索:不同类型的location映射决定是否继续向下搜索其他location配置。

  • 精确匹配 (=):如果请求 URI 与 = 后面的字符串完全匹配,则停止搜索其他 location,直接使用该配置。
  • 前缀匹配 (^~):如果请求 URI 以 ^~ 后面的字符串开头,则停止搜索其他非正则表达式的 location,直接使用该配置。
  • 正则表达式匹配 (~~\*):如果请求 URI 匹配正则表达式,则停止搜索其他正则表达式的 location,直接使用该配置。~ 区分大小写,~* 不区分大小写。
  • 最长前缀匹配:如果请求 URI 匹配多个前缀匹配或正则表达式匹配的 location,则选择匹配路径最长的 location。例如:有 /images/ 和 /images/photos/ 两个location规则,如果一个请求 URI 是 /images/photos/example.jpg,由于第二个匹配到的规则更长一些,所以会选用第二个配置。
  • 普通字符串匹配:如果以上都没有匹配,则使用普通字符串的前缀匹配,匹配路径中包含的 location
  • 通用匹配 (/):如果以上都没有匹配,则使用 / 作为通用匹配。

location优先级从高到底:

(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)

5.5.其他指令

proxy_pass:用于反向代理到其他服务器。

proxy_pass http://localhost:8080; # 反向代理到本地 8080 端口

try_files:用于尝试不同的文件或路径来响应请求。

try_files $uri $uri/ /index.html?$args; # 尝试查找文件或路径,$args代表请求路径中的参数,可实现跳转指定文件、内部跳转新的location等。

rewrite:用于重写 URL。

rewrite ^/old$ /new permanent; # 重写 URL,permanent代表永久重定向,返回客户端301状态码,临时重定向使用redirect,返回客户端302状态码

error_page:用于指定错误页面。

error_page 404 /404.html; # 指定 404 错误页面

index:指定默认的索引文件。

index index.html index.htm index.html; # 默认索引文件顺序

root:指定服务器的根目录,用于存放网站文件。

root /var/www/html; # 网站文件存放目录

ssl_certificatessl_certificate_key:用于配置 SSL 证书和密钥。

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

include:用于包含其他配置文件或片段。

include /etc/nginx/conf.d/*.conf;  # 包含其他配置文件

set:设置变量。

set $var "value"; # set设置的变量在server块中只能在当前server块中使用,在http块中则所有的server块都可以使用。

alias:用于指定一个替代的路径来处理客户端请求。

location /images/ {
    alias /data/images/;
}  # 例如请求路径是:http://example.com/images/image.jpg 时,Nginx 会将请求映射到 /data/images/image.jpg 文件

4.Nginx反向代理

​ 提到Nginx,可能第一印象想到的就是反向代理,说到反向代理就不得不提到正向代理。

什么是正向代理?

​ 正向代理,就是客户端将自己的请求率先发给代理服务器,通过代理服务器将请求转发给服务器。我们常用的VPN就是一种代理服务器,为了可以连上国外的网站,客户端需要使用一个可以连接外网的服务器作为代理,并且客户端能够连接上该代理服务器。例如:我们平时访问谷歌、GitHub等网站的时候,由于这些网站的服务器在国外,所以响应会非常慢甚至无法访问,这时候我们就会采用一些手段搭梯子、翻墙来帮助我们实现快速访问。我们向代理端发送请求,再由代理端帮助我们把请求发送到目标服务器,再把目标服务器的响应返回给客户端,这就完成了正向代理。简而言之:正向代理就是代理了客户端。

什么是反向代理?

​ 反向代理与正向代理不同,正向代理是代理了客户端,而反向代理则是代理服务器端。在有多台服务器分布的情况下,为了能让客户端访问到的IP地址都为同一个网站,就需要使用反向代理。比如:我们访问淘宝的时候,淘宝内部肯定不是只有一台服务器,它的内部有很多台服务器,那我们进行访问的时候,因为服务器中间session不共享,那我们是不是在服务器之间访问需要频繁登录,那这个时候淘宝搭建一个过渡服务器,对我们是没有任何影响的,我们是登录一次,但是访问所有,这种情况就是 反向代理。对我们来说,客户端对代理是无感知的,客户端不需要任何配置就可以访问,我们只需要把请求发送给反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,再返回给客户端,这就完成了反向代理。简而言之:反向代理就是代理了服务端。

在这里插入图片描述
在这里插入图片描述

6.Nginx负载均衡

什么是负载均衡?

​ 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。

​ 简单来说就是:现有的请求使服务器压力太大无法承受,所有我们需要搭建一个服务器集群,去分担原先一个服务器所承受的压力,那现在我们有ABCD等等多台服务器,我们需要把请求分给这些服务器,但是服务器可能大小也有自己的不同,所以怎么分?如何分配更好?又是一个问题。

Nginx给出来三种关于负载均衡的方式:

6.1.轮询(默认方法)

​ 轮询法又称之为RR(round robin),每个请求按时间顺序逐一分配到不同的后端服务器,也就是说第一次请求分配到第一台服务器上,第二次请求分配到第二台服务器上,如果只有两台服务器,第三次请求继续分配到第一台上,这样循环轮询下去,也就是服务器接收请求的比例是 1:1, 如果后端服务器down掉,能自动剔除。轮询是默认配置,不需要太多的配置。

#upstream指令用于定义一组后端服务器,通常配合server使用实现反向代理和负载均衡
upstream web_servers {
   server localhost:8081;
   server localhost:8082;
}

server {
    listen       80;
    server_name  localhost;

    location / {
        proxy_pass http://web_servers;
    }
 }

6.2.权重(weight)

​ 指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。这种方式比较灵活,当后端服务器性能存在差异的时候,通过配置权重,可以让服务器的性能得到充分发挥,有效利用资源。weight和访问比率成正比,用于后端服务器性能不均的情况。权重越高,在被访问的概率越大。

upstream test {
    server localhost:8081 weight=1;
    server localhost:8082 weight=3;
    server localhost:8083 weight=4 backup;
}
#4次请求只有一次被分配到8081上,其他3次分配到8082上。backup是指热备,只有当8081和8082都宕机的情况下才走8083

6.3.ip_hash

​ 上述方式存在一个问题就是说,在负载均衡系统中,假如用户在某台服务器上登录了,那么该用户第二次请求的时候,因为我们是负载均衡系统,每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的。
我们可以采用ip_hash指令解决这个问题,如果客户已经访问了某个服务器,当用户再次访问时,会将该请求通过哈希算法,自动定位到该服务器。每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

upstream test {
    ip_hash;
    server localhost:8080;
    server localhost:8081;
}

6. 4.fair(第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。这个配置是为了更快的给用户响应

upstream backend {
    fair;
    server localhost:8080;
    server localhost:8081;
}

6.5. url_hash(第三方)

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法

upstream backend {
    hash $request_uri;
    hash_method crc32;
    server localhost:8080;
    server localhost:8081;
}

以上5种负载均衡各自适用不同情况下使用,所以可以根据实际情况选择使用哪种策略模式,不过fair和url_hash需要安装第三方模块才能使用。

7.Nginx动静分离

​ 动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路

upstream web_servers {
       server localhost:8081;
       server localhost:8082;
}

server {
    listen       80;
    server_name  localhost;

    #相当于局部变量,在server中定义的只能在当前server块中使用
    set $doc_root /usr/local/static;

    location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ {
       root $doc_root/img;
    }
    
    #如果静态资源在另一台服务器上,使用下面配置
    location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js)$ {
       proxy_pass http://主机
    }

    location / {
        proxy_pass http://web_servers;
    }

    error_page 500 502 503 504  /50x.html;
    location = /50x.html {
        root $doc_root;
    }
 }

简单实现

​ 在Linux环境中data目录下新建两个文件夹:image和html。 将一个网页资源test.html放置进html文件夹,将一张图片1.jpg放置进image文件夹。然后在Nginx的nginx.conf配置文件中添加如下内容:

location /image/ {
	root /data/;
	autoindex on;
}
		
location /html/ {
	root /data/;
	index index.html index.htm;
}

配置完成后重新加载Nginx

./nginx -s reload

访问:

http://IP:端口/image/1.jpg
http://IP:端口/html/test.html

能正常显示资源内容即表示成功。

8.Nginx中的内置变量

nginx的配置文件中可以使用的内置变量以美元符$开始,也有人称为全局变量。其中部分预定义的变量的值是可以改变的。

  • $args#这个变量等于请求行中的参数,同$query_string
  • $content_length :请求头中的Content-length字段。
  • $content_type :请求头中的Content-Type字段。
  • $document_root :当前请求在root指令中指定的值。
  • $host :请求主机头字段,否则为服务器名称。
  • $http_user_agent :客户端agent信息
  • $http_cookie :客户端cookie信息
  • $limit_rate :这个变量可以限制连接速率。
  • $request_method :客户端请求的动作,通常为GET或POST。
  • $remote_addr :客户端的IP地址。
  • $remote_port :客户端的端口。
  • $remote_user :已经经过Auth Basic Module验证的用户名。
  • $request_filename :当前请求的文件路径,由root或alias指令与URI请求生成。
  • $scheme :HTTP方法(如http,https)。
  • $server_protocol :请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
  • $server_addr :服务器地址,在完成一次系统调用后可以确定这个值。
  • $server_name :服务器名称。
  • $server_port :请求到达服务器的端口号。
  • $request_uri :包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
  • $uri :不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
  • $document_uri :与$uri相同

9.同一个端口代理两个前端项目

将打包后的前端项目分别放在同一工作目录下的不同文件夹中,目录结构例如:

一般打包的前端项目都叫dist,通常打包后的前端项目都会放到Nginx启动目录同级的html文件夹下(当然放其他地方也可以),本案例中以html为父文件夹,分别打包了两个静态资源项目,为了区分开两个前端项目,我把各自的dist文件夹分别改名为了project1project2

server {
	#监听端口,以80为例
    listen       80;
		
	#服务名称,这里写能被DNS解析的域名,没有域名就写服务器的IP地址
    server_name  IP;
		
	location = /project1 {
		root html;
		index  index.html;
		try_files $uri $uri/ /index.html;  
	}
		
	location = /project2 {
		root   html;
		index  index.html index.htm;
		try_files $uri $uri/ /index.html;  
	}
		
	#匹配错误页规则
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
          root   html;
    }
    
    #其他location配置......
}

10.Nginx模拟搭建集群

10.1.简述

​ 当我们了解会搭建nginx负载均衡后,就需要考虑部署nginx服务器的安全性,如果只有一台,这台nginx一旦出现问题,web就会无法访问的情况,所以为了应对这种情况,就需要搭建大于等于两台nginx做主备服务器。这里我们使用keepalived + Nginx实现,采用主备 + 双主配置,示意图如下:

在这里插入图片描述

Keepalived

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

VRRP协议

全称 Virtual Router Redundancy Protocol即虚拟路由冗余协议。可以认为它是实现路由器高可用的容错协议,即将N台提供相同功能的路由器组成一个路由器组(RouterGroup),这个组里面有一个master和多个backup,但在外界看来就像一台一样,构成虚拟路由器,拥有一个虚拟IP(vip,也就是路由器所在局域网内其他机器的默认路由),占有这个IP的master实际负责ARP相应和转发IP数据包,组中的其它路由器作为备份的角色处于待命状态。master会发组播消息,当backup在超时时间内收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级来选举一个backup当master,保证路由器的高可用。

总结:

​ 两台主备机器通过keepalived,虚拟一个IP,也就是VIP,不是贵宾的意思,是Virtual IP的意思。VIP开始为主机器所有,备份机为空闲状态,同时在两台keepalived之间通信相当于有一条心跳线,通过心跳线互相通信,只要主机器监控(通过脚本)到ngin服务停止,则主机器自己停止keepalived,将VIP交给备份机器处理web请求,直至主机器再次恢复正常,将VIP返还给主机器。

集群高可用有2种方式:

1、Nginx+keepalived 主从配置
这种方案,使用一个vip地址,前端使用2台机器,一台做主,一台做备,但同时只有一台机器工作,另一台备份机器在主机器不出现故障的时候,永远处于浪费状态,对于服务器不多的网站,该方案不经济实惠。

2、Nginx+keepalived 双主配置
这种方案,使用两个vip地址,前端使用2台机器,互为主备,同时有两台机器工作,当其中一台机器出现故障,两台机器的请求转移到一台机器负担,非常适合于当前l两台服务器的架构环境。

在这里插入图片描述

10.2.环境准备

keepalived环境
两台Nginx服务器
定义一个虚拟IP

采用虚拟机环境,直接克隆已经安装好Nginx的虚拟机镜像,得到第二台Nginx环境。开启后使用远程连接工具进行连接。

在这里插入图片描述

接下来把两台服务器都使用下面的命令安装keepalived环境

yum install keepalived –y

安装完成后可以看到,在etc目录下生成了一个目录keepalived,目录中有一个keepalived.conf,这就是keepalived的配置文件。

10.3.添加检测脚本

分别在两台环境中添加检测脚本,我采用的路径是在/usr/local/src,新建一个文件存进去,命名为nginx_check.sh。

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

10.4.主备模式

10.4.1.编辑keepalived.conf配置文件

主机:192.168.32.132

修改etc/keepalived目录下的keepalived.conf,其中最底层的(192.168.32.134即为虚拟IP)。

global_defs {
   router_id Nginx_01 # 从机换成02
}

vrrp_script check_nginx {
 script "/usr/local/src/nginx_check.sh"  # 自己写的检测脚本,路径就是检测脚本存放的路径
 interval 2  # 每2s检测一次
 weight -2   # 检测失败(脚本返回非0)则优先级 -5
 fall 2      # 检测连续 2 次失败才算确定是真失败。会用weight减少优先级(1-255之间)
 rise 1      # 检测 1 次成功就算成功。但不修改优先级
} 

vrrp_instance VI_1 {
    state MASTER	 # 备份服务器上将 MASTER 改为 BACKUP
    interface ens33  # 网卡信息
    virtual_router_id 51  # 主、备机的 virtual_router_id 必须相同
    priority 100   # 主、备机取不同的优先级,主机值较大,备份机值较小
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.32.134  // VRRP H 虚拟地址
    }
	track_script {
    	check_nginx
    }
}

从机同上,注意注释中需要更改的地方。

然后编辑Nginx的配置文件,将server_name换成虚拟ip

server_name  192.168.32.134;
10.4.2.启动
./nginx 

systemctl start keepalived.service

keepalived启动不成功,一般都是配置文件有问题,仔细检查。

10.4.3.测试

访问:http://虚拟IP:端口/80,即可正常访问Nginx首页。也可以在Linux环境中部署两个Tomcat,分别放一个测试html进行访问,我们配置文件中如果配置了负载均衡,那么多次点击就会发现访问的是不同的html页面。

使用ip addr 命令查看主机,已经获取到虚拟ip,从机则空闲。

在这里插入图片描述

在这里插入图片描述

​ 此时,关闭主机的Nginx和keepalived,再次访问浏览器发现依然可以正常访问,使用ip addr命令查看,从机已经获取到虚拟IP。至此,主备模式模拟Nginx集群搭建成功。

10.5.双主模式

​ 当了解主备模式后,双主模式就容易配置多了。只需要在每台keepalived配置文件,加上一个vrrp_instance命名vrrp_instance VI_2即可,更改几个参数,设置另一个VIP:192.168.32.135

10.5.1.编辑配置文件
global_defs {
   router_id Nginx_01
}

vrrp_script check_nginx {
 script "/usr/local/src/nginx_check.sh"
 interval 2 
 weight -2
 fall 2
 rise 1
}

vrrp_instance VI_1 {
    state MASTER	
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.32.134
    }
	track_script {
    	check_nginx
    }
}

vrrp_instance VI_2 {
    state MASTER	
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.32.135
    }
	track_script {
    	check_nginx
    }
}

同样,在nginx做负载均衡时,需要在nginx的配置文件中,server_name加上这个192.168.200.210这个VIP2的地址,配置如下:

server_name  192.168.32.134;
server_name  192.168.32.135;
10.5.2.测试

依次重启两台服务,查看ip并在浏览器中访问。此时,访问192.168.32.134和192.168.32.135都能实现负载效果。至此,双主模式搭建完成。

10.6.keepalived配置文件详解(参考)

#全局配置
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
}

# 定义用于实例执行的脚本内容,比如可以在线降低优先级,用于强制切换等。例如上文中的检测Nginx服务的脚本信息。
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
              # 除了检测哈希值还可以检测状态码,比如HTTP的200 表示正常,两种方法二选一即可
              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
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值