必要的原理介绍

● Nginx 里有一个master进程和多个worker进程.master进程并不处理网络请求,主要负责调度工作进程: 加载配置,启动工作进程及非停升级.worker进程负责处理网络请求与响应.
● master进程主要用来管理worker进程,具体包括如下4个主要功能:

  1. 接收来自外界的信号

  2. 向各worker进程发送信号

  3. 监控worker进程的运行状态

  4. 当worker进程退出后(异常情况下),会自动重新启动新的worker进程

● worker进程主要用来处理基本的网络事件:

  1. 多个worker进程之间是对等其相互独立的,他们同等竞争来自客户端的请求.

  2. 一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其他的进程请求.

  3. worker进程的个数是可以设置的,一般我们会设置与机器的cpu核数一致,同时,nginx 为了更好的利用多核特性,具有cpu绑定选项,我们可以将某一个进程绑定在某一核上,这样就不会因为进程的切换带来cache的失效

● master 需要完成的工作
○ 读取并验证配置信息
○ 创建.绑定及关闭套接字
○ 启动,终止及维护 worker 进程的个数
○ 无须中止服务而重新配置工作特性
○ 控制非中断式升级,启动新的二进制程序并在需要时回滚至老版本
○ 重新打开日志文件
○ 编译嵌入式 perl 脚本
● worker 进程主要完成的任务包括
○ 接收,传入并处理来自客户端的连接
○ 提供反向待了及过滤功能
○ nginx 任何能完成的其他工作

Nginx 的请求方式处理
● Nginx 是一个高性能的 web 服务器,能够同时处理大量的并发请求。它结合多进程机制和异步机制,异步机制使用的是异步非阻塞方式

多进程机制
● 服务器每当收到一个客户端时就有服务器主进程(master process)生成一个子进程(worker process)出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。
● 使用进程的好处时各个进程之间时相互独立,不需要加锁,减少了使用锁对性能造成的影响,同时降低了编程的复杂度,降低开发成本。其次采用独立的进程可以让进程之间不会影响,如果一个进程发生异常退出时,其他进程正常工作,master 进程则很快的启动新的 worker 进程,确保服务不会中断,从而将风险降到最低。
● 缺点是操作系统生成一个子进程需要进行内存复制等操作,在资源和时间上会产生一定的开销。当有大量请求时,会导致系统性能下降。
nginx 事件驱动模型
● 在 Nginx 的异步非阻塞机制中,工作进程在调用 IO 后,就去处理其他的请求,当 IO 调用返回后,会通知该工作进程。对于这样的系统调用,主要使用 Nginx 服务器的事件驱动模型来实现。

● nginx 事件驱动模型由事件收集器和事件处理器三部分基本单元组成
○ 事件收集器 负责收集 worker 进程 IO 请求;
○ 事件发送器: 负责将 IO 事件发送到事件处理器;
○ 事件处理器: 负责各种事件的响应工作
● 事件发送器将每个请求放入一个待处理事件列表,使用非阻塞 I/O 方式调用 事件处理器 来处理该请求,其处理方式称为"多路 IO 复用方法,"常见的包括以下三种 select 模式,poll 模型.epoll 模型
Nginx 进程处理模型
● nginx 服务器使用 master/worker 多进程模式,多线程启动和执行的流程如下:

  1. 主程序 master process 启动后,通过一个 for 循环来接收和处理外部信号

  2. 主进程通过 fork 函数产生 worker 子进程,每个子进程执行一个 for 循环来实现 Nginx 服务器对事件的接收和处理
    当一个 worker 进程在 accept 这个连接之后,就开始 读取请求 , 解析请求 , 处理请求 ,产生数据后,再 返回给客户端 ,最后才 断开连接 ,这样一个完整的请求就是这样的了。我们可以看到,一个请求,完全由 worker 进程来处理,而且只在一个 worker 进程中处理。
    在 Nginx 服务器的运行过程中, 主进程 和 工作进程 需要进程交互。交互依赖于 Socket 实现的 管道 来实现。

第一步当然是安装了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#安装 pcre 依赖
wget http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz
#解压压缩文件
tar –xvf pcre-8.37.tar.gz
#进入安装目录后./configure 完成后,回到 pcre 目录下执行 make,最后执行 make install
./configure
make
make install
#安装 openssl 、zlib 、 gcc 依赖
yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel

#安装nginx,解压
./configure
make && make install
#上面如果失败
yum install -y gcc gcc-c++
#进入目录 /usr/local/nginx/sbin/nginx 启动服务
./nginx

常用命令 咱复习一下

1
2
3
4
5
6
7
8
#启动命令,在/usr/local/nginx/sbin 目录下执行
./nginx

#关闭命令,在/usr/local/nginx/sbin 目录下执行
./nginx -s stop

#重新加载命令,在/usr/local/nginx/sbin 目录下执行
./nginx -s reload

核心笔记 配置文件

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
41
#配置文件存在的目录
/usr/local/nginx/conf 下

#1、全局块
#从配置文件开始到 events 块之间的内容,主要会设置一些影响 nginx 服务器整体运行的配置指令,主要包括配
#置运行 Nginx 服务器的用户(组)、允许生成的 worker process 数,进程 PID 存放路径、日志存放路径和类型以
#及配置文件的引入等。
#这是 Nginx 服务器并发处理服务的关键配置,worker_processes 值越大,可以支持的并发处理量也越多,但是
#会受到硬件、软件等设备的制约

worker_processes 1;


#2、events 块
#events 块涉及的指令主要影响 Nginx 服务器与用户的网络连接,常用的设置包括是否开启对多 work process
#下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型来处理连接请求,每个 word
#process 可以同时支持的最大连接数等。
#上述例子就表示每个 work process 支持的最大连接数为 1024.
#这部分的配置对 Nginx 的性能影响较大,在实际中应该灵活配置。
events {
worker_connections 1024;
}


#3、http 块
这算是 Nginx 服务器配置中最频繁的部分,代理、缓存和日志定义等绝大多数功能和第三方模块的配置都在这里。
需要注意的是:http 块也可以包括 http 全局块、server 块。
#3-1 http 全局块
http 全局块配置的指令包括文件引入、MIME-TYPE 定义、日志自定义、连接超时时间、单链接请求数上限等。
#3-2 server 块
这块和虚拟主机有密切关系,虚拟主机从用户角度看,和一台独立的硬件主机是完全一样的,该技术的产生是为了
节省互联网服务器硬件成本。
每个 http 块可以包括多个 server 块,而每个 server 块就相当于一个虚拟主机。
而每个 server 块也分为全局 server 块,以及可以同时包含多个 locaton 块。
1、全局 server 块
最常见的配置是本虚拟机主机的监听配置和本虚拟主机的名称或 IP 配置。
2、location 块
一个 server 块可以配置多个 location 块。
这块的主要作用是基于 Nginx 服务器接收到的请求字符串(例如 server_name/uri-string),对虚拟主机名称
(也可以是 IP 别名)之外的字符串(例如 前面的 /uri-string)进行匹配,对特定的请求进行处理。地址定向、数据缓
存和应答控制等功能,还有许多第三方模块的配置也在这里进行。

核心配置 重点来了

反向代理

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#1、反向代理实例一
#通过访问nginx=====》tomcat进行代理
#,修改nginx.conf下面为全部的配置文件,
#192.168.253.130 为你的nginx服务器ip
#http://127.0.0.1:8001 为你的tomcat的访问路径
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 192.168.253.130;

location / {
proxy_pass http://127.0.0.1:8001;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}

#修改tomcat端口为8001,启动tomcat
#重新加载nginx

然后访问 192.168.253.130===》》就会代理到 tomcat服务器



#2、反向代理实例二
#实现效果:使用 nginx 反向代理,根据访问的路径跳转到不同端口的服务中
nginx 监听端口为 9001,准备两台tomcat
访问 http://192.168.253.130:9001/edu/ 直接跳转到tomcat1 127.0.0.1:8081
访问 http://192.168.253.130:9001/vod/ 直接跳转到tomcat2 127.0.0.1:8082

#在 http 块中添加 server{}

所有的配置如下
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 192.168.253.130;

location / {
proxy_pass http://127.0.0.1:8001;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 9001;
server_name 192.168.253.130;

location ~ /edu/ {
proxy_pass http://127.0.0.1:8081;
}

location ~ /vod/ {
proxy_pass http://127.0.0.1:8082;
}
}
}

然后访问 192.168.253.130:9001/edu/a.html
===》》就会代理到 tomcat服务器127.0.0.1:8081//edu/a.html
然后访问 192.168.253.130:9001/vod/a.html
===》》就会代理到 tomcat服务器127.0.0.1:8081/vod/a.html


#####补充说明
1、= :用于不含正则表达式的 uri 前,要求请求字符串与 uri 严格匹配,如果匹配
成功,就停止继续向下搜索并立即处理该请求。
2、~:用于表示 uri 包含正则表达式,并且区分大小写。
3、~*:用于表示 uri 包含正则表达式,并且不区分大小写。
4、^~:用于不含正则表达式的 uri 前,要求 Nginx 服务器找到标识 uri 和请求字
符串匹配度最高的 location 后,立即使用此 location 处理请求,而不再使用 location
块中的正则 uri 和请求字符串做匹配。
注意:如果 uri 包含正则表达式,则必须要有 ~ 或者 ~* 标识。

负载均衡

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#首先准备两个同时启动的Tomcat
配置文件全部如下
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 192.168.253.130;

location / {
proxy_pass http://127.0.0.1:8001;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 9001;
server_name 192.168.253.130;

location ~ /edu/ {
proxy_pass http://127.0.0.1:8081;
}

location ~ /vod/ {
proxy_pass http://127.0.0.1:8082;
}
}

upstream myservers{
server 192.168.253.130:8081;
server 192.168.253.130:8082;
}

server {
listen 9010;
server_name 192.168.253.130;

location / {
proxy_pass http://myservers;
proxy_connect_timeout 10;
}
}


}

#myservers名称自定义
#访问192.168.253.130:9010
=====>>>一个一次
192.168.253.130:8081;
192.168.253.130:8082;


#其他的负载均衡方式
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。

upstream myservers{
server 192.168.253.130:8081;
server 192.168.253.130:8082;
}


2、weight
weight 代表权,重默认为 1,权重越高被分配的客户端越多
upstream myservers{
server 192.168.253.130:8081 weight=1;
server 192.168.253.130:8082 weight=2;
}

3、ip_hash
每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 的问题。
upstream myservers{
ip_hash;
server 192.168.253.130:8081;
server 192.168.253.130:8082;
}

4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream myservers{
server 192.168.253.130:8081;
server 192.168.253.130:8082;
fair;
}

根据文件类型设置过期时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
location ~.*\.css$ {
expires 1d;
break;
}
location ~.*\.js$ {
expires 1d;
break;
}

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
access_log off;
expires 15d; #保存15天
break;
}

# curl -x127.0.0.1:80 http://www.test.com/static/image/common/logo.png -I #测试图片的max-age

禁止文件缓存

1
2
3
location ~* \.(js|css|png|jpg|gif)$ {
add_header Cache-Control no-store;
}

静态文件压缩

1
2
3
4
5
6
7
8
9
10
11
12
server {
# 开启gzip 压缩
gzip on;
# 设置gzip所需的http协议最低版本 (HTTP/1.1, HTTP/1.0)
gzip_http_version 1.1;
# 设置压缩级别,压缩级别越高压缩时间越长 (1-9)
gzip_comp_level 4;
# 设置压缩的最小字节数, 页面Content-Length获取
gzip_min_length 1000;
# 设置压缩文件的类型 (text/html)
gzip_types text/plain application/javascript text/css;
}

指定定错误页面

1
2
3
4
5
# 根据状态码,返回对于的错误页面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /source/error_page;
}复制代码

跨域问题

跨域的定义

  • 同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。通常不允许不同源间的读操作。

同源的定义

  • 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。

nginx解决跨域的原理

例如:

不过只需要启动一个nginx服务器,将server_name设置为xx_domain,然后设置相应的location以拦截前端需要跨域的请求,最后将请求代理回github.com。如下面的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
## 配置反向代理的参数
server {
listen 8080;
server_name xx_domain

## 1. 用户访问 http://xx_domain,则反向代理到 https://github.com
location / {
proxy_pass https://github.com;
proxy_redirect off;
proxy_set_header Host $host; # 传递域名
proxy_set_header X-Real-IP $remote_addr; # 传递ip
proxy_set_header X-Scheme $scheme; # 传递协议
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

重定向配置

1
2
3
4
5
6
7
8
9
10
11
12
location / {
return 404; #直接返回状态码
}
location / {
return 404 "pages not found"; #返回状态码 + 一段文本
}
location / {
return 302 /blog ; #返回状态码 + 重定向地址
}
location / {
return https://www.mingongge.com ; #返回重定向地址
}

Gzip压缩

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
gzip_types  

#压缩的文件类型
text/plain text/css
application/json
application/x-javascript
text/xml application/xml
application/xml+rss
text/javascript

gzip on;
#采用gzip压缩的形式发送数据

gzip_disable "msie6"
#为指定的客户端禁用gzip功能

gzip_static;
#压缩前查找是否有预先gzip处理过的资源

gzip_proxied any;
#允许或者禁止压缩基于请求和响应的响应流

gzip_min_length 1000;
#设置对数据启用压缩的最少字节数

gzip_comp_level 6;
#设置数据的压缩等级

SSL 证书配置及跳转HTTPS配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 192.168.1.250:443 ssl;
server_tokens off;
server_name mingonggex.com www.mingonggex.com;
root /var/www/mingonggex.com/public_html;
ssl_certificate /etc/nginx/sites-enabled/certs/mingongge.crt;
ssl_certificate_key /etc/nginx/sites-enabled/certs/mingongge.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
}

# Permanent Redirect for HTTP to HTTPS
server
{
listen 80;
server_name mingongge.com;
https://$server_name$request_uri;
}

文件只能下载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
location /data {

alias /data/;

if ($request_filename ~* ^.*?\.(doc|pdf|xlsx|png|txt)$) {
add_header Content-Disposition attachment;
add_header Content-Type application/octet-stream;
}

proxy_connect_timeout 3;
proxy_read_timeout 3;
proxy_send_timeout 3;
autoindex on;
sendfile on;
charset utf-8,gbk;
}

只能查看图片

1
2
3
4
5
6
7
8
9
10
11
12
13
1.在图片所在的目录下创建一个名为.htaccess’的隐藏文件,该文件用于设置禁止下载
2.在.htaccess文件中添加以下配置:
SetHandler default-handler
Options-Indexes

这样设置后,用户就无法通过点击链接或使用下载工具下载图片了
接下来,在 nginx的配置文件中添加以下配置
location /path/to/images/ {
add header Content-Disposition "inline";
add header Content-Type "image/jpeg";
}
此配置会为指定路径下的所有图片文件添加Content-Disposition’和Content-Type’头信息,使其只能在线查看。
最后,重启 nginx 服务器使配置生效
1
2
3
4
5
6
7
8
9
location /pic {
alias /data/;
proxy_connect_timeout 3;
proxy_read_timeout 3;
proxy_send_timeout 3;
autoindex on;
add_header Content-Disposition "inline";
add_header Content-Type "image/jpeg";
}