Nginx教程
1.背景
介绍
Nginx是一个高性能的HTTP服务器,以及反向代理服务器
组成
Ngnix有内核和模块组成。微结构的内核根据配置文件将一个请求映射到一个location块中,该location内的指令会启动模块来工作。
模块分类(结构上)
核心类
HTTP、EVENT,以及MAIL模块。
基础类
HTTP的Access、FastCGI、Proxy,以及Rewrite模块。
第三方类
HTTP的 Upstream Request Hash、Access Key模块,以及Notice模块。
模块分类(功能上)
Handlers(处理器):处理请求并输出和修改handlers信息,一般只能有一个。
Filters(过滤器):对Handlers处理过的内容进行修改,最后由Nginx输出,可以有多个。
Proxies(代理类):HTTP Upstream之类,常与后端的服务,如fastcgi交互,实现服务代理和负载均衡功能。
处理请求的过程所经过的模块: --> 处理器 --> 过滤器1 [--> 过滤器2 -->过滤器n] -->
工作模式
工作模式有单工作进程和多工作进程两种。前者是除主进程外,只有一个单线程的工作进程;而后者是多个工作进程,每个进程是多线程的。Nginx默认是单工作进程模式。
优势
作为Web服务器,处理静态文件时索引效率很高
作为代理服务器,实现高效的代理
作为负载均衡服务器,既内部直接支持PHP,也支持代理服务器;同时支持容错和利用算法负载均衡
性能好,采用了Poll模型支持大并发,而且内存占用少
稳定性好,采用分阶段资源分配方式,让CPU和内存占用少
高可用性好,支持热部署,配置修改以及版本更新无需重启服务器
2.Nginx安装运行和测试(CentOS6)
在Centos/Redhat上先配置yum
#/etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
参考自:http://nginx.org/en/linux_packages.html#stable
安装完已经是开机启动的,所以安装完手动启动一下即可
# yum -y install nginx
# service nginx start
补充:高级编译安装(下面的实验会用到里面的增强功能)
ngx_cache_purge:http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
google-perftools:https://codeload.github.com/gperftools/gperftools/zip/master
安装正则表达式工具
yum -y install pcre-devel
cd /usr/local/src
安装缓存清理插件
tar xf ngx_cache_purge-2.3.tar.gz
安装高性能组件
tar xf libunwind-1.1.tar.gz
cd libunwind-1.1
CFLAGS=-fPIC ./configure
make CFLAGS=-fPIC
make CFLAGS=-fPIC install
cd ..
unzip gperftools-master.zip
cd gperftools-master
./autogen.sh
./configure
make
make install
echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
ldconfig
编译安装nginx
tar xf nginx-1.10.2.tar.gz
ln -s nginx-1.10.2 nginx
cd nginx
./configure --user=nginx --group=nginx \
--prefix=/usr/local/nginx \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-http_ssl_module \
--with-google_perftools_module \
--add-module=/usr/local/src/ngx_cache_purge-2.3
make
make install
在做./configure前优化编译过程,将auto/cc/gcc文件下面两行注释掉,不用debug方式编译
# debug
#CFLAGS="$CFLAGS -g"
3.配置文件
层次结构
main
events
HTTP
server1
upstream1
upstream2..n
location1
location2..n
server2..n
main:全局设置
server:主机设置,指定主机和端口
upstream:负载均衡设置,指定一系列后端服务器
location:URL匹配特定位置设置,指定匹配的网页
它们之间的继承关系为:location -> server -> main;而upstream与这三者没有关系
这4个部分包含若干指令,这些指令主要位于主模块、EVENT模块以及HTTP模块中,同时每个部分还可以使用其他HTTP模块命令,例如HTTP SSL、HTTPGzip、HTTPAddition等模块
配置详解
全局配置
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_processes: auto会根据主机CPU线程数启动对应数量的工作进程
events配置
events {
worker_connections 65535;
}
use epoll:已经没有了此配置,因为这是安装包默认的,会根据当前OS平台选择最优的event机制。
worker_connections:每个工作进程打开的连接数。此参数受Linux的进程最大打开文件数限制,需要用ulimit -n 65535对应修改。
客户端最大连接数 = worker_processes * worker_connections。
HTTP配置
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
include /etc/nginx/conf.d/*.conf;
}
log_format:定义日志格式,这里定义了一个名为main的格式;下面的access_log日志文件的内容由main日志格式定义
sendfile:on开启高效的文件传输模式
tcp_nopush:on开启防止网络阻塞
server配置
server {
listen 80;
server_name localhost;
charset UIF-8;
access_log /var/log/nginx/log/host.access.log main;
location / {
root /web/wwwroot/localhost;
index index.html index.htm;
}
location ~ \.(gif|jpg|jpeg|png|bmp)$ {
root /web/wwwroot/localhost;
expires 30d;
}
location ~ ^/(upload|html) {
root /web/wwwroot/localhost;
expires 30d;
}
location ~ \.jsp$ {
proxy_pass http://localhost:8080;
index index.jsp;
}
location /NginxStatus {
stub_status on;
access_log /var/log/nginx/log/NginxStatus.log;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
从上到下分别是静态文件、动态文件、服务器状态信息、网站错误页面的设置
维护技巧
配置文件校验
检查配置文件语法是否有无
nginx -t [-c $nginx.conf]
查看nginx版本号
nginx -v
查看编译的模块
nginx -V
启动、关闭,以及重启
几个跟nginx有关的信号
QUIT:处理完请求关闭工作进程
WINCH: 从容关闭工作进程
HUP: 重新加载配置文件,平滑重启
USR1: 日志切换
USR2:平滑升级可执行文件
启动
service nginx start
ps aux | grep nginx
平滑重启
kill -HUP `cat /var/run/nginx.pid`
4.常用功能
反向代理
反向代理服务器能代表所有外部客户端访问,请求内部网络服务,由于它不保存数据,因此能令后端服务器很安全。
反向代理服务器具有本地缓存后就称为web服务加速器
多域名跳转
实现多个域名的访问跳转到后端同一台服务器。
例子,以反向代理服务器A和后端服务器B为例说名,请求以www.tb.com域名从A跳转到B的/web目录,而请求以www.tb.com/admin的URL从A跳转到B的/admin目录,另外请求m.tb.com则从A跳转到B的/wap目录。配置文件代码主要如下:
server {
listen 80;
server_name www.tb.com;
location / {
proxy_pass http://127.0.0.1:8080/web/;
}
location /admin {
proxy_pass http://127.0.0.1:8080/admin;
}
}
server {
listen 80;
server_name m.tb.com;
location / {
proxy_pass http://127.0.0.1:8080/wap/;
}
}
注意,proxy_pass指令启动代理功能,要重点掌握。如果location匹配的是/根目录,则proxy_pass的目标路径需要以/结尾,如果location匹配的是/根目录下的子目录,则此子目录末尾和proxy_pass指定目标路径末尾都不能以/结尾
新旧域名重定向
常见需要重定向的场景有:新旧域名的替换,目录结构、网页文件名,以及文件后续名的变更。例子要求如果客户端访问www.taob.com,则自动跳转到新域名www.tb.com,下面是实现代码
方式一:
server {
listen 80;
server_name www.tb.com;
location / {
proxy_pass http://127.0.0.1:8080/web/;
}
}
server {
listen 80;
server_name www.taob.com;
rewrite /(.*)$ http://www.tb.com/$1 permanent;
}
启动两个主机,一个做反向代理,一个做重定向
方式二:
server {
listen 80;
server_name www.taob.com www.tb.com;
location / {
if ( $host != 'www.tb.com' ){
rewrite ^/(.*)$ http://www.tb.com/$1 permanent;
}
proxy_pass http://127.0.0.1:8080/web/;
}
}
这里使用了内置的$host变量比较主机名,作为判断是否重定向的条件
注意,rewrite指令启动了重定向功能,需要终点掌握,其最后的参数 permanent 表示永久重定向。
本地访问
别名
server{
listen 80;
server_name www.tb.com;
location / {
root /mysite/web/;
}
location /i {
alias /mysite/web/images;
}
}
注意,alias指令启动了别名的功能。
此例中访问http://www.tb.com会指向/mysite/web/目录,而访问http://www.tb.com/i/hello.jpg会指向/mysite/web/images/hello.jpg文件。
通常给子路径指定本地目录需要用到alias指令,也就是常说的起别名。我们通常在配置/目录时使用root指定路径,而配置/xxx子目录时使用alias指定路径。
location的优先级
location [ = | ~ | ~* | ^~ ] uri { ... }
=:表示精确匹配
~:正则表达式匹配,区分大小写
~*:正则表达式匹配,不区分大小写
^~:URI前半部分匹配,可省略
优先级顺序
字符字面量精确匹配 -> 正则表达式匹配 -> 按字符字面量左侧开始匹配
如果存在多个正则表达式同时匹配,优先选择最前面那个,如果存在URI前半部分多个匹配同时存在,优先选择最长前半部分那个匹配。
举例
location = / {
[ configuration A ]
}
location / {
[ configuration B ]
}
location /documents/ {
[ configuration C ]
}
location ^~ /images/ {
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
讲解:
/匹配A
/index.html匹配B
/documents/document.html匹配C
/images/1.gif匹配D
/documents/1.jpg匹配E
权限
这里列出了目录权限、IP访问权限,以及文件权限
例一 允许172.16.0.0/24和192.168.68.0/24网段的用户访问,但是192.168.68.1和其他来源IP的用户是不允许的
location / {
root /mysite/web/;
deny 192.168.68.1;
allow 172.16.0.0/24;
allow 192.168.68.0/24;
deny all;
}
这里重点以allow和deny指令为主
例二 将网页以目录的形式展示
location / {
root /mysite/web/;
autoindex on;
autoindex_exact_size on;
autoindex_localtime on;
}
这里重点以autoindex指令为主
例三 禁止访问/WEB-INF/目录
location /WEB-INF/ {
deny all;
}
例三 禁止访问资料文件
location ~* \.(txt|doc)$ {
root /mysite/web/;
deny all;
}
与URL重写相关的命令
if指令
判断表达式1,正则类
~:如果匹配正则表达式,则条件为真
~*:如果匹配正则表达式且不区分大小写,则条件为真
!~:如果不匹配正则表达式,则条件为真
!~*:如果与不区分大小写的正则表达式不匹配,则条件为真
判断表达式2,文件类
-f和!-f:判断是否文件
-d和!-d:判断是否目录
-e和!-e:判断文件或目录是否存在
-x和!-x:判断是否可执行
跟if指令一起使用常见内置变量
$limit_rate:用来限制连接的速度
$request_method
$host:请求头部中的Host
$uri:请求的URI
$request_uri:含有完整参数的初始URI
$args:请求行中的参数
$rquery_string:与$args相等
$request_filename:请求的本地文件绝对路径,有URI与alias、root组成
$document_root:对应当前请求的root指定路径
$document_uri:相当于$uri5gg3
$remote_addr:客户端的IP
$remote_port
$remote_user:用户名,由auth_basic认证
$server_name:请求达到的服务器名
$server_port
例子
server{
listen 80;
server_name www.tb.com;
location ~* \.(jpg|jpeg|bmp|gif|css|js|html|htm)$ {
root /mysite/web/images/;
if ( !-f $request_filename ) {
root /mysite/web/css/;
}
if ( !-f $request_filename ) {
root /mysite/web/js/;
}
if ( !-f $request_filename ) {
root /mysite/web/static/;
}
}
location ~* \.(txt)$ {
root /mysite/web/pages/ ;
if ( !-f $request_filename ) {
root /mysite/web/admin/ ;
}
# proxy_pass http://172.16.0.1:8080 ;
}
}
使用if条件和root来查找匹配文件,在第一个location,如果在/mysite/web/images/找不到,则在/mysite/web/css/找,如果也没有,接着在/mysite/web/js/,如果仍旧没有,最后在/mysite/web/static/查找。在第二个location,要注意的是,proxy不能和root一起使用,两者只能存一。
rewrite指令
rewrite regex replacement [flag];
flag标记有下面四个
last
break
redirect
permanent
其中,last和break,它们与URL重写有关,也就是说客户端看不到地址发生变化,前者表示后面继续搜索URL或location,而后者表示后面不再匹配。
而redirect和permanent,它们与URL重定向有关,也就是客户端能看到地址变化,前者表示临时重定向,后者表示永久重定向。
例子一:访问http://www.tb.com/best/test.html,重写为http://www.tb.com/test/test.html
location /best {
rewrite /best/(.*) /test/$1 break;
proxy_pass http://127.0.0.1:8080/test/;
}
这个例子先重写RUI然后转发出去
下面是更有代表意义的URI重写例子
rewrite ^/users/(.*)$ /show?user=$1? last;
set指令:
用来设置一个变量
location / {
proxy_pass http://127.0.0.1:8080/;
set $query $query_string;
rewrite /wp /wordpress/?$query?;
}
这个例子将/wp/?p=abc重写为/wordpress/?p=abc,利用到了自定义变量,这里要注意一点是rewrite指令的第二个问号表示查询字符串的结束。
5.做WEB缓存服务器
安装插件:
缓存插件默认已安装,另外要单独安装清除缓存的插件proxy_cache_purge,见前面的安装过程
配置:
在HTTP段加入两个定义
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache_one:512m inactive=1d max_size=3g;
proxy_temp_path /var/cache/nginx/proxy_temp;
proxy_cache_path表示缓存的目录,levels表示用两层目录结构--第一次单字符目录名而第二层双字符目录名,keys_zone表示缓存对象键的区域名以及分配的内存大小,inactive表示缓存时间d、h、m表示日、时、分,max_file表示内存满后写入磁盘缓存的最大大小
proxy_temp_path表示临时缓存的目录,它需要跟proxy_cache_path在同一分区
server段的完整定义如下:
server {
listen 80;
server_name www.tb.com;
charset UIF-8;
location / {
proxy_cache cache_one;
proxy_cache_valid 200 304 12h;
proxy_cache_key $host$uri$is_args$args;
proxy_set_header Host $Host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8080;
expires 1d;
}
location ~ /purge(/.*) {
allow 127.0.0.1;
allow 172.16.0.0/24;
deny all;
proxy_cache_purge cache_one $host$1$is_args$args;
}
location ~ .*\.(jsp|php|jspx)$ {
proxy_set_header Host $Host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
access_log off;
}
proxy_cache:表示当前location所使用的缓存区域
proxy_cache_valid:对哪些状态的页面缓存多久,例如对200和304缓存12小时
proxy_cache_key:缓存的对象名字是什么组合
proxy_cache_purge:对哪个缓存区域的缓存对象做清除
测试:
启动nginx会看到多了一个cache manager process进程,说明缓存已启动。
访问http://www.tb.com/cache/test.html,修改test.html后再访问,仍能看到修改前的内容则表示缓存有效,清楚缓存用地址http://www.tb.com/purge/cache/test.html,在原来地址的主机名后加多一层目录purge表示做清除缓存操作,补充一下,这个清除操作支持通配符
利用TCMalloc优化Nginx性能
TCMalloc是谷歌的google-perftools中的成员,比glibc的malloc在内存分配效率方面高很多,能提升服务器在并发时的性能,安装TCMalloc需要安装libunwind和google-perftools两个包,前者提供基本函数调用链和函数调用寄存器
安装libunwind和google-perftools
见前面的编译安装章节
创建线程目录
mkdir /tmp/tcmalloc
chown nginx:nginx /tmp/tcmalloc
chmod 0777 /tmp/tcmalloc
修改配置
在main区域的pid下添加一行
google_perftools_profiles /tmp/tcmalloc;
查看运行结果
重启ngins
[root@node5 sbin]# ps aux | grep nginx
root 63937 0.0 0.1 581572 1344 ? Ss 23:42 0:00 nginx: master process ./nginx
nginx 63938 0.1 3.0 612364 30372 ? S 23:42 0:00 nginx: worker process
nginx 63939 0.1 3.1 612364 32000 ? S 23:42 0:00 nginx: worker process
nginx 63940 0.0 3.0 612364 30372 ? S 23:42 0:00 nginx: worker process
nginx 63941 0.1 3.0 612364 30372 ? S 23:42 0:00 nginx: worker process
nginx 63942 0.0 0.3 585924 3976 ? S 23:42 0:00 nginx: cache manager process
root 63951 0.0 0.0 103256 844 pts/3 S+ 23:43 0:00 grep nginx
[root@node5 sbin]# lsof -n | grep tcmalloc
nginx 63938 nginx 12w REG 253,0 0 1048645 /tmp/tcmalloc.63938
nginx 63939 nginx 14w REG 253,0 0 1048643 /tmp/tcmalloc.63939
nginx 63940 nginx 16w REG 253,0 0 1048635 /tmp/tcmalloc.63940
nginx 63941 nginx 18w REG 253,0 0 1048646 /tmp/tcmalloc.63941
nginx 63942 nginx 18w REG 253,0 0 1048632 /tmp/tcmalloc.63942
启动tcmalloc,每个tcmalloc线程跟一个nginx工作进程关联一起,例如 63938 与 /tmp/tcmalloc.63938