# Nginx基础

# 目录结构

进入Nginx的主目录我们可以看到这些文件夹

├── client_body_temp
├── conf ------------------------------------用来存放配置文件相关
│   ├── fastcgi.conf
│   ├── fastcgi.conf.default
│   ├── fastcgi_params
│   ├── fastcgi_params.default
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types
│   ├── mime.types.default
│   ├── nginx.conf
│   ├── nginx.conf.default
│   ├── scgi_params
│   ├── scgi_params.default
│   ├── uwsgi_params
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp
├── html ------------------------------------用来存放静态文件的默认目录 html、css等
│   ├── 50x.html
│   ├── index.html
│   └── sub.html
├── logs
│   ├── access.log
│   ├── error.log
│   └── nginx.pid
├── proxy_temp
├── sbin ------------------------------------nginx的主程序
│   └── nginx
├── scgi_temp
└── uwsgi_temp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

其中这几个文件夹在刚安装后是没有的,主要用来存放运行过程中的临时文件

client_body_temp 
fastcgi_temp 
proxy_temp 
scgi_temp
1
2
3
4

# 基本运行原理

  1. 通过Nginx安装目录下的sbin/nginx启动Nginx服务
  2. 客户端向Nginx发送请求http://192.168.1.100/index.html
  3. Nginx开启多个子进程接收响应请求:通过conf配置文件解析/index.html 请求(request_rui),读取文件/html/index.html

# Nginx配置与应用场景

# 最小配置

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    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;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  • worker_processes

worker_processes 1; 默认为1,表示开启一个业务进程

  • worker_connections

worker_connections 1024; 单个业务进程可接受连接数

  • include mime.types;

include mime.types;引入http mime类型

  • default_type application/octet-stream;

default_type application/octet-stream; 如果mime类型没匹配上,默认使用二进制流的方式传输。

  • sendfile on;

sendfile on; 使用linux的 sendfile(socket, file, len) 高效网络传输,也就是数据0拷贝。

未开启sendfile

开启sendfile后

  • keepalive_timeout

keepalive_timeout 65; 连接保留时间(秒),默认65

  • server

虚拟主机配置

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;
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 虚拟主机

原本一台服务器只能对应一个站点,通过虚拟主机技术可以虚拟化成多个站点同时对外提供服务。

# server_name 匹配规则

我们需要注意的是server_name匹配分先后顺序,写在前面的匹配上就不会继续往下匹配了。

# 完整匹配

我们可以在同一server_name中匹配多个域名

server_name aotuxx.cn aotuxx.com;
1

# 通配符匹配

server_name *.aotuxx.com;
1

# 通配符结束匹配

server_name aotuxx.*;
1

# 正则匹配

server_name ~^[0-9]+\.aotuxx\.com$;
1

# 反向代理

proxy_pass xxx;

location / { 
    proxy_pass http://aotuxx.cn/; 
}
1
2
3

# 基于反向代理的负载均衡

http {
    include       mime.types; #引入http mime类型
    default_type  application/octet-stream; #如果mime类型没匹配上,默认使用二进制流的方式传输

    sendfile        on; #使用linux的sendfile(socket,file,len)高效网络传输,也就是数据0拷贝
    keepalive_timeout  65; #超过这个时间 没有活动,会让keepalive失效

    #上游服务
    upstream httpd {
        server 192.168.10.202;
        server 192.168.10.203;
        server 192.168.10.204;
    }

    server {
        listen       80; #监听端口号
        server_name  localhost; #主机名

        location / { #匹配路径
            #基于反向代理的负载均衡
            proxy_pass http://httpd;
        }

        error_page   500 502 503 504  /50x.html; #报错编码对应页面
        location = /50x.html {
            root   html;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 负载均衡策略

  • 轮询

默认情况下使用轮询方式,逐一转发,这种方式适用于无状态请求。

  • weight(权重)

指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

upstream httpd { 
    server 192.168.1.1:8080 weight=10 down; 
    server 192.168.1.2:8080 weight=1; 
    server 192.168.1.3:8080 weight=1 backup; 
}
1
2
3
4
5

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

weight:默认为1,weight越大,负载的权重就越大。

backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。

  • ip_hash

根据客户端的ip地址转发同一台服务器,可以保持回话。

upstream httpd { 
    ip_hash;
    server 192.168.1.1:8080; 
    server 192.168.1.2:8080; 
    server 192.168.1.3:8080; 
}
1
2
3
4
5
6
  • least_conn

最少连接访问,请求会被转发到连接数最少的服务器上。

upstream httpd { 
    least_hash;
    server 192.168.1.1:8080; 
    server 192.168.1.2:8080; 
    server 192.168.1.3:8080; 
}
1
2
3
4
5
6
  • url_hash

根据用户访问的url定向转发到同一后端服务器,需要配合缓存命中使用。同一个资源请求会到达同一台机器,一旦缓存住了资源,再收到此请求,就可以直接从缓存中读取返回。

upstream httpd { 
    hash $request_uri;
    server 192.168.1.1:8080; 
    server 192.168.1.2:8080; 
    server 192.168.1.3:8080; 
}
1
2
3
4
5
6
  • fair

根据后端服务器响应时间转发请求,后端响应时间短的优先分配。fail属于第三方模块,直接使用会报错,需要添加nginx-upstream-fair

upstream httpd { 
    fair; #需要添加nginx-upstream-fair模块,否则添加这个配置会报错
    server 192.168.1.1:8080; 
    server 192.168.1.2:8080; 
    server 192.168.1.3:8080; 
}
1
2
3
4
5
6

# 动静分离

添加反向代理

location / { 
    proxy_pass http://127.0.0.1:8080; 
    root html; 
    index index.html index.htm; 
}
1
2
3
4
5

增加每一个 location

location /css { 
    root /usr/local/nginx/static; 
    index index.html index.htm; 
} 
location /images { 
    root /usr/local/nginx/static; 
    index index.html index.htm; 
} 
location /js { 
    root /usr/local/nginx/static; 
    index index.html index.htm; 
}
1
2
3
4
5
6
7
8
9
10
11
12

使用一个 location

location ~*/(css|img|js) { 
    root /usr/local/nginx/static; 
    index index.html index.htm; 
}
1
2
3
4

使用正则

(1)location 前缀

通配符 描述
/ 通用匹配,任何请求都会匹配到
= 精准匹配,不是以指定模式开头
~ 正则匹配,区分大小写
~* 正则匹配,不区分大小写
^~ 非正则匹配,匹配以指定模式开头的location

(2)location 匹配顺序

1)多个正则location直接按书写顺序匹配,成功后就不会继续往后面匹配。

2)普通(非正则)location会一直往下,直到找到匹配度最高的(最大前缀匹配)。

3)当普通location与正则location同时存在,如果正则匹配成功,则不会再执行普通匹配。

4)所有类型location存在时,"="匹配 > "^~"匹配 > 正则匹配 > 普通(最大前缀匹配)。

(3)alias与root

root用来设置根目录,而alias在接受请求的时候在路径上不会加上location。

1)alias指定的目录是准确的,即location匹配访问的path目录下的文件直接是在alias目录下查找的;

2)root指定的目录是location匹配访问的path目录的上一级目录,这个path目录一定要是真实存在root指定目录下的;

3)使用alias标签的目录块中不能使用rewrite的break(具体原因不明);另外alias指定的目录后面必须要加上"/"符号!!

4)alias虚拟目录配置中,location匹配的path目录如果后面不带"/",那么访问的url地址中这个path目录后面加不加"/"不影响访问,访问时它会自动加上"/"; 但是如果location匹配的path目录后面加上"/",那么访问的url地址中这个path目录必须要加上"/",访问时它不会自动加上"/"。如果不加上"/",访问就会失败!

5)root目录配置中,location匹配的path目录后面带不带"/",都不会影响访问。

# Url Rewrite

rewrite 语法格式及参数说明:

rewrite是实现URL重写的关键指令,根据regex (正则表达式)部分内容,重定向到replacement,结尾是flag标记。 

rewrite  <regex>  <replacement>  [flag]; 
关键字    正则      替代内容        flag标记 

关键字:其中关键字error_log不能改变
正则:perl兼容正则表达式语句进行规则匹配 
替代内容:将正则匹配的内容替换成replacement 
flag标记:rewrite支持的flag标记 

rewrite参数的标签段位置: 
server,location,if 

flag标记说明: 
last #本条规则匹配完成后,继续向下匹配新的location URI规则 
break #本条规则匹配完成即终止,不再匹配后面的任何规则 
redirect #返回302临时重定向,浏览器地址会显示跳转后的URL地址 
permanent #返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

实例

upstream httpds { 
    server 192.168.44.102 weight=8 down; 
    server 192.168.44.103:8080 weight=2; 
    server 192.168.44.104:8080 weight=1 backup; 
}

location / { 
    # 将http://127.0.0.1:8080/2.html重写成http://127.0.0.1:8080/index.jsp?pageNum=2
    rewrite ^/([0-9]+).html$ /index.jsp?pageNum=$1 redirect; 
    proxy_pass http://httpds ; 
}
1
2
3
4
5
6
7
8
9
10
11

# 防盗链配置

盗链是直接使用正规网站保存图片、视频等的 URL 以获取相应的资源。盗链会浪费网站的流量,资源被引用的多了,导致服务器压力大,影响服务器性能。

valid_referers none | blocked | server_names | strings ....;
1

none 检测 Referer 头域不存在的情况。

blocked 检测 Referer 头域的值被防火墙或者代理服务器删除或伪装的情况。这种情况该头域的值不以"http://" 或 "https://" 开头。

server_names 设置一个或多个 URL ,检测 Referer 头域的值是否是这些 URL 中的某一个。

在需要防盗链的 location 中配置:

#可以盗链的IP地址,可以把google/baidu/sogou/soso/bing/feedsky/zhuaxia/photozero等搜索引擎域名放进来,便于被搜索引擎收录
valid_referers 192.168.1.101; 
# 注意:if后有空格,()后也有空格
if ($invalid_referer) { 
    return 403; 
}
1
2
3
4
5
6

使用 curl 测试:

curl -I http://192.168.1.101/img/nginx.png
1

带引用:

curl -e "http://baidu.com" -I http://192.168.1.101/img/nginx.png
1

# 高可用配置

Keepalived软件起初是专为LVS(Linux Virtual Server)负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP (Virtual Router Redundancy Protocol ,虚拟路由器冗余协议)功能。因此Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。

Keepalived对高可用服务之间的故障切换转移,是通过 VRRP 来实现的。在 Keepalived服务正常工作时,主 Master节点会不断地向备节点发送(多播的方式)心跳消息,用以告诉备Backup节点自己还活着,当主 Master节点发生故障时,就无法发送心跳消息,备节点也就因此无法继续检测到来自主 Master节点的心跳了,于是调用自身的接管程序,接管主Master节点的 IP资源及服务。而当主 Master节点恢复时,备Backup节点又会释放主节点故障时自身接管的IP资源及服务,恢复到原来的备用角色。

Keepalived的作用是检测服务器的状态,当服务器宕机或工作出现故障,Keepalived将检测到并将服务器集群中剔除,选择其他服务器代替该服务器的工作;当服务器恢复工作正常,Keepalived检测到自动将服务器加入服务器集群。

# Keepalived安装

编译安装

下载地址:https://www.keepalived.org/download.html#

使用 ./configure 编译安装。如遇报错提示:

configure: error: 
	!!! OpenSSL is not properly installed on your system. !!! 
	!!! Can not include OpenSSL headers files. !!!
1
2
3

安装依赖openssl-devel

yum install -y openssl-devel
1

yum 安装

yum install -y keepalived
1

# keepalived配置

使用yum安装后配置文件在 /etc/keepalived/keepalived.conf

最小配置

第一台机器:

! Configuration File for keepalived

global_defs {
   router_id lb03
}

vrrp_instance aotuxx {
    state MASTER #主
    interface ens33 #网卡
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication { #与备用服务一致
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.10.200 #虚拟IP:与备用服务一致
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

第一台机器:

! Configuration File for keepalived

global_defs {
   router_id ld04
}

vrrp_instance aotuxx {
    state BACKUP #备用
    interface ens33 #网卡
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication { #与主服务一致
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.10.200 #虚拟IP:与主服务一致
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 启动服务

systemctl start keepalived
1

# https证书配置

# 不安全的http协议

HTTP是超文本传输协议(Hyper Text Transfer Protocol,HTTP)的简称,这是一个简单的请求-响应协议,属于明文传输,它指定了客户端可能发送给服务器什么样的请求,以及期望服务器能给到什么样的响应。

之所以说它不安全,是因为该协议较为简单,在网络数据传输中信息处于非加密状态,也就是暴露在外,数据的保密性较差,这就导致数据极易遭受恶意攻击,出现被盗取的情况。伴随用户安全意识的提升,目前诸多浏览器厂商都对HTTP协议的网站增加了风险提示,同时也建议各网站增加使用SSL加密证书,提升数据的保密性,以此杜绝数据泄露的风险。

# https协议

  1. 客户端与服务端使用非对称加密将一个秘钥传递给对方。
  2. 双方使用此秘钥通过对称加密通信。

# CA证书

我们知道非对称加密需要一对秘钥:公钥和私钥。当一方拥有了此秘钥对后,最头疼的事情就是如何将公钥安全的传递给对方。因为通讯过程是不安全的,我们不知道公钥在传递过程中会发生什么(中间人攻击)。此时CA就粉墨登场了,其存在的意义就是确保通信的一方可以安全的获取到对方的公钥。

CA: certificate authority , 负责颁发CA证书的机构和组织,都是一些欧美邪恶组织,轻易不让别人加入。

CA证书:CA机构颁发给其他人的证书。主要包含如下信息

  • 申请者公钥
  • 申请者的信息
  • 颁发者(CA)的信息
  • 以上信息的数字签名。 数字签名生成规则:先使用摘要算法,例如SHA256,将以上信息生成摘要,然后CA使用自己的私钥对此摘要加密

# 自签名证书

使用OpenSSL生成多域名自签名证书。

OpenSSL:包含SSL协议库、应用程序以及密码算法库。

https证书配置案例:

#默认为1,表示开启一个业务进程
worker_processes  1;
events {
    #单个业务进程可接受的连接数
    worker_connections  1024;
}

http {
    include       mime.types; #引入http mime类型
    default_type  application/octet-stream; #如果mime类型没匹配上,默认使用二进制流的方式传输
    sendfile        on; #使用linux的sendfile(socket,file,len)高效网络传输,也就是数据0拷贝
    keepalive_timeout  65;

    server {
		server {
		   listen  443 ssl;
		   server_name aa.abc.com;

		   ssl_certificate      /data/cert/server.pem;
		   ssl_certificate_key  /data/cert/server.key;
		}
		
		location / {
            root   html;
            index  index.html;
        }
		
		error_page   500 502 503 504  /50x.html; #报错编码对应页面
        location = /50x.html {
            root   html;
        }
    }

    server {
        listen       80; 
        server_name  www.aotuxx.com aotuxx.com;
		return 301 https://$server_name$request_uri;
        root   html;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40