Nginx

基础

CentOS7中使用yum安装Nginx的方法

1、添加源

  默认情况Centos7中无Nginx的源,最近发现Nginx官网提供了Centos的源地址。因此可以如下执行命令添加源:

1
sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

2、安装Nginx

  通过yum search nginx看看是否已经添加源成功。如果成功则执行下列命令安装Nginx。

1
sudo yum install -y nginx

3、启动Nginx并设置开机自动运行

1
2
sudo systemctl start nginx.service
sudo systemctl enable nginx.service

4、浏览查看效果

在浏览器中输入您的服务器地址

nginx 安装

  1. 下载nginx

    wget http://nginx.org/download/nginx-1.10.1.tar.gz
    
  2. 进行解压

    tar -zxvf nginx-1.10.1.tar.gz
    
  3. 安装nginx必须的相关包

    yum install -y pcre-devel openssl-devel
    yum install gcc-c++
    
  4. 配置nginx安装环境

    cd nginx-1.10.1
    ./configure --with-http_stub_status_module --with-http_ssl_module
    
  5. 安装nginx

    make && make install
    
  6. 启动:

    /usr/local/nginx/sbin/nginx
    
  7. 关闭:

    /usr/local/nginx/sbin/nginx  -s stop
    
  8. 重启 nginx 服务:

    /usr/local/nginx/sbin/nginx -s reload
    
  9. 配置nginx负载均衡

    修改/usr/local/nginx/conf/nginx.conf

微程序缓存

  1. 简介

    NGINX 和 NGINX Plus 被广泛应用于网站内容缓存,微程序缓存通过将动态、非个人化的内容缓存很短的时间,能有效加速这些内容的传递。

    适合缓存的动态内容包括:

  • 经常更新的新闻或博客网站的首页,每隔几秒就有新文章发布
  • 最近资讯 RSS
  • 持续整合(CI)或搭建平台的进度页面
  • 库存、进度或筹款计数
  • 彩票开奖结果
  • 日历数据
  • 在客户端呈现的个人化动态内容,例如利用 cookie 数据展示的广告内容或数据(“你好,你的名字”)

    动态内容的微程序缓存

    微程序缓存是一种缓存技术,将内容缓存1秒左右很短的时间。这意味着网站更新会延迟不到1秒钟,这在很多情况下是可以接受的。
    
  1. 利用 NGINX 来加速服务

    第一步: 通过 NGINX 代理服务器

    第二步: 启动短期缓存

    在服务器配置中只添加了两条指令,NGINX 或 NGINX Plus 就可以缓存所有可缓存的响应。带有 200 OK 状态码的响应只缓存1秒钟

    proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;
    server {
        proxy_cache cache;
        proxy_cache_valid 200 1s;
        ...
    }
    

    从每秒钟处理5条请求到600条

    需要在确保缓存内容最新的情况下,尽可能少地向上游源服务器转发请求。在缓存内容不断更新的前提下,笔者愿意从缓存获取旧的(延后1到2秒)响应。要实现这一目标,需要添加两条指令:

    proxy_cache_lock ——限制填充缓存的并发尝试数量,这样当一条缓存入口被创建后,对该资源的请求将会在 NGINX 中排队。
    proxy_cache_use_stale ——配置 NGINX,使它提供旧的(最近缓存的)内容,同时更新缓存入口。
    

    加上之前已经添加的缓存指令,笔者得到如下服务器配置:

    server {
        proxy_cache one;
        proxy_cache_lock on;
        proxy_cache_valid 200 1s;
        proxy_cache_use_stale updating;
        ...
    }
    

    每秒钟的请求数量从600跳跃到接近2200

    了解更多信息,请查阅以下资源:

    利用 NGINX 缓存指南——概述和方法介绍
    内容缓存——NGINX Plus 向导
    利用 NGINX Plus 进行内容缓存— NGINX Plus 功能描述
    

实战

http 强转https

  1. rewrite

    因为rewrite 需要使用正则去匹配,本来https就会有相对http有一些性能上的消耗,在增加更多的正则,会造成更多的性能消耗。

    server {
    
        listen 80;
    
        #统配拦截所有域名
    
        server_name *.toutiao.com;
    
        #判断端口是80然后做重定向
    
        if ($server_port = "80"){
    
            rewrite ^(.*)$ https://$host$1 permanent;
        }
    }
    
  2. return

    推荐使用return,return就是告诉你到此结束,语义明确 。

    server {
    
        listen 80;
    
        #统配拦截所有域名
    
        server_name *.toutiao.com;
    
        #判断端口是80然后做重定向
    
        if ($server_port = "80"){
    
            #301 是永久重定向,相当于permanent
    
            return 301 https://$server_name$request_uri;
    
        }
    
    }
    
  3. Nginx SSL+tomcat集群配置需要注意

https://www.toutiao.com/i6366765491389727234/

  • 配置 Nginx 的转发选项:
1
2
3
4
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;
  • 配置Tomcat server.xml 的 Engine 模块下配置一个 Valve:
1
2
3
4
<Valve className="org.apache.catalina.valves.RemoteIpValve"
remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto"
protocolHeaderHttpsValue="https"/>

配置双方的 X-Forwarded-Proto 就是为了正确地识别实际用户发出的协议是 http 还是 https。

按天切割访问日志并删除超过一个月的日志

https://www.toutiao.com/i6375731838341612034/

  1. 日志位置

    /data/logs/nginx

    下面存放多个站点的访问日志,切割后的日志放在/data/logs/nginx/backup目录下面,某个站点单独一个目录,每个目录下面记录最近30天的访问日志

  2. 日志命名规则

    站点域名:www.timophp.com

    日志名称:www.timophp.com.access.log

    站点域名:s1.static.timophp.com

    日志名称:s1.static.timophp.access.log

    备份日志名称

    /data/logs/nginx/backup/www.timophp.com/access.20170117.log

  3. 日志切割脚本

    nginx_access_log_cut.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#初始化
LOGS_PATH="/data/log/nginx"
PID_FILE="/usr/local/nginx/logs/nginx.pid"
YESTERDAY=$(date -d "yesterday" +%Y%m%d)

#日志分割,按天分类
LOGS=`ls ${LOGS_PATH}/*.access.log | xargs -n 1 | cut -f 5 -d "/" | cut -f 1 -d "."`
for LOG in $LOGS
do
mkdir -p ${LOGS_PATH}/backup/${LOG}
mv ${LOGS_PATH}/${LOG}.access.log ${LOGS_PATH}/backup/${LOG}/access.${YESTERDAY}.log
done

kill -USR1 `cat ${PID_FILE}`

#删除30天前的日志
LOG_BACK_DIRS=`ls ${LOGS_PATH}/backup/ | xargs -n 1`
for LOG_DIR in $LOG_BACK_DIRS
do
find ${LOGS_PATH}/backup/${LOG_DIR}/ -name "access*" -mtime +30 | xargs rm -f
done
  1. 日志切割脚本位置

    这个随意,我就把他放在/data/script下面

  2. 增加定时任务crontab

1
0 0 * * */data/script/nginx_access_log_cut.sh > /dev/null2>&1

使用Nginx搭建视频直播服务器

==亲验,可行!==

https://www.toutiao.com/i6315159435152982530/?group_id=6316744795554595073&group_flags=0

  1. 下载RTMP模块

官网地址:https://github.com/arut/nginx-rtmp-module

我们直接输入如下命令

    wget https://github.com/arut/nginx-rtmp-module/archive/master.zip

    unzip master.zip
  1. 下载安装nginx
1
2
3
4
5
6
wget http://nginx.org/download/nginx-1.13.8.tar.gz
tar -zxvf nginx-1.13.8.tar.gz
cd nginx-1.13.8
./configure --prefix=/usr/nginx-1.13.8 --with-http_ssl_module --add-module=../nginx-rtmp-module-master
make
make install
  1. 配置rtmp流
1
2
3
cd /usr/nginx-1.13.8/

vi /conf/nginx.conf
增加如下的代码,详细的配置可以看rtmp模块的github这里,我这里只是简单创建一个直播的应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
rtmp {

server {

listen 1935;

application live {

live on;

}

}

}
重启nginx

    /usr/nginx-1.13.8/sbin/nginx
  1. 推流与拉流

    直播分为推流和拉流,推流就是将视频流发往直播服务器端,而拉流就是将视频流获取到播放器。

  • 比较常见的推流软件OBS,可以在官方网站下载:https://obsproject.com/

    可以设置自己服务器的地址

    rtmp://192.168.1.100/live
    

    点击开始串流就可以进行推流了

  • 拉流数据可以使用VLC播放器

    http://vlc-media-player.en.softonic.com/

    设置自己服务器的地址

    rtmp://192.168.1.100/live
    

    输入后点击播放就可以了

  1. 应用
  • Android使用ijkplayer+nginx进行视频直播

https://www.toutiao.com/i6317047669256618498/

  • ios使用ijkplayer+nginx进行视频直播

https://www.toutiao.com/i6317447470469087745/

性能优化与压力测试

  1. conf配置
1
worker_processes auto;
worker_processes 定义了nginx对外提供web服务时的worker进程数。最优值取决于许多因素,包括(但不限于)CPU核的数量、存储 数据的硬盘数量及负载模式。不能确定的时候,将其设置为可用的CPU内核数将是一个好的开始(设置为“auto”将尝试自动检测它)
1
worker_rlimit_nofile 100000;

==worker_rlimit_nofile 更改worker进程的最大打开文件数限制。如果没设置的话,这个值为操作系统的限制。设置后你的操作系统和 Nginx可以处理比“ulimit -a”更多的文件,所以把这个值设高,这样nginx就不会有“too many open files”问题了。==

  1. Events模块

    events模块中包含nginx中所有处理连接的设置。

1
2
3
4
5
6
7
8
events {
worker_connections 2048;

multi_accept on;

use epoll;

}
worker_connections 设置可由一个worker进程同时打开的最大连接数。如果设置了上面提到的worker_rlimit_nofile,我们可以将这个值 设得很高。 记住,最大客户数也由系统的可用socket连接数限制(~ 64K),所以设置不切实际的高没什么好处。

multi_accept 告诉nginx收到一个新连接通知后接受尽可能多的连接。 u

se 设置用于复用客户端线程的轮询方法。如果你使用Linux 2.6+,你应该使用epoll。如果你使用*BSD,你应该使用kqueue。 (值得注意的是如果你不知道Nginx该使用哪种轮询方法的话,它会选择一个最适合你操作系统的)
  1. 压力测试
  • 并发200时
1
webbench -c 200 -t 60 http://www.loudsay.com/index.php
参数解释:-c为并发数,-t为时间(秒)

    Speed=1454 pages/min, 2153340 bytes/sec.
    Requests: 1454 susceed, 0 failed.
    当并发200时,网站访问速度正常
  • 并发800时

    Speed=1194 pages/min, 2057881 bytes/sec.
    
    Requests: 1185 susceed, 9 failed.
    
    当并发连接为800时,网站访问速度稍慢
    
  • 并发1600时

    Speed=1256 pages/min, 1983506 bytes/sec.
    
    Requests: 1183 susceed, 73 failed.
    
    当并发连接为1600时,网站访问速度便非常慢了
    
  • 并发2000时

    Speed=2154 pages/min, 1968292 bytes/sec.
    
    Requests: 2076 susceed, 78 failed.
    
    当并发2000时,网站便出现“502 Bad Gateway”,由此可见web服务器已无法再处理用户访问请求
    

./configure –prefix=/usr/nginx-1.13.8 –with-http_ssl_module –add-module=../nginx-rtmp-module-master

Nginx反向代理Websocket

  1. 基础

WebSocket握手是通过HTTP来完成的

NGINX通过允许一个在客户端和后端服务器之间建立的隧道来支持WebSocket。为了NGINX发送来至于客户端Upgrade请求到后端服务器,Upgrade和Connection头部必须被设置明确。

  1. 配置

实测可行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
upstream wsbackend {
hash $remote_addr consistent; # 可以根据客户端ip映射,防止断线重连后,连接到其他服务器了
server 127.0.0.1:8081 weight=1;
server 127.0.0.1:8082 weight=1;
server 127.0.0.1:8083 weight=1;
}

#include /etc/nginx/conf.d/*.conf;

server {
listen 8080;
server_name localhost 192.168.1.238;

location / {
proxy_pass http://wsbackend;
proxy_set_header Host $host:$server_port;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

Nginx根据浏览器类型切换手机版和桌面版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
server_name xxxx.net;
access_log /data/log/h5access.log;
server_tokens off;
location / {
if ($http_user_agent ~* (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)) {
root /data/h5/web-mobile; # 手机版
}
if ($http_user_agent !~* (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)) {
root /data/h5/web-desktop; # 桌面版
}
}
}

强转https跳转内部非https

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 443 ssl;
server_name xxxx.net;
ssl_certificate /data/ssl/214972844030649.pem;
ssl_certificate_key /data/ssl/214972844030649.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
#禁止在header中出现服务器版本,防止黑客利用版本漏洞攻击
server_tokens off;
#如果是全站 HTTPS 并且不考虑 HTTP 的话,可以加入 HSTS 告诉你的浏览器本网站全站加密,并且强制用 HTTPS 访问
fastcgi_param HTTPS on;
fastcgi_param HTTP_SCHEME https;
access_log /data/log/httpsaccess.log;

location / {
proxy_pass http://xxxx.net:7000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect http:// $scheme://; #做https跳转
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

问题汇总

Post请求静态页面报错 405 Method not allowed

  1. 新浪微博轻应用开发时,会通过post请求设置的静态页面

  2. 有两种解决方法

    a 重定向 405 错误码到 200

    location ~ ^/(js/sandbox|uploads/rs|img)/ {
        root /data/runjs/webapp;
        error_page 405 =200 $uri;
    }
    

    b 修改 Nginx 源码

    修改文件 /www/nginx-1.10.1/src/http/modules/ngx_http_static_module.c
    
    找到如下行(大约在文件的第206行):
    
    if (r->method & NGX_HTTP_POST) {
         return NGX_HTTP_NOT_ALLOWED;
    }
    
    将这段屏蔽掉;
    /*
    if (r->method & NGX_HTTP_POST) {
         return NGX_HTTP_NOT_ALLOWED;
    }
    */
    
    保存推出;
    
    cd /www/nginx-1.10.1/
    
    然后重新编译 make ,不要 make install
    
    然后把编译生成的 nginx 文件复制到 sbin 下替换原有 nginx 文件
    cp objs/nginx /usr/local/nginx/sbin/
    
    停止 nginx
    
    /usr/local/nginx/sbin/nginx  -s stop
    
    启动 nginx
    
    /usr/local/nginx/sbin/nginx
    

Starting nginx: nginx: [emerg] bind() to 0.0.0.0:8091 failed (13: Permission denied)

开启selinux 导致的。

1、临时关闭selinux

setenforce 0 ##设置SELinux 成为permissive模式
setenforce 1 ##设置SELinux 成为enforcing模式

2、永久关闭selinux,

修改/etc/selinux/config 文件
将SELINUX=enforcing改为SELINUX=disabled
重启机器即可

a