Nginx

  1. 1. Nginx简介
    1. 1.1. 什么是Nginx
    2. 1.2. 为什么要用Nginx
    3. 1.3. 什么是正向代理和反向代理?
    4. 1.4. 负载均衡的理解
    5. 1.5. 为什么Nginx性能这么高
    6. 1.6. Nginx怎么处理请求的
  2. 2. Nginx常用命令
  3. 3. 在Docker容器中安装Nginx
    1. 3.1. Setup SSL with NGINX
    2. 3.2. DNS域名解析上加上blog域名
  4. 4. Nginx核心知识点总结
    1. 4.1. 配置文件结构
    2. 4.2. 核心模块指令详解
      1. 4.2.1. 1. 全局配置指令(main context)
      2. 4.2.2. 2. Events块配置
      3. 4.2.3. 3. HTTP核心配置
        1. 4.2.3.1. 基础设置
        2. 4.2.3.2. Server块配置
        3. 4.2.3.3. Location块配置与匹配规则
      4. 4.2.4. 4. 反向代理配置
      5. 4.2.5. 5. 负载均衡配置
      6. 4.2.6. 6. 缓存配置
      7. 4.2.7. 7. 静态文件优化
    3. 4.3. 常用内置变量
    4. 4.4. 性能优化最佳实践
      1. 4.4.1. 1. 系统层面优化
      2. 4.4.2. 2. HTTP层面优化
      3. 4.4.3. 3. 配置验证与调试
    5. 4.5. 安全配置建议
    6. 4.6. 常见配置模板
      1. 4.6.1. 单页应用(SPA)配置
      2. 4.6.2. PHP应用配置
  5. 5. 参考

NGINX is open source software for web serving, reverse proxying, caching, load balancing, media streaming, and more. It started out as a web server designed for maximum performance and stability. In addition to its HTTP server capabilities, NGINX can also function as a proxy server for email (IMAP, POP3, and SMTP) and a reverse proxy and load balancer for HTTP, TCP, and UDP servers.

Nginx简介

什么是Nginx

Nginx(enginx x)是一个高性能的HTTP和反向代理服务器,具有内存少,高并发能力强特点,他可以处理2-3万并发连接数,官方监测能支持5万并发

  1. 处理静态文件, 索引文件以及自动索引,打开文件描述符缓冲
  2. 无缓存的反向代理加速,简单的负载均衡和容错.

为什么要用Nginx

  • 跨平台、配置简单、方向代理、高并发连接:处理2-3万并发连接数,官方监测能支持5万并发,内存消耗小:开启10个nginx才占150M内存 ,nginx处理静态文件好,耗费内存少
  • 而且Nginx内置的健康检查功能:如果有一个服务器宕机,会做一个健康检查,再发送的请求就不会发送到宕机的服务器了。重新将请求提交到其他的节点上

使用Nginx的话还能:

  1. 节省宽带:支持GZIP压缩,可以添加浏览器本地缓存
  2. 稳定性高:宕机的概率非常小
  3. 接收用户请求是异步的

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

正向代理就是一个人发送一个请求直接就到达了目标的服务器(代理客户端)

例如VPN,在电脑上做了一个代理,这个代理会帮你请求外部的资源

反向代理就是请求统一被Nginx接收,nginx反向代理服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了

例如:每天大量的人访问百度,永远都是www.baidu.com这个域名,百度肯定不止一台服务器

反向代理就是代理服务器端的,让你无感知的浏览一些服务器资源,可以让服务更好的部署上线

负载均衡的理解

Nginx提供的负载均衡策略有2种:内置策略和扩展策略,内置策略为轮询,加权轮询,IP hash,扩展策略就是天马行空的感觉

请求依次循环访问服务器就是轮询

加权轮询就是加上权重

IP hash对客户端请求的IP进行hash操作,然后根据hash结果将同一个客户端ip的请求分发给同一台服务器进行处理,可以解决session不共享问题

动静分离:在我们的软件开发中,有些请求是需要后台处理的,有些请求是不需要经过后台处理的(如:CSS,HTML,JS,jpg等文件),这些不需要经过后台处理的文件称为静态文件。让动态网站里的动态网页根据一定规则把不变的资源和经常变得资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,提高资源响应速度

为什么Nginx性能这么高

因为它的事件处理机制:异步非阻塞事件处理机制:运用了epoll模型,提供了一个队列,排队解决

Nginx怎么处理请求的

nginx接收一个请求后,首先由listen和server_name指令匹配server模块,再匹配server模块里的location,location就是实际地址

1
2
3
4
5
6
7
8
server {                              # 第一个Server区块开始,表示一个独立的虚拟主机站点
listen 80; # 提供服务的端口,默认80
server_name localhost; # 提供服务的域名主机名
location / { # 第一个location区块开始
root html; # 站点的根目录,相当于Nginx的安装目录
index index.html index.htm; # 默认的首页文件,多个用空格分开
} # 第一个location区块结果
}

Nginx常用命令

1
2
3
4
5
6
cd /usr/local/nginx/sbin/
./nginx # 启动
./nginx -s stop # 停止
./nginx -s quit # 安全退出
./nginx -s reload # 重新加载配置文件
ps aux | grep nginx # 查看nginx进程

默认80端口,如果连接不上,检查服务器防火墙是否开放端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 开启
service firewalld start
# 重启
service firewalld restart
# 关闭
service firewalld stop
# 查看防火墙规则
firewall-cmd --list-all
# 查询端口是否开放
firewall-cmd --query-port=8000/tcp
# 开放80端口
firewall-cmd --permanent --add-port=80/tcp
# 移除端口
firewall-cmd --permanent --remove-port=8080/tcp

# 重启防火墙(修改配置后需要重启防火墙)
firewall-cmd --reload

# 参数解释
1. firewall-cmd:是linux提供的操作firewall的一个工具
2. --permanent:表示设置为持久
3. --add-port:标识添加的端口

在Docker容器中安装Nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 启动新容器绑定80和443端口 容器名ubuntu 镜像名ubuntu1
docker run -it -p 80:80 -p 443:443 --name ubuntu ubuntu1 /bin/bash

# 更新
apt update && apt upgrade

# 安装 nano
apt install nano

# 安装 nginx
apt-get install nginx

# 运行 nginx
service nginx start

Setup SSL with NGINX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cd /etc/nginx/conf.d

# make a new configuration
nano blog.tyokyo320.com.conf

# make a new directory to hold nginx SSL certain key
mkdir /etc/nginx/ssl

# give it the necessary permissions for read and write
chmod 700 /etc/nginx/ssl

# 安装 openssl
apt-get install openssl

# 生成私有密钥
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/blog.key -out /etc/nginx/ssl/blog.crt

接下来编辑配置文件的内容

1
2
# modify configuration
nano blog.tyokyo320.com.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server{
listen 80 default_server;
server_name blog.tyokyo320.com;
return 301 https://$server_name$request_uri;


}

server{
listen 443 ssl;
server_name blog.tyokyo320.com;

# ssl_certificate -- Specifies public key
ssl_certificate /etc/nginx/ssl/blog.crt;
# ssl_certificate_key -- Specifies private key
ssl_certificate_key /etc/nginx/ssl/blog.key;

location / {
root /usr/share/nginx/html;
index index.html index.html;
}

}

这里需要将/etc/nginx/conf.d中的blog.tyokyo320.com.conf移动到/etc/nginx/sites-available

1
2
# 当前路径 /etc/nginx/sites-available
mv ../conf.d/blog.tyokyo320.com.conf .

然后备份sites-available下的default文件

1
mv default default.bak

再删除/etc/nginx/sites-enabled下的default链接文件

1
2
# 当前路径 /etc/nginx/sites-available
rm ../sites-enabled/default

最后在sites-enabled建立一个blog.tyokyo320.com.conf的软链接

1
2
# 当前路径 /etc/nginx/sites-enabled
ln -s ../sites-available/blog.tyokyo320.com.conf .

执行结果

1
2
3
root@5602de98f6a6:/etc/nginx/sites-enabled# ls -l
total 0
lrwxrwxrwx 1 root root 42 Sep 11 06:46 blog.tyokyo320.com.conf -> ../sites-available/blog.tyokyo320.com.conf

最后检查一下配置文件是否成功

1
2
3
root@5602de98f6a6:/etc/nginx/sites-enabled# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

成功的话可以reload了

1
nginx -s reload

退出容器返回NUC,编辑~/docker/frp/frpc.ini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[common]
server_addr = 3.19.55.120
server_port = 7000

[ssh]
type = tcp
local_ip = 172.17.0.1
local_port = 22
remote_port = 6000

[blog_http]
type = tcp
local_ip = 172.17.0.1
local_port = 80
remote_port = 80
custom_domains = blog.tyokyo320.com

[blog_https]
type = tcp
local_ip = 172.17.0.1
local_port = 443
remote_port = 443
custom_domains = blog.tyokyo320.com

DNS域名解析上加上blog域名

Nginx核心知识点总结

配置文件结构

Nginx的配置文件采用层级化结构,由指令(directive)和上下文(context)组成:

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
# 全局块(main context)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

# events块
events {
worker_connections 1024;
use epoll;
multi_accept on;
}

# http块
http {
# http全局配置
include /etc/nginx/mime.types;
default_type application/octet-stream;

# server块(虚拟主机配置)
server {
listen 80;
server_name example.com;

# location块(请求路由配置)
location / {
root /usr/share/nginx/html;
index index.html;
}

location /api {
proxy_pass http://backend;
}
}
}

配置文件位置

  • /etc/nginx/nginx.conf(主配置文件)
  • /etc/nginx/conf.d/*.conf(额外配置文件)
  • /etc/nginx/sites-available/(可用站点配置)
  • /etc/nginx/sites-enabled/(已启用站点配置)

核心模块指令详解

1. 全局配置指令(main context)

指令 说明 示例
user 运行worker进程的用户 user nginx;
worker_processes worker进程数量,建议设为CPU核心数或auto worker_processes auto;
worker_cpu_affinity 绑定worker进程到特定CPU worker_cpu_affinity auto;
worker_rlimit_nofile 每个worker进程的最大文件描述符数 worker_rlimit_nofile 65535;
error_log 错误日志路径和级别 error_log /var/log/nginx/error.log warn;
pid 主进程PID文件位置 pid /var/run/nginx.pid;

错误日志级别(从低到高):debuginfonoticewarnerrorcritalertemerg

2. Events块配置

1
2
3
4
5
6
7
8
9
10
11
12
13
events {
# 每个worker进程的最大连接数
worker_connections 1024;

# 使用高效的事件模型(Linux推荐epoll,FreeBSD推荐kqueue)
use epoll;

# 一个worker进程可以同时接受多个新连接
multi_accept on;

# 使用互斥锁方式序列化accept(默认off)
accept_mutex off;
}

最大并发连接数计算max_clients = worker_processes × worker_connections

3. HTTP核心配置

基础设置
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
http {
# MIME类型定义
include /etc/nginx/mime.types;
default_type application/octet-stream;

# 字符集
charset utf-8;

# 日志格式
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 /var/log/nginx/access.log main;

# 优化文件传输
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# 连接超时设置
keepalive_timeout 65;
keepalive_requests 100;

# 客户端请求限制
client_max_body_size 20m;
client_body_timeout 60s;
client_header_timeout 60s;

# Gzip压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript;
}
Server块配置
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
server {
# 监听端口和地址
listen 80;
listen [::]:80; # IPv6
listen 443 ssl http2; # HTTPS with HTTP/2

# 虚拟主机名称(支持通配符和正则)
server_name example.com www.example.com;
# server_name *.example.com;
# server_name ~^www\d+\.example\.com$;

# 网站根目录
root /var/www/html;
index index.html index.htm;

# SSL配置
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

# 访问日志
access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log;
}
Location块配置与匹配规则

匹配优先级(从高到低):

  1. location = /path - 精确匹配(最高优先级)
  2. location ^~ /path - 前缀匹配(阻止正则匹配)
  3. location ~ pattern - 区分大小写的正则匹配
  4. location ~* pattern - 不区分大小写的正则匹配
  5. location /path - 普通前缀匹配(最低优先级)
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
# 精确匹配,优先级最高
location = / {
return 200 "exact match";
}

# 前缀匹配,阻止正则检查
location ^~ /static/ {
root /var/www;
}

# 区分大小写的正则匹配
location ~ \.(jpg|png|gif)$ {
root /var/www/images;
}

# 不区分大小写的正则匹配
location ~* \.(JPG|PNG|GIF)$ {
root /var/www/images;
}

# 普通前缀匹配
location /api/ {
proxy_pass http://backend;
}

# 通用匹配(兜底)
location / {
root /usr/share/nginx/html;
index index.html;
}

常用Location指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
location /app/ {
# 设置根目录
root /var/www; # 实际路径:/var/www/app/

# 别名(替换location路径)
alias /var/www/application/; # 实际路径:/var/www/application/

# 按顺序检查文件是否存在
try_files $uri $uri/ /index.html;

# 自定义错误页面
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

# 限制HTTP方法
limit_except GET POST {
deny all;
}

# 限制访问速率
limit_rate 500k;
}

4. 反向代理配置

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
location /api/ {
# 代理到后端服务器
proxy_pass http://backend_server;

# 传递原始请求头
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_set_header X-Forwarded-Proto $scheme;

# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;

# 缓冲设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;

# WebSocket支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

5. 负载均衡配置

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
# upstream块定义后端服务器组
upstream backend {
# 负载均衡策略:
# 1. 轮询(默认)
# 2. weight - 加权轮询
# 3. ip_hash - 根据客户端IP分配
# 4. least_conn - 最少连接数
# 5. hash - 自定义hash键

# 加权轮询
server 192.168.1.101:8080 weight=3;
server 192.168.1.102:8080 weight=1;
server 192.168.1.103:8080 backup; # 备份服务器
server 192.168.1.104:8080 down; # 标记为不可用

# 健康检查参数
server 192.168.1.105:8080 max_fails=3 fail_timeout=30s;

# 保持连接
keepalive 32;
}

# IP Hash策略(解决session问题)
upstream backend_iphash {
ip_hash;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}

# 最少连接策略
upstream backend_leastconn {
least_conn;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}

# 使用upstream
server {
listen 80;
server_name example.com;

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

6. 缓存配置

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
# 定义缓存路径和参数
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=my_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;

server {
location / {
# 启用缓存
proxy_cache my_cache;

# 缓存状态码和时间
proxy_cache_valid 200 304 10m;
proxy_cache_valid 404 1m;

# 缓存键
proxy_cache_key "$scheme$request_method$host$request_uri";

# 添加缓存状态头
add_header X-Cache-Status $upstream_cache_status;

# 绕过缓存条件
proxy_cache_bypass $http_pragma $http_authorization;

proxy_pass http://backend;
}
}

7. 静态文件优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
root /var/www/static;

# 过期时间
expires 30d;

# 添加缓存控制头
add_header Cache-Control "public, immutable";

# 访问日志关闭(提升性能)
access_log off;

# 文件描述符缓存
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}

常用内置变量

变量 说明
$host 请求的主机名
$uri 当前请求的URI(不含参数)
$request_uri 完整的原始请求URI(含参数)
$args 请求参数
$remote_addr 客户端IP地址
$remote_port 客户端端口
$server_addr 服务器地址
$server_name 服务器名称
$scheme 请求协议(http/https)
$request_method 请求方法(GET/POST等)
$http_user_agent 客户端User-Agent
$http_referer 来源页面
$status 响应状态码
$body_bytes_sent 发送的字节数

性能优化最佳实践

1. 系统层面优化

1
2
3
4
5
6
7
8
9
10
# nginx.conf
worker_processes auto;
worker_rlimit_nofile 65535;
worker_cpu_affinity auto;

events {
worker_connections 4096;
use epoll;
multi_accept on;
}

2. HTTP层面优化

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
http {
# 启用高效文件传输
sendfile on;
tcp_nopush on;
tcp_nodelay on;

# 启用压缩
gzip on;
gzip_vary on;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript;

# 文件缓存
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;

# 减少超时时间
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;

# 隐藏版本号(安全)
server_tokens off;
}

3. 配置验证与调试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 测试配置文件语法
nginx -t

# 查看配置文件路径
nginx -V

# 重新加载配置(平滑重启)
nginx -s reload

# 查看nginx进程
ps aux | grep nginx

# 实时查看访问日志
tail -f /var/log/nginx/access.log

# 实时查看错误日志
tail -f /var/log/nginx/error.log

安全配置建议

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
http {
# 隐藏版本号
server_tokens off;

# 限制请求方法
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405;
}

server {
# 防止点击劫持
add_header X-Frame-Options "SAMEORIGIN" always;

# XSS防护
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

# HTTPS强制跳转
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}

# SSL安全配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';

# HSTS(HTTP严格传输安全)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# 限制请求速率(防DDoS)
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_req zone=one burst=5;
}
}

常见配置模板

单页应用(SPA)配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 80;
server_name app.example.com;
root /var/www/app/dist;
index index.html;

location / {
try_files $uri $uri/ /index.html;
}

location /api {
proxy_pass http://backend;
}

location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}

PHP应用配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
listen 80;
server_name php.example.com;
root /var/www/php;
index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

location ~ /\. {
deny all;
}
}

参考