Nginx是目前世界上最流行、最高性能的Web服务器之一。

对于程序员和运维来说Nginx已经成为了必备技能。无论是搭建网站还是做反向代理还是负载均衡还是静态资源服务Nginx都能出色地完成任务。可以说不会用Nginx的程序员和运维在2015年已经开始落伍了。

我自己从2012年开始接触Nginx到现在已经用了三年多了。从最初的只会用Apache到后来接触Nginx被它的高性能和低资源消耗深深吸引。现在我所有的项目都用Nginx作为Web服务器和反向代理。一路走来踩了不少坑也总结了不少经验。

2015年Nginx已经成为了Web服务器的绝对主流。根据Netcraft的统计Nginx已经超过了Apache成为了全球使用量最大的Web服务器。各大互联网公司包括淘宝、腾讯、百度、京东、新浪等都在大规模使用Nginx。Nginx已经从一个小众的Web服务器变成了主流的Web服务器。

今天分享Nginx高性能Web服务器从什么是Nginx到Nginx的安装到Nginx的配置到Nginx的核心功能到Nginx的性能优化到Nginx的安全加固全方位讲解Nginx的使用方法和技巧帮你掌握这个强大的Web服务器。

什么是Nginx

Nginx(发音同engine x),是一个高性能的HTTP和反向代理服务器也是一个IMAP/POP3/SMTP代理服务器。

Nginx由俄罗斯人Igor Sysoev在2004年开发。最初是为了解决C10K问题(同时处理10000个并发连接),而开发的。Igor Sysoev在Rambler.ru(俄罗斯第二大门户网站),工作时发现Apache在高并发下性能很差资源消耗很大。于是他决定自己开发一个更高性能的Web服务器这就是Nginx。

Nginx的特点:

  1. 高性能:Nginx采用事件驱动的异步非阻塞架构能处理大量的并发连接。官方测试Nginx能支持5万并发连接实际生产环境能支持2-3万并发。这是Apache无法比拟的。
  2. 低资源消耗:Nginx占用的内存和CPU非常少。一个Nginx进程只占用几MB的内存。在高并发下Nginx的资源消耗也远低于Apache。
  3. 高稳定性:Nginx采用master-worker架构master进程管理worker进程worker进程处理请求。如果某个worker进程崩溃了master进程会立即启动一个新的worker进程不会影响服务。Nginx可以连续运行几个月甚至几年不重启。
  4. 热部署:Nginx支持热部署可以在不中断服务的情况下重新加载配置文件升级版本。
  5. 功能丰富:Nginx不仅是一个Web服务器还支持反向代理、负载均衡、静态资源服务、Gzip压缩、SSL/TLS、虚拟主机、URL重写、访问控制、限流等功能。
  6. 模块化设计:Nginx采用模块化设计功能都是通过模块实现的。可以根据需要编译不同的模块。也有很多第三方模块可以扩展Nginx的功能。
  7. 跨平台:Nginx支持Linux、FreeBSD、Solaris、Mac OS X、Windows等多种操作系统。

Nginx和Apache的对比:

特性NginxApache
架构事件驱动异步非阻塞进程驱动同步阻塞
并发高支持5万+低一般几千
资源消耗
静态文件一般
动态文件一般(需配合FastCGI)好(mod_php)
配置简洁复杂
模块少但核心功能全多丰富
.htaccess不支持支持

简单来说Nginx适合高并发、静态资源、反向代理、负载均衡的场景;Apache适合动态内容、需要.htaccess、需要丰富模块的场景。现在很多网站采用Nginx + Apache的架构Nginx处理静态资源和反向代理Apache处理动态内容。

Nginx的安装

1. Linux安装

在Linux上安装Nginx有两种方式:源码编译安装和包管理器安装。

包管理器安装(Ubuntu/Debian)

# 更新软件源
sudo apt-get update

# 安装Nginx
sudo apt-get install -y nginx

# 启动Nginx
sudo service nginx start

# 设置开机自启
sudo update-rc.d nginx defaults

# 验证安装
nginx -v

包管理器安装(CentOS/RHEL)

# 安装EPEL源
sudo yum install -y epel-release

# 安装Nginx
sudo yum install -y nginx

# 启动Nginx
sudo service nginx start

# 设置开机自启
sudo chkconfig nginx on

# 验证安装
nginx -v

源码编译安装

源码编译安装可以选择需要的模块和编译参数更加灵活。

# 安装依赖
sudo apt-get install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev

# 下载Nginx
wget http://nginx.org/download/nginx-1.8.0.tar.gz

# 解压
tar xzf nginx-1.8.0.tar.gz
cd nginx-1.8.0

# 配置
./configure \
    --prefix=/usr/local/nginx \
    --with-http_ssl_module \
    --with-http_gzip_static_module \
    --with-http_stub_status_module \
    --with-pcre

# 编译
make

# 安装
sudo make install

# 验证安装
/usr/local/nginx/sbin/nginx -v

常用的编译参数:

  • --prefix=PATH:安装路径
  • --with-httpsslmodule:启用SSL模块
  • --with-httpgzipstatic_module:启用Gzip静态压缩模块
  • --with-httpstubstatus_module:启用状态监控模块
  • --with-httprealipmodule:启用真实IP模块
  • --with-httpsubmodule:启用内容替换模块
  • --with-pcre:启用PCRE库(支持正则表达式)
  • --with-zlib:启用zlib库(支持Gzip压缩)
  • --add-module=PATH:添加第三方模块

2. Windows安装

在Windows上安装Nginx很简单:

  1. 到Nginx官网下载Windows版本:http://nginx.org/en/download.html
  2. 解压到任意目录如C:\nginx
  3. 运行nginx.exe启动Nginx
  4. 在浏览器访问http://localhost看到Nginx的欢迎页面就说明安装成功了

注意:Windows版本的Nginx主要用于开发和测试不建议在生产环境使用。生产环境建议使用Linux。

3. Nginx的启动、停止、重启

# 启动Nginx
nginx

# 快速停止(立即停止,不处理当前请求)
nginx -s stop

# 优雅停止(处理完当前请求后,再停止)
nginx -s quit

# 重新加载配置文件(热部署)
nginx -s reload

# 重新打开日志文件
nginx -s reopen

# 测试配置文件是否正确
nginx -t

# 查看Nginx版本
nginx -v

# 查看Nginx版本和编译参数
nginx -V

Nginx配置文件

Nginx的配置文件通常是nginx.conf。它由指令和指令块组成。

1. 配置文件结构

Nginx配置文件的基本结构:

# 全局块
user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

# events块
events {
    worker_connections  1024;
}

# http块
http {
    # http全局块
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    # server块(虚拟主机)
    server {
        # server全局块
        listen       80;
        server_name  localhost;

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

        # 错误页面
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }

    # 可以有多个server块
    # server { ... }
}

Nginx配置文件分为几个块:

  • 全局块:配置影响Nginx全局的指令如用户、worker进程数、错误日志、PID文件等。
  • events块:配置Nginx的事件模型和连接数如worker_connections。
  • http块:配置HTTP相关的指令可以包含多个server块。
  • server块:配置一个虚拟主机可以包含多个location块。
  • location块:配置URL的匹配规则和处理方式。

2. 常用指令

全局块指令

  • user:Nginx worker进程运行的用户
  • worker_processes:worker进程数建议设置为CPU核数
  • error_log:错误日志路径和日志级别
  • pid:PID文件路径
  • workerrlimitnofile:worker进程最大打开文件数

events块指令

  • worker_connections:每个worker进程最大并发连接数
  • use:事件模型Linux下建议epoll
  • multi_accept:是否一次接受多个连接

http块指令

  • include:包含其他配置文件
  • default_type:默认的MIME类型
  • sendfile:是否启用sendfile高效传输文件
  • tcpnopush:是否启用TCPNOPUSH减少网络包
  • keepalive_timeout:长连接超时时间
  • gzip:是否启用Gzip压缩
  • clientmaxbody_size:客户端请求体最大大小

server块指令

  • listen:监听的端口和IP
  • server_name:域名可以有多个支持通配符和正则
  • root:网站根目录
  • index:默认首页
  • error_page:错误页面
  • access_log:访问日志

location块指令

  • root:网站根目录
  • alias:别名和root不同
  • index:默认首页
  • proxy_pass:反向代理转发到后端服务器
  • fastcgi_pass:FastCGI转发到PHP-FPM等
  • try_files:尝试访问文件
  • return:返回状态码或重定向
  • rewrite:URL重写

3. location匹配规则

location支持多种匹配方式:

  1. 精确匹配location = /path,精确匹配,/path
  2. 前缀匹配location ^~ /path,前缀匹配,/path开头优先级高于正则
  3. 正则匹配location ~ /path,大小写敏感正则匹配;location ~* /path,大小写不敏感正则匹配
  4. 普通前缀匹配location /path,前缀匹配,/path开头
  5. 通用匹配location /,匹配所有请求

匹配优先级:精确匹配 > ^~前缀匹配 > 正则匹配(按顺序) > 普通前缀匹配 > 通用匹配

4. 虚拟主机配置

Nginx支持基于域名的虚拟主机。每个server块就是一个虚拟主机。

# 第一个网站
server {
    listen 80;
    server_name www.example.com example.com;
    root /var/www/example;
    index index.html index.php;

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

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

# 第二个网站
server {
    listen 80;
    server_name www.test.com;
    root /var/www/test;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Nginx核心功能

1. 静态资源服务

Nginx处理静态资源(HTML、CSS、JS、图片、视频等),性能非常高。

server {
    listen 80;
    server_name www.example.com;
    root /var/www/example;

    # 静态资源缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|swf)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }

    # HTML不缓存
    location ~* \.(html|htm)$ {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
}

2. Gzip压缩

Nginx支持Gzip压缩减少传输数据量加快页面加载速度。

http {
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_vary on;
    gzip_proxied any;
    gzip_disable "MSIE [1-6]\.";
}

3. 反向代理

Nginx作为反向代理转发请求到后端服务器。

server {
    listen 80;
    server_name www.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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_read_timeout 60s;
        proxy_send_timeout 60s;
    }
}

4. 负载均衡

Nginx支持负载均衡把请求分发到多个后端服务器。

http {
    # 定义上游服务器组
    upstream backend {
        server 192.168.1.10:8080 weight=1;
        server 192.168.1.11:8080 weight=2;
        server 192.168.1.12:8080 backup;
        # ip_hash;  # 按IP哈希,同一IP,总是访问同一服务器
        # least_conn;  # 最少连接数
        # fair;  # 响应时间,需要第三方模块
    }

    server {
        listen 80;
        server_name www.example.com;

        location / {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

负载均衡策略:

  • 轮询(默认):按顺序轮流分发请求
  • weight:权重权重高的分发更多请求
  • ip_hash:按IP哈希同一IP总是访问同一服务器解决session问题
  • least_conn:最少连接数分发给连接数最少的服务器
  • fair:响应时间分发给响应最快的服务器(需要第三方模块)
  • backup:备份服务器只有其他服务器都不可用时才使用
  • down:标记服务器不可用

5. PHP-FPM集成

Nginx本身不处理PHP需要通过FastCGI转发到PHP-FPM。

server {
    listen 80;
    server_name www.example.com;
    root /var/www/example;
    index index.php index.html;

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

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

6. URL重写

Nginx支持URL重写把一个URL重写成另一个URL。

server {
    listen 80;
    server_name example.com;

    # 重定向到www
    return 301 http://www.example.com$request_uri;
}

server {
    listen 80;
    server_name www.example.com;
    root /var/www/example;

    location / {
        # 伪静态,把/article/123,重写成/index.php?id=123
        rewrite ^/article/(\d+)$ /index.php?id=$1 last;

        try_files $uri $uri/ /index.php?$query_string;
    }
}

rewrite指令语法:rewrite 正则 替换 标志

标志:

  • last:停止当前location的后续指令重新搜索location
  • break:停止当前location的后续指令继续执行当前location的其他指令
  • redirect:302临时重定向
  • permanent:301永久重定向

7. HTTPS/SSL

Nginx支持HTTPS/SSL。

server {
    listen 443 ssl;
    server_name www.example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    root /var/www/example;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

# HTTP重定向到HTTPS
server {
    listen 80;
    server_name www.example.com;
    return 301 https://$server_name$request_uri;
}

8. 访问控制

Nginx支持基于IP的访问控制。

server {
    listen 80;
    server_name www.example.com;

    # 禁止访问,某些目录
    location /admin {
        allow 192.168.1.0/24;
        deny all;
    }

    # 禁止访问,某些文件
    location ~* \.(env|log|sh|sql)$ {
        deny all;
    }

    # 禁止访问,隐藏文件
    location ~ /\. {
        deny all;
    }
}

9. 限流

Nginx支持限流防止恶意请求和DDoS攻击。

http {
    # 定义限流区域
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

    server {
        listen 80;
        server_name www.example.com;

        location / {
            # 应用限流
            limit_req zone=one burst=20 nodelay;
            try_files $uri $uri/ =404;
        }
    }
}
  • limitreqzone:定义限流区域,$binaryremoteaddr是按IP限流zone=one:10m是区域名one大小10MB,rate=10r/s是每秒10个请求
  • limit_req:应用限流zone=one是使用one区域burst=20是允许突发20个请求nodelay是不延迟超过的直接返回503

Nginx性能优化

1. worker进程优化

# worker进程数,设置为CPU核数
worker_processes auto;

# worker进程,绑定到CPU核
worker_cpu_affinity auto;

# worker进程,最大打开文件数
worker_rlimit_nofile 65535;

2. 事件优化

events {
    # 使用epoll事件模型
    use epoll;

    # 每个worker进程,最大并发连接数
    worker_connections 65535;

    # 一次接受多个连接
    multi_accept on;
}

3. HTTP优化

http {
    # 启用sendfile,高效传输文件
    sendfile on;

    # 启用tcp_nopush,减少网络包
    tcp_nopush on;

    # 启用tcp_nodelay,减少延迟
    tcp_nodelay on;

    # 长连接超时时间
    keepalive_timeout 65;

    # 长连接,最大请求数
    keepalive_requests 1000;

    # 客户端请求头,超时时间
    client_header_timeout 10;

    # 客户端请求体,超时时间
    client_body_timeout 10;

    # 发送超时时间
    send_timeout 10;

    # 客户端请求体,最大大小
    client_max_body_size 20m;
}

4. 静态资源缓存

server {
    # 图片、CSS、JS,缓存30天
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|swf|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }

    # HTML,不缓存
    location ~* \.(html|htm)$ {
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
}

5. Gzip压缩优化

http {
    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 6;  # 压缩级别,1-9,6是性价比最高的
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_vary on;
    gzip_proxied any;
    gzip_disable "MSIE [1-6]\.";
}

6. 系统内核优化

修改,/etc/sysctl.conf:

# 最大打开文件数
fs.file-max = 65535

# TCP最大连接数
net.core.somaxconn = 65535

# TCP接收缓冲区
net.core.rmem_max = 16777216

# TCP发送缓冲区
net.core.wmem_max = 16777216

# TCP接收缓冲区,三个值:最小、默认、最大
net.ipv4.tcp_rmem = 4096 87380 16777216

# TCP发送缓冲区,三个值:最小、默认、最大
net.ipv4.tcp_wmem = 4096 65536 16777216

# 启用TCP时间戳
net.ipv4.tcp_timestamps = 1

# 启用TCP窗口缩放
net.ipv4.tcp_window_scaling = 1

# 启用TCP选择性确认
net.ipv4.tcp_sack = 1

# TCP FIN超时时间
net.ipv4.tcp_fin_timeout = 30

# TCP keepalive空闲时间
net.ipv4.tcp_keepalive_time = 600

# TCP keepalive探测间隔
net.ipv4.tcp_keepalive_intvl = 30

# TCP keepalive探测次数
net.ipv4.tcp_keepalive_probes = 3

# 本地端口范围
net.ipv4.ip_local_port_range = 1024 65535

# 启用SYN Cookie,防止SYN Flood攻击
net.ipv4.tcp_syncookies = 1

# SYN重试次数
net.ipv4.tcp_syn_retries = 2

# SYN+ACK重试次数
net.ipv4.tcp_synack_retries = 2

修改后执行,sysctl -p,生效。

Nginx安全加固

1. 隐藏Nginx版本号

http {
    server_tokens off;
}

2. 禁止访问敏感文件

server {
    # 禁止访问隐藏文件
    location ~ /\. {
        deny all;
    }

    # 禁止访问敏感文件
    location ~* \.(env|log|sh|sql|ini|conf|bak|swp)$ {
        deny all;
    }
}

3. 限制请求方法

server {
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
        return 405;
    }
}

4. 防止盗链

server {
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        valid_referers none blocked www.example.com example.com;
        if ($invalid_referer) {
            return 403;
        }
    }
}

5. 添加安全头

server {
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
}

6. 配置SSL安全

server {
    listen 443 ssl;
    server_name www.example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
}

Nginx常见问题

1. 403 Forbidden

原因:

  • 网站根目录权限不对
  • index文件不存在
  • Nginx用户没有权限访问目录

解决方法:

  • 检查网站根目录权限确保Nginx用户有读权限
  • 检查index文件是否存在
  • 检查Nginx配置root指令是否正确

2. 502 Bad Gateway

原因:

  • 后端服务器(PHP-FPM、Tomcat等),没有启动
  • 后端服务器端口不对
  • 后端服务器崩溃了

解决方法:

  • 检查后端服务器是否启动
  • 检查Nginx配置proxypass或fastcgipass地址和端口是否正确
  • 查看后端服务器日志排查崩溃原因

3. 504 Gateway Timeout

原因:

  • 后端服务器处理请求太慢超时了

解决方法:

  • 优化后端服务器性能
  • 增加Nginx的proxyreadtimeout超时时间

4. 404 Not Found

原因:

  • 请求的文件不存在
  • URL重写配置错误
  • root指令配置错误

解决方法:

  • 检查请求的文件是否存在
  • 检查URL重写配置
  • 检查root指令配置

5. 大文件上传失败

原因:

  • clientmaxbody_size设置太小

解决方法:

  • 增加clientmaxbodysize如clientmaxbodysize 100m;
  • 同时检查PHP的uploadmaxfilesize和postmaxsize配置

学习资源

推荐书籍

  • 《深入理解Nginx》:陶辉写的深入讲解Nginx的内部原理和模块开发非常详细
  • 《Nginx高性能Web服务器详解》:苗泽写的Nginx入门和实战适合初学者
  • 《实战Nginx:取代Apache的高性能Web服务器》:张宴写的Nginx实战比较早但经典

在线教程

  • Nginx官方文档:http://nginx.org/en/docs/ ,最权威、最全面的Nginx文档
  • Nginx中文文档:http://www.nginx.cn/doc/ ,中文的Nginx文档
  • 菜鸟教程Nginx教程:https://www.runoob.com/linux/nginx-install-setup.html
  • 阮一峰的Nginx入门:http://www.ruanyifeng.com/blog/2015/03/nginx.html

工具

  • nginx -t:测试配置文件是否正确
  • nginx -V:查看Nginx版本和编译参数
  • Nginx Amplify:Nginx官方的监控工具
  • GoAccess:实时日志分析工具

写在最后

Nginx是目前世界上最流行、最高性能的Web服务器之一。对于程序员和运维来说Nginx已经成为了必备技能。掌握了Nginx你就能搭建高性能的网站做反向代理和负载均衡优化网站性能加固网站安全。

学习Nginx不要死记硬背配置指令而要理解它的架构和原理。理解了Nginx的事件驱动、异步非阻塞架构理解了master-worker模型理解了配置文件的结构很多配置指令就自然而然地理解了。

另外学习Nginx最好的方式就是多实践。在实际项目中多使用Nginx遇到问题多查文档多尝试慢慢就熟练了。

2015年Nginx已经超过了Apache成为了全球使用量最大的Web服务器。未来Nginx会越来越强大应用场景会越来越广泛。特别是Nginx的微服务、API网关、服务网格等新方向值得关注。

"工欲善其事必先利其器。"希望这篇文章能帮你掌握Nginx这个强大的Web服务器让你的网站更快、更稳、更安全。

最后记住:Nginx只是工具。好的工具能提升效率但真正决定网站性能的还是架构设计和代码本身。 不要为了用Nginx而用Nginx要根据项目的实际需求合理使用。

祝你在Nginx的世界里游刃有余搭建出高性能的网站!