如何查看Nginx的运行状态:nginx_status

如何查看Nginx的运行状态信息?很简单,只要你在编译安装Nginx时添加了ngx_http_stub_status_module模块(一般都有的),然后
在配置文件里添加如下配置(高亮部分):

server {
listen 80;
server_name xxx;
…
location /status
{
stub_status on;
access_log off;
error_log off;
}
…
}

从浏览器中打开:http://www.yourdomain.com/status 可以看到类似以下的内容:

Active connections: 410
server accepts handled requests
30871298 30871298 105864919
Reading: 4 Writing: 8 Waiting: 398

active connections– 对后端发起的活动连接数
server accepts handled requests– nginx 总共处理了 30871298 个连接, 成功创建 30871298 次握手,总共处理了 105864919个请求
reading– nginx 读取到客户端的Header信息数
writing– nginx 返回给客户端的Header信息数
waiting– 开启 keep-alive 的情况下,这个值等于 active – (reading + writing),意思就是Nginx说已经处理完正在等候下一次请求指令的驻留连接
如果reading或writing的值很高,说明正在处理的数据量很大,可能是因为后端的php程序处理慢,拖了后腿,而一般来说,PHP之后以慢,是因为MYSQL,另一个原因很可能就是IO慢,或者客户端的网络慢(这种情况在国内常见些).因为CPU配置低的情况少见.

nginx 出现413 Request Entity Too Large问题的解决方法

nginx 出现413 Request Entity Too Large问题的解决方法

使用php上传图片(大小1.9M),出现 nginx: 413 Request Entity Too Large 错误。

根据经验是服务器限制了上传文件的大小,但php默认的文件上传是2M,应该不会出现问题。

打开php.ini,把 upload_max_filesize 和 post_max_size 修改为20M,然后重启。

再次上传,问题依旧,可以排除php方面的问题。

原来nginx默认上传文件的大小是1M,可nginx的设置中修改。

解决方法如下:

  1. 打开nginx配置文件 nginx.conf, 路径一般是:/etc/nginx/nginx.conf。

  2. 在http{}段中加入 client_max_body_size 20m; 20m为允许最大上传的大小。

  3. 保存后重启nginx,问题解决。

https双向验证-nginx实例

简介

一般的web服务器都是https单向认证,双向认证大部分用于企业对接,信任对方身份。比如该网站的接口不是所有人都可以访问,只允许一个或者部分持有证书的人访问。就需要双向认证

环境准备

ubuntu 16.4
nginx或者OpenResty, 本文用的OpenResty 版本为:openresty-1.11.2.1

创建目录

  1. 修改/etc/ssl/openssl.cnf配置文件(如果不知道openssl配置文件可以查找一下,后者使用locate openssl.cnf命令)
  2. 找到[CA_default]标签
  3. 修改dir对应的工作目录,我的目录为 /home/用户名/ca
  4. cd 到工作目录

生成CA证书

openssl genrsa -aes256 -out private/ca.pem 1024
openssl rsa -in private/ca.pem -out private/ca.key
openssl req -new -key private/ca.pem -out private/ca.csr
openssl x509 -req -days 365 -sha1 -signkey private/ca.pem -in private/ca.csr -out certs/ca.cer

生成服务端证书

用根证书签发server端证书

openssl genrsa -aes256 -out private/server.pem 1024
openssl rsa -in private/server.pem -out private/server.key
openssl req -new -key private/server.pem -out private/server.csr
openssl x509 -req -days 365 -sha1 -CA certs/ca.cer -CAkey private/ca.pem -CAserial ca.srl -in private/server.csr -out certs/server.cer

生成客户端证书

openssl genrsa -aes256 -out private/client.pem 1024
openssl rsa -in private/client.pem -out private/client.key
openssl req -new -key private/client.pem -out private/client.csr
openssl x509 -req -days 365 -sha1 -CA certs/ca.cer -CAkey private/ca.pem -CAserial ca.srl -in private/client.csr -out certs/client.cer

导出证书

openssl pkcs12 -export -clcerts -inkey private/client.pem -in certs/client.cer -out certs/client.p12
openssl pkcs12 -export -clcerts -inkey private/server.pem -in certs/server.cer -out certs/server.p12

安装证书

  1. 安装CA证书,在谷歌浏览器中点击设置->高级选项->证书管理->授权中心,点击导入,然后选择生成的ca.cer证书文件。
  2. 安装客户端证书,在谷歌浏览器中点击设置->高级选项->证书管理->您的证书 点击导入,选择生成的client.p12证书文件

未分类

未分类

需要注意的地方

在生成客户端证书的时候在填写CN的时候不要和生成CA证书和服务端证书一样。测试好多次如果subj和CA,server一样的话浏览器一直是400错误。

配置nginx启动

server {
        listen       443 ssl;
        server_name  www.soaer.com;
        ssl on;
        ssl_certificate      /home/sunny/ca/certs/server.cer;
        ssl_certificate_key  /home/sunny/ca/private/server.key;
        ssl_client_certificate /home/sunny/ca/certs/ca.cer;
        ssl_verify_client on;
        ssl_prefer_server_ciphers on;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;

        location / {
            root   html;
            index  index.html index.htm;
        }
}

测试

浏览器中输入https://www.soaer.com, 如图所示,需要你选择发送给服务端的证书,此时选择client.p12证书文件

未分类

结果(成功)

未分类

使用zabbix监控nginx和php-fpm性能

一、系统环境

1.1 软件及其版本

未分类

1.2 软件安装路径

zabbix安装在/usr/local/zabbix路径下,其相关配置文件及二进制执行程序都放置其中。
nginx安装在/usr/local/nginx下,其相关配置文件及二进制执行程序都放置其中。
php安装在/usr/local/php下,其相关配置文件及二进制执行程序都放置其中。
继续后面的操作前,请确认nginx和php-fpm的服务端口都处于监听状态。

二、配置nginx的status

2.1 确认nginx的status已编译到程序包中

使用nginx -V可以查看nginx是否将模块·http_stub_status_module`编译进包中:

[root@monitor-server2 zabbix_agentd.conf.d]# nginx -V
nginx version: nginx/1.10.3
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) 
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx-1.10.3 
--with-http_ssl_module 
--with-http_stub_status_module --with-pcre   
#出现with-http_stub_status_module说明已装载status模块

2.2 启用nginx的status模块

  • 修改nginx.conf文件

一般在默认主机中增加如下location即可:

location /nginx_status {
  stub_status on;
  access_log off;
  allow 127.0.0.1;
  allow 192.168.249.0/24;
  deny all;
  • 查看nginx status

nginx配置文件修改完成以后,使用nginx -t测试配置文件是否有明显逻辑及语法错误,没有问题则重载配置文件。

nginx -t
nginx -s reload

然后使用浏览器或者curl指令查看nginx status:

[root@monitor-server2 zabbix_agentd.conf.d]# curl localhost/nginx_status
Active connections: 2 
server accepts handled requests
 1585 1585 7785 
Reading: 0 Writing: 1 Waiting: 1 

2.3 nginx status数值的含义说明

未分类

三、配置php-fpm的status

php-fpm自带的有用于查询其工作状态的页面,需要进行如下 两步,以启用这一功能。

3.1 启用php-fpm status页面

修改php-fpm.conf文件,去掉status页面的注释,并可以根据需要将其改名。操作如下:

vim /usr/local/php/etc/php-fpm.conf
pm.status_path = /php_fpm-status      
 #去掉了前面的;注释符,并更名为php_fpm-status

3.2 查看php-fpm的status

修改完php-fpm.conf后,使用service php-fpm reload重新加载配置文件,然后在浏览器或者使用curl指令查看php-fpm的status。操作如下:

[root@monitor-server2 zabbix_agentd.conf.d]# curl localhost/php_fpm-status
pool:                 www
process manager:      dynamic
start time:           01/May/2017:15:14:23 +0800
start since:          29536
accepted conn:        5947
listen queue:         0
max listen queue:     3
listen queue len:     128
idle processes:       2
active processes:     1
total processes:      3
max active processes: 3
max children reached: 0
slow requests:        0

php-fpm的status可以查看汇总信息和详细信息,详细信息比汇总信息要多出每一个php-fpm进程的相关信息,同时支持多种格式输出,如xml、html和json,默认情况下分别使用如果指令即可:

Examples for summary status page:
http://example.com/status
http://example.com/status?json
http://example.com/status?html
http://example.com/status?xml
Example for detailed status page:
http://example.com/status?full
http://example.com/status?json&full
http://example.com/status?html&full
http://example.com/status?xml&full

使用何种格式查看status决定了后续使用zabbix进行监控获取status数值的方式。本文以上述curl localhost/php_fpm-status的输出为例。

3.3 php-fpm status的含义

未分类

四、编写status数据提取脚本

在适当的位置,一般是/usr/local/zabbix/bin里准备脚本用于提取status里每个字段的数值。

4.1 nginx的status数值提取脚本

此脚本为/usr/local/zabbix/bin/nginx_status.sh,其内容如下:

#!/bin/bash
#check nginx status
ip=127.0.0.1
function ping() {                              #用于检测nginx进程是否存在
    /sbin/pidof nginx | wc -l
}

function active() {                 #用于提取status中的active数值
    /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '1p' | awk '{print $NF}'
}

function accepts() {            #用于提取status中的accepts数值
    /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '3p' | awk '{print $1}'
}

function handled() {          #用于提取status中的handled数值
    /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '3p' | awk '{print $2}'
}

function requests() {        #用于提取status中的request数值
    /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '3p' | awk '{print $3}'
}

function reading() {        #用于提取status中的reading数值
    /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '4p' | awk '{print $2}'
}

function writing() {        #用于提取status中的writing数值
    /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '4p' | awk '{print $4}'
}

function waiting() {     #用于提取status中的waiting数值
    /usr/bin/curl http://$ip/nginx_status 2>/dev/null | sed -n '4p' | awk '{print $6}'
}

$1                           #通过第一个位置参数的值来调用相应的函数  

4.2 php-fpm status数值提取脚本

php-fpm status数值提取脚本为/usr/local/zabbix/bin/php_fpm_status.sh,内容如下:

#!/bin/bash
#check php-fpm status
case $1 in
    ping)                           #检测php-fpm进程是否存在
    /sbin/pidof php-fpm | wc -l
    ;;
    start_since)             #提取status中的start since数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==4{print $3}'
    ;;
    conn)                     #提取status中的accepted conn数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==5{print $3}'
    ;;
    listen_queue)         #提取status中的listen queue数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==6{print $3}'
    ;;
     max_listen_queue)  #提取status中的max listen queue数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==7{print $4}'
    ;;
    listen_queue_len)    #提取status中的listen queue len
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==8{print $4}'
    ;;
    idle_processes)      #提取status中的idle processes数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==9{print $3}'
    ;;
    active_processes)   #提取status中的active processes数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==10{print $3}'
    ;;
     total_processes)    #提取status中的total processess数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==11{print $3}'
    ;;
    max_active_processes)     #提取status中的max active processes数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==12{print $4}'
    ;;
     max_children_reached)    #提取status中的max children reached数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==13{print $4}'
    ;;
    slow_requests)   #提取status中的slow requests数值
    /usr/bin/curl localhost/php_fpm-status 2>/dev/null  | awk 'NR==14{print $3}'  
    ;;
    *)
    echo "Usage: $0 {conn|listen_queue|max_listen_queue|listen_queue_len|idle_processes|active_processess|total_processes|max_active_processes|max_children_reached|slow_requests}"
    exit 1
    ;;
esac

五、创建zabbix_agentd的子配置文件

在/usr/local/zabbix/etc/zabbix_agentd.d/中创建关联nginx status和php-fpm status的子配置文件,创建一个,或者在已有的某配置文件中增加也可以,我这里分别为它们创建配置文件,文件名可自定义,只要确保此文件夹全部内容在zabbix_agentd.conf中包含(include)了。

5.1 userparameter_nginx.conf

[root@monitor-server2 zabbix_agentd.conf.d]# cat userparameter_nginx.conf 
#/usr/local/zabbix/bin/nginx_status.sh
UserParameter=nginx.status[*],/usr/local/zabbix/bin/nginx_status.sh $1  
 #这种写法比较简洁,参考zabbix 3.2.4中自带的的userparameter_examples.conf
UserParameter=nginx.version,/usr/local/nginx/sbin/nginx -v     
#让zabbix-agentd获取nginx的版本信息 ,一切shell指令都推荐使用绝对路径 

5.2 userparameter_php-fpm.conf

[root@monitor-server2 zabbix_agentd.conf.d]# cat userparameter_php-fpm.conf 
#/usr/local/zabbix/bin/php_fpm_status.sh
UserParameter=php-fpm.status[*],/usr/local/zabbix/bin/php_fpm_status.sh $1
UserParameter=php-fpm.version,/usr/local/php/sbin/php-fpm -v | awk 'NR==1{print $0}'   
#获取php-fpm版本信息

5.3 确认子配置文件被zabbix_agentd配置文件包含

确认在/usr/local/zabbix/etc/zabbix_agentd.conf中包含:Include=/usr/local/zabbix/etc/zabbix_agentd.conf.d/且没有被注释。

六、重启zabbix_agentd服务

service zabbix_agentd restart 让zabbix_agentd加载新的配置文件。

七、测试zabbix_get能否取到数据

在zabbix server上使用如下指令测试能否获取到nginx和php-fpm status数值。

[root@monitor-server2 zabbix_agentd.conf.d]# zabbix_get -s 127.0.0.1 -k 'nginx.status[ping]'      
1
[root@monitor-server2 zabbix_agentd.conf.d]# zabbix_get -s 127.0.0.1 -k 'nginx.status[active]'
6
[root@monitor-server2 zabbix_agentd.conf.d]# zabbix_get -s 127.0.0.1 -k 'nginx.status[requests]'  
1841
[root@monitor-server2 zabbix_agentd.conf.d]# zabbix_get -s 127.0.0.1 -k 'php-fpm.status[ping]' 
1
[root@monitor-server2 zabbix_agentd.conf.d]# zabbix_get -s 127.0.0.1 -k 'php-fpm.status[conn]'
1247

注意:

  • zabbix_get指令在zabbix server上运行。
  • userparameter_*.conf文件位于zabbix_agentd端。
  • nginx_status.sh和php_fpm_status.sh位于zabbix_agentd端。
  • zabbix-get后-s指定的ip为zabbix-agentd的监听ip。

八、zabbix server上配置相应的模板

这里的模板包含对nginx status和php-fpm status要监控的item、trigger、Graphs等一系列内容。对于在zabbix server上新增要监控的内容,最好的办法就是从模板开始,然后按照顺序依次配置相应内容,无需去网上找现成的模板导入,对于系统的监控按需配置是最好的。下面是相应的操作过程。

8.1 添加nginx status监控模板

未分类

新建nginx status模板

未分类

定义nginx status模板

未分类

新建nginxApplication

未分类

定义nginx status items,这里我使用的是被动临控

未分类

增加nginx status状态码映射

未分类

nginx trigger定义

未分类

定义nginx监控视图

8.2 添加php-fpm status监控模板

php-fpm status的模板添加步骤和上述方法一样,此处不在赘述。

8.3 选择相应的主机或主机组关联上相应的模板

未分类

给主机或主机组关联模板

九、实际监控效果展示

查看监控效果可以通过查看Monitoring—->Latest data,过滤出相应的主机及应用名进行查看,最新收集的各item的监控结果,凡是监控到数据的item会显示数据,出现灰色的表示没有监控到数据,需要排查原因。如下所示:

未分类

nginx的监控数据

也可以通过定义的Graphs查看监控效果:

未分类

nginx statur监控视图

十、小结

zabbix中要实现对用户自定义的item的监控,大致过程如下:

  • 启用相应软件的性能统计功能
  • 编写性能统计数据提取脚本
  • 配置自定义的userparameter conf文件
  • 重启zabbix_agentd服务
  • zabbix server web上添加相应的模板
  • 给主机或主机组调用模板

Nginx 启用 Brotli 压缩

Brotli 是 Google 开发的一种压缩格式,它通过内置分析大量网页得出的字典,实现了更高的压缩比率,同时几乎不影响压缩 / 解压速度。

本站通过 ngx_brotli 模块来让 Nginx 支持 Brotli 压缩方式。本文介绍其配置方式。

安装模块

若要启用 ngx_brotli 模块,需要在编译 Nginx 时,加入相应模块:

# get source

git clone https://github.com/google/ngx_brotli.git

cd ngx_brotli

git submodule update --init

cd ..

# configure

./configure ... --add-module=../ngx_brotli

配置文件

安装完成 ngx_brotli 模块后,你就可以在配置文件里启用它了:

# 配置段: http, server, location

# 开启 ngx_brotli 压缩

brotli on;

# 指定压缩数据的最小长度,只有大于或等于最小长度才会对其压缩。这里指定 20 字节

brotli_min_length 20;

# Brotli 请求缓冲区的数量和大小

brotli_buffers 16 10k;

# Brotli 使用的窗口值。默认值为 512k

brotli_window 512k;

# 压缩水平可以是 0 到 11,默认值是 6。太高的压缩水平对性能提升并没有太大好处,因为这需要更多的 CPU 时间

brotli_comp_level 6;

# 指定允许进行压缩的回复类型

brotli_types text/html text/xml text/plain application/json text/css image/svg application/font-woff application/vnd.ms-fontobject application/vnd.apple.mpegurl application/javascript image/x-icon image/jpeg image/gif image/png;

# 是否允许查找预处理好的、以 .br 结尾的压缩文件。可选值为 on、off、always

brotli_static always;

未分类

Nginx+SSL+Tomcat+CDN部署总结

之前在度娘搜索资料,无意间看到一些个人站点的博客都用了https协议,在浏览器地址栏中被标记为绿色的“安全”,前些天特地给自己负责的小项目升级成https协议,其优点这里不再赘述,小伙伴们可以自行百度,今天把整合部署分享在这里,希望小伙伴们少走弯路~

效果如下:

未分类

软件版本如下:

未分类

一、生成SSL证书

首先我们创建一个用来存放letsencrypt生成证书项目的路径并进入:

cd /usr/local/letsencrypt

接下来我们克隆letsencrypt项目:

git clone https://github.com/letsencrypt/letsencrypt

开始生成SSL证书:

./letsencrypt-auto certonly --standalone --email [email protected] -d www.test1.com -d www.test2.com --agree-tos

这里一定注意:

(1). 域名绑定在国内DNS服务器无法生成,需要先将DNS服务器切换到DNS服务商,例如ClouldFlare、Godaddy、Dnsever后才能正常生成!
(2). web服务需要处于关闭状态,注意关闭nginx和80端口的占用!(不间断服务方式生成可以自行百度)
(3). -d 代表domain 可以同时生成多个域名对应证书,生成后我们可以在默认目录中看到:

/etc/letsencrypt/live/www.test.com/
cert.pem(用户证书) 
chain.pem(中间证书) 
fullchain.pem(证书链) 
privkey.pem(证书私钥)

最后我们生成Perfect Forward Security(PFS)键值,具体作用可以自行百度:

mkdir /etc/ssl/private/ -p
cd /etc/ssl/private/
openssl dhparam 2048 -out dhparam.pem

二、Nginx配置SSL证书及Tomcat代理

    #Tomcat 8080端口
    upstream tomcat_8080{
        server    127.0.0.1:8080  weight=1;
    }

    #将所有http协议内容重定向到https协议
    server {
        listen 80;
        server_name www.test.com;
        rewrite ^ https://$server_name$request_uri? permanent;
    }

    #https协议
    server {
        listen 443;
        server_name www.test.com;

        # letsencrypt生成的文件
        ssl on;
        ssl_certificate /etc/letsencrypt/live/www.test.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.test.com/privkey.pem;

        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_session_tickets on;

        ssl_dhparam /etc/ssl/private/dhparam.pem;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        # 一般推荐使用的ssl_ciphers值: https://wiki.mozilla.org/Security/Server_Side_TLS
        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK';
        ssl_prefer_server_ciphers on;

        # 代理tomcat
        location / {   
            proxy_set_header    Host                $http_host;             
            proxy_set_header    X-Real-IP           $remote_addr;     
            proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;     
            proxy_set_header    Cookie              $http_cookie;
            proxy_pass          http://tomcat_8080;
            #proxy_redirect     default;
        }

        access_log /home/wwwlogs/www.test.com_access.log;
        error_log  /home/wwwlogs/www.test.com_error.log;
    }

三、Tomcat的SSL配置

1、Connector节点将redirectPort=”8443″修改为 redirectPort=”443″ proxyPort=”443″最终为:

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="443" proxyPort="443" />

2、找到Engine节点,在最后一个Host标签后加入:

<Host name="www.test.com" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
    <Valve className="org.apache.catalina.valves.RemoteIpValve"
        remoteIpHeader="x-forwarded-for"
        remoteIpProxiesHeader="x-forwarded-by"
        protocolHeader="x-forwarded-proto"/>
    <Context docBase="/www/java/projectName" path="" crossContext="true" debug="3" privileged="true"  reloadable="false" deubt="true" />
</Host>

四、CloudFlare CDN设置(这里很重要)

我们将域名解析到自己服务器后,点击Crypto选项卡,将SSL状态修改为Full(strict)模式,在这种模式下会使用你服务器中的ssl证书,否则会导致页面无限301跳转,导致chrome提示重定向次数过多,请求失败!

php nginx 实时输出

PHP 里开启实时输出方法是ob_implicit_flush(),
但它大部分情况下都不管用,

因为php.ini配置里output_buffering输出缓冲大部分是On开启的,
还有zlib.output_compression也经常会被开启,

除了 PHP 这一层,还有 Nginx 的缓冲设置proxy_buffering,和压缩gzip也大都是开启的。
为了一两个页面的需求,修改整个服务器的网站配置,恐怕没有人会做这种选择。

这里推荐一下简单的方法:

set_time_limit(0);
ob_end_clean();
ob_implicit_flush();

header('X-Accel-Buffering: no'); // 关键是加了这一行。

echo '现在是:'.date('H:i:s').'<br>';
sleep(5);
echo '五秒后:'.date('H:i:s');

使用 Nginx 过滤网络爬虫

现在有许多初学者学习网络爬虫,但他们不懂得控制速度,导致服务器资源浪费。通过 Nginx 的简单配置,能过滤一小部分这类爬虫。

方法一:通过 User-Agent 过滤

Nginx 参考配置如下:

    location / {
        if ($http_user_agent ~* "scrapy|python|curl|java|wget|httpclient|okhttp") {
            return 503;
        }
        # 正常请求
    }

这里只列出了部分爬虫的 User-Agent,需要更多请参考:GitHub – JayBizzle/Crawler-Detect

注意:User-Agent 很容易修改

方法二:block IP

通过禁止某个 IP 或者某个 IP 段访问,也能起到一定效果。 Nginx 示例配置如下:

deny 178.238.234.1;
deny 1.32.128.0/18;

方法三:rate limit

通过限制某个 IP 的访问频率,避免一部分 CC (Challenge Collapsar)攻击。

Nginx 示例配置如下:

http{ 
    #定义一个名为allips的limit_req_zone用来存储session,大小是10M内存,
    #以$binary_remote_addr 为key,限制平均每秒的请求为20个,
    #1M能存储16000个状态,rete的值必须为整数,
    #如果限制两秒钟一个请求,可以设置成30r/m
    limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
    ...
    server{
        ...
        location {
            ...
            #限制每ip每秒不超过20个请求,漏桶数burst为5
            #brust的意思就是,如果第1秒、2,3,4秒请求为19个,
            #第5秒的请求为25个是被允许的。
            #但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。
            #nodelay,如果不设置该选项,严格使用平均速率限制请求数,
            #第1秒25个请求时,5个请求放到第2秒执行,
            #设置nodelay,25个请求将在第1秒执行。

            limit_req zone=allips burst=5 nodelay;
            ...
        }
        ...
    }
    ...
}

当然,攻击者也可以使用代理IP来破除频率限制。建议在网站前面加一层 CDN。

使用systemctl设置Nginx、PHP、Mysql开机启动

CentOS 7继承了RHEL 7的新的特性,例如强大的systemctl,而systemctl的使用也使得以往系统服务的/etc/init.d的启动脚本的方式就此改变,也大幅提高了系统服务的运行效率。但服务的配置和以往也发生了极大的不同,说实在的,变的简单而易用了许多。

CentOS 7的服务systemctl脚本存放在:/usr/lib/systemd/,有系统(system)和用户(user)之分,像需要开机不登陆就能运行的程序,最好还是存在系统服务里面,即:/usr/lib/systemd/system目录下,每一个服务以.service结尾,一般会分为3部分:[Unit]、[Service]和[Install]

我们可以使用systemctl -a来查看所有服务,如果列表里面没有Nginx,PHP、Mysql,又想借助于systemctl来进行统一管理的话,就到上述所说的/usr/lib/systemd/system目录下面创建以下文件吧

Nginx之nginx.service文件[自定义]

[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target

PHP之php.service文件[自定义]

[Unit]
Description=php
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/php/sbin/php-fpm
ExecStop=/bin/pkill -9 php-fpm
PrivateTmp=true
[Install]
WantedBy=multi-user.target

Mysql之mysqld.service文件[安装的时候软件自动生成]

[Unit]
Description=MySQL Community Server
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
Alias=mysql.service
[Service]
User=mysql
Group=mysql
#systemctl status就是根据pid来判断服务的运行状态的
PIDFile=/var/run/mysqld/mysqld.pid
# 以root权限来启动程序
PermissionsStartOnly=true
# 设置程序启动前的必要操作。例如初始化相关目录等等
ExecStartPre=/usr/bin/mysql-systemd-start pre
# 启动服务
ExecStart=/usr/bin/mysqld_safe
# Don't signal startup success before a ping works
ExecStartPost=/usr/bin/mysql-systemd-start post
# Give up if ping don't get an answer
TimeoutSec=600
#Restart配置可以在进程被kill掉之后,让systemctl产生新的进程,避免服务挂掉
Restart=always
PrivateTmp=false

上述文件创建完成后,只要使用systemctl enable 命令就可以将所编写的服务添加至开机启动了。例如:

#将php服务添加至开机启动。执行enable命令后,会自动创建一个软链接/etc/systemd/system/multi-user.target.wants/php.service指向此文件。
systemctl enable php.service
#查看php是否已设置为开机启动
systemctl is-enabled php.service

注意

[Unit]部分主要是对这个服务的说明,内容包括Description和After,Description用于描述服务,After用于描述服务类别

[Service]部分是服务的关键,是服务的一些具体运行参数的设置,这里 Type=forking是后台运行的形式,PIDFile为存放PID的文件路径,
ExecStart为服务的具体运行命令,ExecReload为重启命令,ExecStop为停止命令,PrivateTmp=True表示给服务分配独立的临时空间。[Service]部分的启动、重启、停止命令全部要求使用绝对路径,使用相对路径则会报错!

[Install]部分是服务安装的相关设置,可设置为多用户的

服务脚本按照上面编写完成后,以754的权限保存在/usr/lib/systemd/system目录下,这时就可以利用systemctl进行配置了

使用systemctl start [服务名(也是文件名)]可以测试服务是否可以成功运行,如果不能运行则可以使用systemctl status [服务名(也是文件名)]查看错误信息和其他服务信息。然后根据报错进行修改,直到可以start,如果不放心还可以测试restart和stop命令。

Nginx支持HTTPS并且支持反爬虫

自己写了若干爬虫, 但是自己的网站也有人爬, 呵呵, 这里介绍一种Nginx反爬.我在阿里云只开放80端口, 所有一般端口都通过Nginx进行反向代理. 通过Nginx, 我们还可以拦截大部分爬虫.

然后我们再给自己的网站加上HTTPS支持.

Nginx安装

我的系统如下:

jinhan@jinhan-chen-110:~/book/Obiwan/bin$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.3 LTS
Release:    16.04
Codename:   xenial

安装(如果有apache服务器, 建议卸载了, 或者改Nginx的默认端口):

sudo apt-get install nginx

此时已经开启了80端口, 并且配置处在etc/nginx

lsof -i:80

cd /etc/nginx

Nginx服务一般配置

将配置放于conf.d/*

PHP配置(可忽视)

server{
    listen 80;
    server_name php.lenggirl.com;
    charset utf-8;
    access_log /data/logs/nginx/www.lenggirl.com.log;
    #error_log /data/logs/nginx/www.lenggirl.com.err;

    location / {
            root   /data/www/php/blog;
        index index.html index.php;
        #访问路径的文件不存在则重写URL转交给ThinkPHP处理
        if (!-e $request_filename) {
            rewrite  ^/(.*)$  /index.php/$1  last;
            break;
        }
    }

    ## Images and static content is treated different
    location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {

        access_log        off;
        expires           30d;
        root /data/www/php/blog;
     }

    location ~.php/?.*$ {
    root        /data/www/php/blog;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        #加载Nginx默认"服务器环境变量"配置
        include        fastcgi.conf;

        #设置PATH_INFO并改写SCRIPT_FILENAME,SCRIPT_NAME服务器环境变量
        set $fastcgi_script_name2 $fastcgi_script_name;
        if ($fastcgi_script_name ~ "^(.+.php)(/.+)$") {
            set $fastcgi_script_name2 $1;
            set $path_info $2;
        }
        fastcgi_param   PATH_INFO $path_info;
        fastcgi_param   SCRIPT_FILENAME   $document_root$fastcgi_script_name2;
        fastcgi_param   SCRIPT_NAME   $fastcgi_script_name2;        
    }
}

Go配置

通过server_name, 用域名访问, 全部会到80端口, 根据域名会转发到8080

域名请A记录到该机器IP地址.

vim /etc/nginx/conf.d/www.lenggirl.com.conf

server{
    listen 80;
    # 本地测试时可以将域名改为: 127.0.0.1
    server_name www.lenggirl.com;
    charset utf-8;
    access_log /root/logs/nginx/www.lenggirl.com.log;
    #error_log /data/logs/nginx/www.lenggirl.com.err;
    location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://localhost:8080;

    # 这个就是反爬虫文件了
    include /etc/nginx/anti_spider.conf;
    }   
}

日志文件要先建立:

sudo mkdir -p /root/logs/nginx

查看配置是否无误, 并重启:

sudo nginx -t
sudo service nginx restart
sudo nginx -s reload

访问127.0.0.1会发现502错误, 因为8080端口我们没开! 此时访问localhost会发现, 这时Nginx欢迎页面出来了, 这是默认80端口页面!

反爬虫配置

增加反爬虫配额文件:

sudo vim /etc/nginx/anti_spider.conf

#禁止Scrapy等工具的抓取  
if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) {  
     return 403;  
}  

#禁止指定UA及UA为空的访问  
if ($http_user_agent ~ "WinHttp|WebZIP|FetchURL|node-superagent|java/|FeedDemon|Jullo|JikeSpider|Indy Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|Java|Feedly|Apache-HttpAsyncClient|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|BOT/0.1|YandexBot|FlightDeckReports|Linguee Bot|^$" ) {  
     return 403;               
}  

#禁止非GET|HEAD|POST方式的抓取  
if ($request_method !~ ^(GET|HEAD|POST)$) {  
    return 403;  
}  

#屏蔽单个IP的命令是
#deny 123.45.6.7
#封整个段即从123.0.0.1到123.255.255.254的命令
#deny 123.0.0.0/8
#封IP段即从123.45.0.1到123.45.255.254的命令
#deny 124.45.0.0/16
#封IP段即从123.45.6.1到123.45.6.254的命令是
#deny 123.45.6.0/24

# 以下IP皆为流氓
deny 58.95.66.0/24;

在网站配置server段中都插入include /etc/nginx/anti_spider.conf, 见上文. 你可以在默认的80端口配置上加上此句:sudo vim sites-available/default

重启:

sudo nginx -s reload

爬虫UA常见:

FeedDemon             内容采集  
BOT/0.1 (BOT for JCE) sql注入  
CrawlDaddy            sql注入  
Java                  内容采集  
Jullo                 内容采集  
Feedly                内容采集  
UniversalFeedParser   内容采集  
ApacheBench           cc攻击器  
Swiftbot              无用爬虫  
YandexBot             无用爬虫  
AhrefsBot             无用爬虫  
YisouSpider           无用爬虫(已被UC神马搜索收购,此蜘蛛可以放开!)  
jikeSpider            无用爬虫  
MJ12bot               无用爬虫  
ZmEu phpmyadmin       漏洞扫描  
WinHttp               采集cc攻击  
EasouSpider           无用爬虫  
HttpClient            tcp攻击  
Microsoft URL Control 扫描  
YYSpider              无用爬虫  
jaunty                wordpress爆破扫描器  
oBot                  无用爬虫  
Python-urllib         内容采集  
Indy Library          扫描  
FlightDeckReports Bot 无用爬虫  
Linguee Bot           无用爬虫  

使用curl -A 模拟抓取即可,比如:

# -A表示User-Agent
# -X表示方法: POST/GET
# -I表示只显示响应头部
curl -X GET -I -A 'YYSpider' localhost

HTTP/1.1 403 Forbidden
Server: nginx/1.10.3 (Ubuntu)
Date: Fri, 08 Dec 2017 10:07:15 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive

模拟UA为空的抓取:

curl -I -A ' ' localhost

模拟百度蜘蛛的抓取:

curl -I -A 'Baiduspider' localhost

支持https

见: https://certbot.eff.org/#ubuntuxenial-other

首先执行:

apt-get update
apt-get install software-properties-common
add-apt-repository ppa:certbot/certbot
apt-get update
apt-get install python-certbot-nginx 

然后执行这个按说明操作:

certbot --authenticator standalone --installer nginx --pre-hook "nginx -s stop" --post-hook "nginx"

之前/etc/nginx/conf.d/www.lenggirl.com.conf文件变更如下:

server{
        listen 80;
        # 本地测试时可以将域名改为: 127.0.0.1
        server_name www.lenggirl.com;
        charset utf-8;
        access_log /root/logs/nginx/www.lenggirl.com.log;
        #error_log /data/logs/nginx/www.lenggirl.com.err;
        location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://localhost:4000;

        # 这个就是反爬虫文件了
        # include /etc/nginx/anti_spider.conf;
        #
}

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/www.lenggirl.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/www.lenggirl.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    } # managed by Certbot

}