Nginx配置、优化

一、Nginx配置、优化

  一)Nginx配置文件详解

  1、Nginx的性能优化

  nginx性能优化 - 小亮的BLOG - 博客园

  2、优化后的配置文件
user  nginx nginx;                #运行nginx的用户和组
worker_processes  8;              #允许启动的nginx进程数(一般是CPU的倍数)
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;   #为每个nginx进程绑定cpu,将8个nginx进程绑定到8个cpu上

worker_rlimit_nofile 102400;   #这个指令是指当一个Nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与Nginx进程数相除,但是Nginx分配请求并不是那么均匀,所以最好与ulimit -n的值保持一致。

client_header_buffer_size 4k;  #客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,以便一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k;所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得

open_file_cache max=102400 inactive=20s;  #这个将为打开文件指定缓存,默认是没有启用,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没有被请求后删除缓存。

open_file_cache_valid 30s; #这个是指多长时间检查一次缓存的有效信息。

open_file_cache_min_uses 1;  #open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是缓存中打开的,如上例,如果有一个文件在inactive时间内没有使用,它将被移除。


error_log  /log/nginx/error.log  error;   指定错误日志存放的路径,错误日志记录级别可选项为[ debug |info | notice | warn | error | crit ]

google_perftools_profiles /tmp/tcmalloc;     #做了nginx下的Google-perftools优化


events {
    use epoll;          #使用epoll的I/O模型
    multi_accept on;    #(告诉nginx收到一个新的连接通知后接受尽可能多的连接)是否允许一次性地响应多个用户请求,
    worker_connections  204800;     #每个进程允许的最大连接数
}


http {
    include       mime.types;                  #加载媒体类型
    default_type  application/octet-stream; 

    #charset gb2312    设置使用的字符集,如果一个网站有多种字符集,请不要随便设置,应让程序员在HTML代码中通过Meta标签设置   

    access_log /dev/null;    #不记录全局访问日志

    client_max_body_size 8m   设置客户端能够上传的文件大小
    
    sendfile       on;      
  #sendfile是Linux2.0+退出的一个系统调用,可以避免数据经过用户层,以此可以减少上下文切换次数,和数据拷贝次数。开启这项功能可以优化web服务器,从硬盘读取数据直接传送到网络的性能
    
    tcp_nopush     on;       #这个参数原理比较复杂,待定

    keepalive_timeout  65;   #设定长连接超时时长


    #压缩配置(主要是为了提高数据传输速度)

    gzip  on;                #开启nginx的gzip压缩,gzip压缩功能就是可以让你节省不少宽带,并加快传输速度,但是会增加服务器CPU的开销。
    gzip_disable "msie6";  #禁用IE6的gzip压缩,IE6的某些版本对gzip的压缩支持很不好,会照成页面的假死,测试发现对img进行gzip压缩后会照成IE6的假死。

    gzip_proxied any;      #对所有的代理结果数据无条件启动压缩
    gzip_min_length 1000;  #规定大于1K的页面才启动压缩(为了避免页面过小,数据可能会越压越大)
    gzip_comp_level 4;     #定义gzip的压缩比   1:压缩比最小,处理速度最快,9:压缩比最大但处理最慢(传输快但比较消耗CPU)

    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;   
  #指定需要压缩的MIME类型,"test/html"类型总是会被压缩的。

    gzip_vary on;    
  #与http头有关系,价格vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持。因此,为了避免浪费不支持的也压缩,需要根据客户端的HTTP头来判断,是否需要压缩(这个理论不太确定),一般用于squid做反向代理是gzip压缩失效。

    open_file_cache max=100000 inactive=20s;   
  #缓存打开文件描述的文件大小和修改时间信息、存在的目录信息、搜索文件的错误信息:文件不存在 无权限读取等信息。 max指定缓存数量  inactive是指经过多长时间文件没有被请求后删除缓存。
    #这里指定的是20s,所以等到至少20s不访问这个文件,相应缓存的这个文件的更改信息才会被删除

    open_file_cache_valid 30s;
    #这个是指多长时间检查一次缓存的有效信息。也就是说即使我一直访问这个文件,30s后会检查此文件的更改信息是否改变,发现变化就更新。

    open_file_cache_min_uses 2;
    #这个指令指定了open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如果使用更大的值,文件描述符在cached中总是打开状态。
    
    open_file_cache_errors on;
    #这个指令是否在搜索一个文件是记录cached错误。

}

   Nginx的正则匹配:Nginx配置文件nginx.conf详解 - 柔和的天空 - 博客园

  二)Nginx的日志配置

与Nginx日志相关的指令主要有两条,一条是log_format,用来设置日志的格式。另外一条是access_log,用来指定日志文件的存放路径、格式和缓存大小。两条指令在Nginx配置文件中的位置可以在http{....}之间,也可以在虚拟主机之间,即server{....}之间。


用log_format指令设置日志格式,语法如下:
log_format  name  format [format ...]
其中name表示定义的格式名称,format表示定义的格式样式。log_format有一个默认的、无需设置的combined日志格式设置,combined的日志格式如下:
log_format  combined  '$remote_addr - $remote_user [$time_local]'
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agetn"';
可以自定义一份日志的记录格式,不过要注意,log_format指令设置的name名称在Nginx配置文件中是不能重复的。

如果Nginx服务器作为Web服务器,位于负载均衡设备、Squid反向代理的之后,就不能获取到客户端的真实IP地址了。原因是经过反向代理后,由于在客户端和Web服务器之间增加了中间层,因此Web服务器无法直接拿到客户端的IP,通过$remote_addr变量拿到的将是反向代理服务器的IP地址。但是,反向代理服务器在转发请求的HTTP头信息中,可以增加X-Forwarded-For信息,用以记录原有的客户端IP地址和原来客户端请求的服务器地址。这个时候要用log_format指令来设置日志格式,让日志记录X-Forwarded-For信息中的IP地址,即客户的真实IP,设置如下
log_format  mylogformat  '$http_x_forwarded_for - $remote_user [$time_local] '
                        '"$request"  $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"'
 log_format main '[$time_iso8601] $remote_addr - $remote_user "$request" '
    '$status $request_time $upstream_response_time $upstream_addr $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for" "$scheme://$host$uri" "$http_x_connecting_for" "$http_real_ip"';


 log_format main01 '[$time_iso8601] $remote_addr - $remote_user "$request" '
    '$status $request_time $upstream_response_time $upstream_addr $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for" "$scheme://$host$uri" "$args" "$http_x_connecting_for" "$http_real_ip"';
日志格式样式中,

$remote_addr和$http_x_forwarded_for:用于记录IP地址;
$remote_user:用于记录远程客户端用户名称
$time_local用于记录访问时间与时区;
$request用于记录请求URL与HTTP协议
$status 用于记录请求状态
$body_bytes_sent  用于记录发送给客户端的文件主体内容大小
$http_referer 用于记录是从哪个页面链接访问过来的;
$http_user_agent用于记录客户端浏览器的相关信息。
access_log指令的语法如下:

access_log path  [format  [buffer=size  | off]]
path:指定日志路径
format:指定日志格式
buffer:指定日志内存缓冲区大小
如:access_log  /log/access.log  mylogformat  buffer=32k;
  access_log /opt/logs/nginx/www.test.com_access.log main;
  2、缓存设置

  http://nginx.org/en/docs/http/ngx_http_core_module.html

  示例一:

location = /images/default.gif {
    expires 30s; # 30m:30 分钟,2h:2 小时,30d:30 天
}

  示例二:

location ~* \.(jpg|jpeg|gif|bmp|png){
    expires 1d;#缓存1天
}

  expires 的上下文包括 location、if in location

  304 也是一种很好的缓存手段

  原理是: 服务器响应文件内容是,同时响应etag标签(内容的签名,内容一变,他也变), 和 last_modified_since 2个标签值

浏览器下次去请求时,头信息发送这两个标签, 服务器检测文件有没有发生变化,如无,直接头信息返回 etag,last_modified_since
浏览器知道内容无改变,于是直接调用本地缓存.
这个过程,也请求了服务器,但是传着的内容极少.
对于变化周期较短的,如静态html,js,css,比较适于用这个方式

  三)Nginx日志分割

  Nginx的信号控制

TERM,INT 快速关闭;
QUIT      从容关闭
HUP       平滑重启,重新加载配置文件
USR1      重新打开日志文件,在切割日志时用途较大
USR2      平滑升级可执行程序
WINCH     从容关闭工作进程

  Nginx的日志切割、归档(编写bash脚本实现),晚上0点定时执行

#!/bin/bash


log_base='/opt/logs/nginx'
top_level_domain='test.com'
log_archive_time=$(date -d yesterday +"%Y")/$(date -d yesterday +"%m")
yesterday_time=$(date -d yesterday +"%Y%m%d")
nginx_pid_dir='/usr/local/nginx/logs/nginx.pid'
server_name_pre="user api"


for i in ${server_name_pre}
do
  server_name=${i}.${top_level_domain}
  mkdir -p ${log_base}/${server_name}/${log_archive_time}
  cd ${log_base}/${server_name}
  mv ${server_name}-access.log ./${log_archive_time}/${server_name}-access_${yesterday_time}.log
  kill -USR1 `cat ${nginx_pid_dir}`    
done

  四)location和rewrite配置

  nginx中的rewrite用法及实例_ng代理rewrite转义符-优快云博客

  1、location的匹配方式
=用于普通uri前,要求精确匹配,如果匹配成功,则停止搜索并用当前location处理此请求
~ 表示uri包含正则,并且区分大小写
~*表示uri包含正则,但不区分大小写
^~表示在普通uri前要求Nginx服务器找到普通uri匹配度最高的那个location后,立即处理此请求,并不再进行正则匹配
^~和=都可以阻止继续匹配正则location两者的区别:“^~”依然遵守最大前缀原则,然后“=”是需要严格匹配

  详情见:Nginx location 匹配顺序整理 - fan-tastic - 博客园

  location的命中过程是怎样的?

  1. 先判断精准命中,若命中,立即返回结果并结束解析过程
  2. 判断普通命中,若有多个命中,记录下来最长的命中结果(注意:记录但不结束,最长的为准)
  3. 继续判断正则表达式的解析结果,按配置里的正则表达式顺序为准,由上到下开始匹配,一旦匹配成功一个,立即返回结果,并结束解析过程

  延伸分析:

  1. 普通命中,顺序无所谓,是因为按命中的长短来确定的
  2. 正则命中,顺序有所谓,因为是从前到后命中的

 

   2、rewrite重写

  官网文档:Module ngx_http_rewrite_module

  rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在server{},location{},if{}中,并且只能对域名后边的除去传递的参数外的字符串起作用,例如http://seanlook.com/a/we/index.PHP?id=1&u=str 只对/a/we/index.php重写。语法rewrite regex replacement [flag];

    1、标志位
1 last : 相当于Apache的[L]标记,表示完成rewrite
2 break : 停止执行当前虚拟主机的后续rewrite指令集
3 redirect : 返回302临时重定向,地址栏会显示跳转后的地址
4 permanent : 返回301永久重定向,地址栏会显示跳转后的地址

  因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里 last 和 break 区别有点难以理解:

1 last一般写在server和if中,而break一般使用在location中
2 last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
3 break和last都能组织继续执行后面的rewrite指令
    2、if指令与全局变量

  if判断指令

  语法为if(condition){...},对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:

  • 当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
  • 直接比较变量和内容时,使用=!=
  • ~正则表达式匹配,~*不区分大小写的匹配,!~区分大小写的不匹配
1 -f和!-f用来判断是否存在文件
2 -d和!-d用来判断是否存在目录
3 -e和!-e用来判断是否存在文件或目录
4 -x和!-x用来判断文件是否可执行

  全局变量

 1 $args : #这个变量等于请求行中的参数,同$query_string
 2 $content_length : 请求头中的Content-length字段。
 3 $content_type : 请求头中的Content-Type字段。
 4 $document_root : 当前请求在root指令中指定的值。
 5 $host : 请求主机头字段,否则为服务器名称。
 6 $http_user_agent : 客户端agent信息
 7 $http_cookie : 客户端cookie信息
 8 $limit_rate : 这个变量可以限制连接速率。
 9 $request_method : 客户端请求的动作,通常为GET或POST。
10 $remote_addr : 客户端的IP地址。
11 $remote_port : 客户端的端口。
12 $remote_user : 已经经过Auth Basic Module验证的用户名。
13 $request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
14 $scheme : HTTP方法(如http,https)。
15 $server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
16 $server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
17 $server_name : 服务器名称。
18 $server_port : 请求到达服务器的端口号。
19 $request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
20 $uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
21 $document_uri : 与$uri相同。
    3、常用的正则
 1 . : 匹配除换行符以外的任意字符
 2 ? : 重复0次或1次
 3 + : 重复1次或更多次
 4 * : 重复0次或更多次
 5 \d :匹配数字
 6 ^ : 匹配字符串的开始
 7 $ : 匹配字符串的介绍
 8 {n} : 重复n次
 9 {n,} : 重复n次或更多次
10 [c] : 匹配单个字符c
11 [a-z] : 匹配a-z小写字母的任意一个

  小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容。正则里面容易让人困惑的是\转义特殊字符。

  3、解决跨域问题
    location /apis {
        rewrite  ^.+apis/?(.*)$ /$1 break;
        include  uwsgi_params;
        proxy_pass   http://b.com:;
    }        

  五)架构篇

  1、相同server_name多个虚拟主机优先级访问

    

  启动时,会有warn,但不影响使用

  效果:会按照文件优先读取的顺序,成效的是第一个匹配到的配置。

  2、location匹配优先级
  • =          进行普通字符精确匹配,也就是完全匹配(优先级最高,匹配到就不再继续往下匹配)
  • ^~        表示普通字符匹配,使用前缀匹配(优先级最高,匹配到就不再继续往下匹配)
  • ~ \~*    表示执行一个正则(优先级比较低,继续往下匹配,若下面有更精确的匹配,会使用下面的配置;若没有就使用自身的配置)  ~区分大小写
    范例

  

  3、try_files的使用

  按顺序检查文件是否存在:存在直接访问,不存在后面的配置生效

  

    1、范例

  

    2、使用场景:缓存——缓存不存在,访问后面
  4、alias和root的区别

    访问加载的路径不同

    1、root

  

    2、alias

  

   5、传递用户的真实IP地址

  

  在第一层代理设置一个变量:set x_real_ip=$remote_addr

  6、其他
    1、Nginx:413 request entity too large
  • 用户上传文件限制:client_max_body_size
    2、502  badgateway
  • 后端服务无响应
    3、504 gateway time-out
  • 后端服务执行超时

  六)性能优化

  1、性能优化考虑点
    1、当前系统瓶颈

    观察指标、压力测试(接口压力测试)

    2、理解业务模式

    接口业务类型、系统层次结构

    3、性能与安全(权衡利弊)

    防火墙配置

   2、系统于Nginx的性能优化
    1、文件句柄

  Linux\Unix一切皆文件,文件句柄就是一个索引

    2、设置方式

  系统全局性修改、用户局部性修改、进程局部性修改

  /etc/security/limits.conf (修改完立即生效)

#用户局部修改
root soft nofile 65536
root hard nofile 65536
#全局
* soft nofile 65536
* hard nofile 65536
* soft nproc 65536
* hard nproc 65536
* soft  memlock  unlimited
* hard memlock  unlimited

  进程限制

worker_rlimit_nofile 10240;

  3、系统与Nginx的性能优化
    1、CPU的亲和

  

  查看物理CPU

cat /proc/cpuinfo|grep "physical id"|sort|uniq|wc -l

  查看每个CPU的核心

cat /proc/cpuinfo|grep "cpu cores"|sort|uniq|wc -l

  设置Nginx的CPU worker(建议和CPU的核数相同)

worker_processes 16;
worker_cpu_affinity auto; #Nginx1.9.x开始支持

events {
  use epoll;
  worker_connections 10240;  #建议改大
}

  查看Nginx进程使用CPU核数情况

ps -eo pid,args,psr|grep [n]ginx

  七)基于Nginx架构的安全篇

  1、常见的恶意行为
  • 网页行为:爬虫行为和恶意抓取、资源盗用(要分清允许和不允许的内容,采取不同的策略)
    • 基础防盗链功能:目的不让恶意用户能轻易的爬取网站对外数据
    • secure_link_module——对数据安全性提高加密验证和失效性,适合如核心重要数据
    • access_module:对后台、部分用户服务的数据提供IP防控
  2、常见的应用层攻击手段
  • 后台密码撞库——通过猜测密码字典不断对后台系统登录性尝试,以获取后台密码
    • 方法一:后台登录密码复杂度
    • 方法二:access_module——对后台提供IP防控
    • 方法三:预警机制:Nginx+lua
  • 文件上传漏洞——利用这些可以上传的接口将恶意代码植入服务器中,再通过url去访问以执行代码
  • SQL注入——利用未过滤/未审核用户输入的攻击方法,让应用运行本不应该运行的SQL代码

  

  

  

  sql中 #是注释

  3、Nginx防攻击策略

  

  4、场景:Nginx+lua的安全waf防火墙

   项目地址16年:GitHub - loveshell/ngx_lua_waf: ngx_lua_waf是一个基于lua-nginx-module(openresty)的web应用防火墙

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值