写给大忙人的nginx核心配置详解
由于当前很多应该都是前后端分离了,同时大量的基于http的分布式和微服务架构,使得很多时候应用和不同项目组之间的系统相互来回调用,关系复杂。如果使用传统的做法,都在应用中进行各种处理和判断,不仅维护复杂、容易出错,还大大增加开发、调试的工作量,在nginx中,有不少的非功能类其实是可以帮我们处理掉的,所以,对于现代开发人员来说,有必要对nginx的location比较熟悉,以便达到事半功倍的效果,比如说,日常的图片上传就是个例子,我们可以将图片上传到特定的目录,然后配置nginx对于用户上传的图片,都转发到特定的目录,该目录不一定是nginx的html目录,甚至是挂载的盘,这样对于一般的应用来说,既可以按应用规划设置文件服务器,也避免了需要安装和维护ftp服务器软件的工作。
nginx配置
因为Nginx是模块化架构,每个模块都会有一系列自己引入的指令,这些指令通常包含在指令块中,比如events模块,就有一个events块。如下所示:
events {
worker_connections 1024;
}
对于最常用的部分,指令块通常层层嵌套。例如:
http {
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/example.com.log;
location ^~ /admin/ {
index index.php;
}
}
}
默认情况下,之块会继承父块中声明的设置,除非明确覆盖。
在nginx的配置中,语法比较复杂,而且不同的指令,可能规则完全不同。
比如root仅接受一个字符,声明服务于网站的文件的根路径。
模块中通常定义了可以用于指令中的变量,变量以$开头。某些指令中不允许使用变量,比如error_log,此时它会被当做字面量处理。
指令的值可以带双引号、带单引号、不带引号,除非使用了特殊符号,此时需要用引号括起来以避免nginx解析误解,对于特殊符号需要当做字面量使用的,需要用\,比如$。
nginx的基本模块包括Core、Events(主要是声明网络机制,某些参数对系统的性能影响较大)、Configuration,这三个模块提供了整个基础架构。
nginx使用多进程架构。
核心模块的主要指令:
- error_log:声明日志文件的位置,error_log /file/path level;格式,默认是logs/error.log error。main,http, server,location级别都可以自定义。
- thread_pool:声明一个可供aio指令使用的线程池。主要用于服务于异步较大的文件请求时提高性能,thread_pool name threads=number [max_
- queue=number];默认为thread_pool default threads=32 max_queue=65536;。
- worker_processes:声明实际工作进程数,默认情况下,nginx会使用检测到的cpu数量而不是1,这一点现代系统基本上都是动态判断,不像早期一样默认为单核,甚至内存都是动态自己判断和设置。
- worker_cpu_affinity:声明进程跟cpu的亲和关系,一般仅在多核下使用,格式worker_cpu_affinity 1000 0100 0010 0001;每组代表一个进程,每组中的1代表第几个核心。
events模块的主要指令包括(这些指令必须声明在events块中):
- use:声明使用的事件模型,现代linux一般都应该使用epoll。
- worker_connections:声明工作进程可以同时处理的并发连接数。
配置模块的主要指令包括:
- include指令,在声明的位置插入指定文件的内容,跟spring的import/mybatis的sql一样。nginx内置模块化的文件包括nginx.conf、mime.types、fastcgi_params、proxy.conf、sites.conf,include的值支持通配符。
HTTP Core模块
HTTP Core模块包含了HTTP服务器的所有基础块、指令以及变量,其默认启用,实际上它也是最重要的一个模块。它包含三个主要的块:http,server,location。
- http块位于最高层,定义了所有和http相关的指令和块。
- server块声明一个网站,必须声明在http块内。
- location块声明应用于网站内特定路径的一组设置,可以声明在server块内,或者嵌套在其他location内。
一个典型的http配置结构如下:
主要指令包括:
- listen:声明监听的地址,listen [address][:port] [additional options];应用于server块。
- server_name:为server定义一个或多个主机名,server_name hostname1 [hostname2…];如果一个nginx服务提供多个网站时,该值可以用来进行区分。应用于server块。
- tcp_nopush:启用或者禁用TCP_NOPUSH (FreeBSD)/TCP_CORK(Linux) socket选项,仅在sendfile启用时有效,其作用是nginx尽量在一个tcp包中传输所有HTTP响应头。应用于所有块。
- sendfile:如果启用,nginx会使用sendfile内核调用处理文件传输,否则nginx会自己传输。应用于所有块。
路径相关指令包括:
- root:定义服务客户端请求的根目录,默认为html。应用于所有块以及if。
- alias:声明用来提取文件时的别名路径,根路径不变,应该主要是用于对外公共接口的内部地址变了。
- error_page:声明特定HTTP返回码的替换页面。格式为error_page code1 [code2…] [=replacement code] [=@block | URI]。应用于所有块以及if。
- index:定义nginx的默认页面,默认为index.html,可以声明多个。应用于所有块。
客户端请求相关的指令包括:
- keepalive_requests:一个长连接最多可以请求的数量,默认100,可应用于http, server, location。
- keepalive_timeout:定义长连接的超时时间,默认75,第二个参数的值会通过http包头传给客户端,格式:keepalive_timeout time1 [time2];应用于http, server, location。
- send_timeout:声明nginx多久后关闭未活动连接,客户端停止传输数据开始计算未活动,默认60秒。
- client_body_buffer_size:声明用于存放客户端请求体的缓存大小,默认8k或者16k,具体是系统架构而定。
限制相关的指令包括:
- limit_except:设置仅支持哪些HTTP方法。应用于location。例如:
location /admin/ {
limit_except GET {
allow 192.168.1.0/24;
deny all;
}
}
格式为:
limit_except METHOD1 [METHOD2…] {
allow | deny | auth_basic | auth_basic_user_file | proxy_pass | perl;
}
- limit_rate:设置每链接每秒钟的流量,默认不限,应用于http, server, location, if。
- internal:声明本location仅适用于内部访问,也就是必须通过rewrite才能访问。
文件和缓存相关的指令:
- directio:当文件超过特定大小时,使用Direct I/O系统机制直接从存储设备读取。应用于http, server, location。
其他指令:
- merge_slashes:是否合并连续的/为单个/,比如将http://website.com//documents/转换为http://website.com/documents/,默认情况下会报404。应用于http, server, location。
- resolver:声明nginx使用的自定义的DNS服务器。
- underscores_in_headers:声明自定义HTTP请求头中是否允许下划线名字,默认为不允许,http头中一般为-分隔。
- post_action:声明请求执行完成后,nginx调用的uri,特殊情况下可用,比如PV统计。
模块变量
HTTP Core模块包含了很多的变量,分为三类:第一类是在Http请求头中传递的,第二类是http响应头中的,第三类是完全nginx生成的。参考nginx http server第三版 90页。
nginx允许用户声明样式匹配指定的uri,location的语法为:
location [=|~|~*|^~|@] pattern { ... }
第一个可选的参数是修饰符,各修饰符详解如下:
- =修饰符:完全匹配,也就是直接常量比较。
- 无修饰符:必须以声明的样式开头,也就是like 'pattern%',通常servlet上下文匹配就是无修饰符的模式。
- ~修饰符:请求的URI必须大小写敏感的匹配声明样式的正则表达式。如:
server {
server_name website.com;
location ~ ^/abcd$ {
[…]
}
}
- ~*修饰符:请求的URI必须大小写不敏感的匹配声明样式的正则表达式。
- ^~修饰符:和无修饰符类似,区别在于如果当前location匹配请求,则不会继续搜索其他的location。
- @修饰符:定义一个命名location块,这些块不对外开放访问,仅用于内部转发。
搜索顺序和location匹配优先级
很多时候,我们定义的不止一个location,通常至少会有两个,一个是根本身,一个指向后端服务。所以我们需要理解nginx接收到一个请求之后,它如何确定匹配的location。定义在配置文件中的location顺序对于一个请求是否优先匹配没有关系,nginx搜索匹配的样式的顺序如下:
- =修饰符的location
- 无修饰符的location(如果精确匹配的话)
- ^~修饰符的location
- ~/~*修饰符的location
- 无修饰符的location(如果前缀匹配的话)
Rewrite模块
这个模块的目的就是为了URL重写,URL重写是SEO的关键元素之一。URL重写由rewrite指令执行,它接收一个样式和一个替换URI。
正则表达式规则参考nginx http server第三版P103。
注意,因为正则表达式的{}和nginx指令块冲突,所以如果要使用,必须放到引号中。
捕获,正则表达式中用()括起来的内容会被捕获到一个个内置变量中,$N,N为捕获的索引,从1开始。捕获的变量可以作为指令的值。()也通常和|一起使用,二选一。命名捕获使用?<name>语法设置,例如^/(?<folder>[^/]+)/(?<file>.*)$。
在nginx中,在正则表达式中捕获的值,可以在后续指令中使用,只要不被覆盖即可。
server {
server_name website.com;
location ~* ^/(downloads|files)/(.*)$ {
add_header Capture1 $1;
add_header Capture2 $2;
}
}
nginx区分内外部请求,内部请求由error_page, index, rewrite,try_files, add_before_body, add_after_body生成。内部请求还分两类:
- 内部重定向(Internal redirects):最常见的内部重定向是rewrite。
- 子请求(Sub-requests):内部自动触发,一般用的少。
简单的重定向如下:
server {
server_name website.com;
root /var/www/vhosts/website.com/httpdocs/;
location /storage/ {
internal;
alias /var/www/storage/;
}
location /documents/ {
rewrite ^/documents/(.*)$ /storage/$1;
}
}
Rewrite模块的指令包括:
- rewrite:为当前请求重写URI,格式为rewrite regexp replacement [flag];flag的取值以及含义为:
- last:当前的重写规则是最后一个,当前重写应用之后,就去寻找新匹配的location。
- break:当前重写规则应用之后,不再找新的location。
- redirect:返回302以及新的URI地址。
- permanent:返回301以及新的URI地址。
如果声明的URI以http://开头,nginx自动使用redirect标志。
可应用于server,location,if。
- break:用来防止后续重写,后面的重写都会被忽略。
- return:中止处理请求,返回声明的状态码或声明的文本。状态码为204, 400, 402 to 406, 408, 410, 411, 413, 416, and 500 to 504。
- set:初始化或定义变量。
- uninitialized_variable_warn:如果为on,nginx为每个遇到的未初始化的变量记录日志。
- rewrite_log:如果为on,Nginx为每一次重写记录notice级别的日志。
upstream模块
任何以_pass结尾的指令都接受到一组服务器的引用。声明一组服务器的第一步是在http的upstream块内声明一个或多个server指令,如下:
http {
upstream MyUpstream {
server 10.0.0.201;
server 10.0.0.202;
server 10.0.0.203;
}
[…]
}
然后在server块内引用声明的upstream,如下:
server {
server_name example.com;
listen 80;
root /home/example.com/www;
# Proxy all requests to the MyUpstream server group
proxy_pass http://MyUpstream;
[…]
}
nginx提供多种负载均衡机制,P248。从Nginx 1.9.0开始,新增的Stream模块支持TCP负载均衡,这意味原来必须使用LVS或者HAPROXY作为负载均衡机制的模式可以采用NGINX了。
要启用线程池,必须使用--withthreads参数编译nginx,对于经常文件下载的应用,应使用如下配置:
location /downloads/ {
aio threads;
directio 8k;
sendfile on;
}
ngx_http_log_module模块负责以声明的格式记录请求日志。
其主要的两个指令是:
- log_format:声明日志格式。格式为:log_format name [escape=default|json|none] string ...;默认为log_format combined "...";日志格式可以包含公用变量以及仅在日志写的时候存在的变量。配置总是包含预定义的“combined”格式,如下:
- access_log:设置写日志的路径、格式以及额外配置。格式为:
access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
默认为access_log logs/access.log combined;
nginx获取环境变量的值
首先参考centos下nginx安装与配置安装所需模块。
With Lua
If you are using Openresty, or have the ngx_lua
module and ngx_devel_kit
module installed, you are in luck.
You first need to declare what variables you'll be needing somewhere in your nginx.conf
file using the env
directive:
env API_KEY;
After that, when you want to access the environment variable, you can use a combination of set_by_lua
and os.getenv
, like this:
http { ... server { location / { set_by_lua $api_key 'return os.getenv("API_KEY")'; ... } } }
In this example we are assigning the environment variable to one of Nginx variables; we can use $api_key
as a regular nginx.conf
variable.
With Perl
Using Lua was our preferred approach, since we have OpenResty. If you can't use Lua, a second solution involves using Perl. The first part is similar; you must declare the variables he uses using env
:
env API_KEY;
After that, you can combine perl_set
and some Perl to do the same thing as before:
http { ... server { location / { perl_set $api_key 'sub { return $ENV{"API_KEY"}; }'; ... } } }
You will need to have the ngx_http_perl_module
module enabled in order to be able to use this technique.
写给大忙人的nginx核心配置详解的更多相关文章
- Nginx 核心配置详解
目录 Nginx 核心配置详解 Nginx 四层访问控制: Nginx账户认证功能: 自定义错误页面: 自定义访问日志: 检测文件是否存在: 长连接配置: 作为下载服务器配置: 作为上传服务器: 其他 ...
- PHP的核心配置详解
1.PHP核心配置详解 代码在不同的环境下执行的结果也会大有不同,可能就因为一个配置问题,导致一个非常高危的漏洞能够利用:也可能你已经找到的一个漏洞就因为你的配置问题,导致你鼓捣很久都无法构造成功的漏 ...
- nginx.conf配置详解
######Nginx配置文件nginx.conf中文详解##### #定义Nginx运行的用户和用户组 user www www; #nginx进程数,建议设置为等于CPU总核心数. worker_ ...
- Nginx location配置详解
上一篇博客Nginx配置详解已经说过了nginx 的基本配置情况,今天来详细讲述一下nginx的location的配置原则, location是根据Uri来进行不同的定位,location可以把网站的 ...
- Nginx的配置详解
人无再少年,花有重开日——风城玫瑰 德里克·罗斯 Nginx是一款轻量级的HTTP服务器,采用事件驱动的异步非阻塞处理方式框架,这让其具有极好的IO性能,时常用于服务端的反向代理和负载均衡. Ngin ...
- 快速部署Python应用:Nginx+uWSGI配置详解
在PHP里,最方便的就是deployment了,只要把php文件丢到支持PHP的路径里面,然后访问那个路径就能使用了:无论给主机添加多少PHP应用,只要把目录改好就没你的事了,完全不用关心php-cg ...
- Nginx基本属性配置详解
1. Nginx服务的基本配置 1.1 用于调试进程和定位问题的配置项 是否以守护进程的方式运行nginx # 默认on daemon on|off; 是否以master/worker方式工作 # 默 ...
- nginx location 配置详解 【转载,整理】
http://www.nginx.cn/115.html NGINX location 配置参考:http://www.cnblogs.com/zlingh/p/6288994.html https: ...
- 快速安装Nginx及配置详解(未完待续)
导读: Nginx (engine x) 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器,从2007年被德国人开发出来后可以说在市场的占有率一路飙升,因为它支持高并 ...
随机推荐
- async await的用法
const fs = require('fs'); const readFile = function (fileName) { return new Promise(function (resolv ...
- 6.C# 释放非托管资源2
C# 释放非托管资源 C#中资源分为托管资源和非托管资源. 托管资源由垃圾回收器控制如何释放,不需要程序员过多的考虑(当然也程序员也可以自己释放). 非托管资源需要自己编写代码来释放.那么编写好的释放 ...
- iOS UI基础-18.0 UIView
设置边框 UIView *bgView = [[UIView alloc] init]; bgView.backgroundColor = [UIColor whiteColor]; self.bgV ...
- 懒汉处理dapper字段名与属性名的映射方式
你还以为走路是世上最简单的事情呢?只不过是把一只脚放到另一只脚前面.但我一直很惊讶这些原本是本能的事情实际上做起来有多困难.而吃,吃也是一样的,有些人吃起东西来可困难了.说话也是,还有爱.这些东西都可 ...
- ANTLR4权威指南 - 第5章 设计语法
在第I部分,我们熟悉了ANTLR,并在一个比较高的层次上了解了语法以及语言程序.现在,我们将要放慢速度来学习下实现更实用任务的一些细节上的技巧,例如建立内部数据结构,提取信息,生成输入对应的翻译内容等 ...
- Python学习笔记之装饰器原理
def decorator(fn): def wrapper(): print("询价") fn() print("购买成功!") return wrapper ...
- 参考termux中包管理命令的伪装修改的arch版包管理命令
#!/bin/bash set -e -u show_help() { echo "This help message is useless, please read the content ...
- html5-select和datalist元素
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- Boss Bo (主席树)
主要想法:假设给你足够时间,那么就可以对每个点建议一颗线段树来查询了,但是需要将点全部按照某个特定的序列存进线段树,如代码是以树的深搜顺序作为指定顺序,这样以来我们既可以将数据查询分成诺干个区间进行查 ...
- python_super注意事项
class room: def __init__(self,area=120,usedfor='sleep'): self.area = area self.usedfor = usedfor def ...