nginx(engine X)
易百 Nginx教程:https://www.yiibai.com/nginx/
nginx中文文档:http://www.nginx.cn/doc/index.html
NGINX Documentation https://docs.nginx.com/
nginx documentation http://nginx.org/en/docs/
nginx for Windows http://nginx.org/en/docs/windows.html
作者个人网站:http://sysoev.ru/en/
Nginx开发从入门到精通http://tengine.taobao.org/book/index.html
【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器 - EdisonZhou - 博客园
https://www.cnblogs.com/edisonchou/p/4126742.html
Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性:
作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型.
作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。
作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。
Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在 不间断服务的情况下进行软件版本的升级。
nginx目录结构说明
- conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params两个文件,配置文件一般都有个样板配置文件,是文件名.default结尾,使用的使用将其复制为并将default去掉即可。
- html目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web文件是默认的错误页面提示页面。
- logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比如/var/logs/nginx里面。
- sbin(linux下,widows通过nginx.exe):保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。
nginx指令
查看帮助
nginx -h
nginx -?
查看版本
nginx -v
测试配置是否正常
nginx -t
nginx的启动和停止
windows
双击启动,杀掉nginx进程停止
tasklist /fi "imagename eq nginx.exe"
linux
启动nginx
(nginx二进制文件绝对路径,可以根据自己安装路径实际决定)
sudo /usr/local/nginx/nginx
nginx从容停止命令,等所有请求结束后关闭服务
ps -ef |grep nginx
kill -QUIT nginx主进程号
nginx 快速停止命令,立刻关闭nginx进程
ps -ef |grep nginx
kill -TERM nginx主进程号
如果以上命令不管用,可以强制停止
kill -9 nginx主进程号
如果嫌麻烦可以不用查看进程号,直接使用命令进行操作
其中`/usr/local/nginx/nginx.pid
为nginx.conf
中pid
命令设置的参数,用来存放nginx主进程号的文件
kill -信号类型(HUP|TERM|QUIT) `cat /usr/local/nginx/nginx.pid`
例如
kill -QUIT `cat /usr/local/nginx/nginx.pid`
nginx重启命令
nginx重启可以分成几种类型
- 简单型,先关闭进程,修改你的配置后,重启进程。
kill -QUIT cat /usr/local/nginx/nginx.pid
sudo /usr/local/nginx/nginx
- [重新加载配置文件,不重启进程,不会停止处理请求](http://www.nginx.cn/nginxchscommandline#reload config)
- [平滑更新nginx二进制,不会停止处理请求](http://www.nginx.cn/nginxchscommandline#reload bin)
nginx install
linux centos 安装
yum install nginx -yum -y
nginx 代理
proxy_pass http://v5;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
调试 nginx
Nginx的一个 杀手级特性 就是你能使用 debug_connection
指令只调试 某些 连接。
这个设置只有是你使用 --with-debug
编译的nginx才有效。
linux nginx 目录
配置文件目录
/etc/nginx
html目录
/usr/share/nginx/html
或者
/usr/local/nginx/html/
ocation的url 匹配优先级:
1、= 首先是精准匹配优先级最高
2、^~ 其次是以某特定常规字符串开头的匹配,这个不是正则
3、~ 、 ~*、!~、!~* 再次是按顺序的正则匹配,依次为区分大小写的正则匹配、不区分大小写的正则匹配、依次为区分大小写的正则不匹配、不区分大小写的正则不匹配、
4、最后是 / 的通用符匹配
以上依次为nginx location的url 匹配优先级
原文链接:https://blog.csdn.net/qq659851998/article/details/80210815
Nginx 十一个执行阶段
nginx rewrite 指令last break区别最详细的解释 - swing07 - 博客园
https://www.cnblogs.com/swing07/p/5381772.html
typedef enum {
NGX_HTTP_POST_READ_PHASE = 0,
NGX_HTTP_SERVER_REWRITE_PHASE,
NGX_HTTP_FIND_CONFIG_PHASE,
NGX_HTTP_REWRITE_PHASE, //rewrite阶段在这里
NGX_HTTP_POST_REWRITE_PHASE,
NGX_HTTP_PREACCESS_PHASE,
NGX_HTTP_ACCESS_PHASE,
NGX_HTTP_POST_ACCESS_PHASE,
NGX_HTTP_TRY_FILES_PHASE,
NGX_HTTP_CONTENT_PHASE,
NGX_HTTP_LOG_PHASE
} ngx_http_phases;
Module ngx_http_fastcgi_module
https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html
操作记录
[TOC]
说明,示例里面需要代理的测试站点均由nginx生成,站点文件在wwwroot
目录,拷贝到html
文件夹即可
配置一个网站
相关资源
- nginx-config/config-1
- wwwroot/config-1
配置目的
- 访问url: http://localhost:8100/ 即可访问site1
配置示例
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
}
}
配置说明
# 工作进程设置为一个
worker_processes 1 ;
# pid 进程id存储到的文件位置
pid logs/nginx.pid ;
# 配置事件模块,必须加上,为空使用默认配置
events
{
# 工作进程最大连接数
worker_connections 1024;
}
# 配置http 模块
http{
# 引入类型映射文件里面的内容(可以查看conf/mime.types文件)
include mime.types;
# 指定默认文件类型为二进制流
default_type application/octet-stream;
# 设置访问日志存储位置
access_log logs/access.log;
# 链接保持活动60s
keepalive_timeout 60;
# 配置服务模块
server{
# 配置服务监听端口 8100且 为默认
listen 8100 default;
#默认服务名,在linux下可以使用localhost,在win下使用
#127.0.0.1最好,不然在反向代理会出问题,加载很慢,win下专属bug
server_name 127.0.0.1;
# 配置定位 / (根目录开头) 的请求
location / {
# 根目录
root html/site1;
# 默认访问的文件
index index.html;
}
}
}
配置一个网站,部分路径要映射,开启目录浏览功能
相关资源
- nginx-config/config-2
- wwwroot/config-2
配置目的
- 访问url: http://localhost:8100/ 即可访问site1
- 映射
html/site1/common/css/face.css
到/face.css
- 映射
html/site1/common/images/face
到/face
- 开启目录浏览,通过
/files
访问html/site1/common
目录下的文件
配置示例
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
location /face.css{
root html/site1/common/css;
}
location /face{
alias html/site1/common/images/icon;
}
location /files{
root html/site1/common;
autoindex on;
autoindex_exact_size on;
autoindex_localtime on;
charset utf-8;
}
}
}
配置说明
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
#实际访问路径等于root指定的路径+location定位的路径
#即html/site1/common/css/face.css
location /face.css{
root html/site1/common/css;
}
#location定位的路径访问的实际路径就是alias指定的路径
#访问 /face 实际访问html/site1/common/images/icon
location /face{
alias html/site1/common/images/icon;
}
#html/site1/common/files
# 开启目录浏览功能
location /files{
root html/site1/common;
autoindex on;
autoindex_exact_size on;
autoindex_localtime on;
# 指定字符编码,避免乱码
charset utf-8;
}
}
}
配置负载均衡
相关资源
- nginx-config/config-3
- wwwroot/config-3
配置目的
-
配置站点site1、site1.slave1、site1.salve2分别到端口8200、8201、8202
-
代理上面三个站点到8100
-
访问url: http://localhost:8100/ 即可访问
配置示例
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
# [start] config site1 and slave site
server{
listen 8200;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
}
server{
listen 8201;
server_name 127.0.0.1;
location / {
root html/site1.slave1;
index index.html;
}
}
server{
listen 8202;
server_name 127.0.0.1;
location / {
root html/site1.slave2;
index index.html;
}
}
# [end] config site1 and slave site
# [start] config upstream
upstream site1{
# site1
server 127.0.0.1:8200 weight=1;
# site1.slave1
server 127.0.0.1:8201 weight=1;
# site1.slave2
server 127.0.0.1:8202 weight=1;
}
# [end] config upstream
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
proxy_pass http://site1;
}
}
}
配置说明
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
# [start] config site1 and slave site
server{
listen 8200;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
}
server{
listen 8201;
server_name 127.0.0.1;
location / {
root html/site1.slave1;
index index.html;
}
}
server{
listen 8202;
server_name 127.0.0.1;
location / {
root html/site1.slave2;
index index.html;
}
}
# [end] config site1 and slave site
# [start] config upstream
# 配置负载均衡代理,轮询方式负载(默认就是轮询)
upstream site1{
# site1
server 127.0.0.1:8200 weight=1;
# site1.slave1
server 127.0.0.1:8201 weight=1;
# site1.slave2
server 127.0.0.1:8202 weight=1;
}
# [end] config upstream
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
# 这里进行代理访问
proxy_pass http://site1;
}
}
}
配置负载均衡,把配置文件拆分到多个文件
相关资源
- nginx-config/config-4
- wwwroot/config-4
配置目的
- 配置站点site1、site1.slave1、site1.salve2分别到端口8200、8201、8202
- 上述的三个站点的配置文件放置conf.d文件夹
- 代理上面三个站点到8100
- 访问url: http://localhost:8100/ 即可访问
配置示例
site1.conf
server{
listen 8200;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
}
site1.slave1.conf
server{
listen 8201;
server_name 127.0.0.1;
location / {
root html/site1.slave1;
index index.html;
}
}
site1.slave2.conf
server{
listen 8202;
server_name 127.0.0.1;
location / {
root html/site1.slave2;
index index.html;
}
}
nginx.conf
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
# [start] config site1 and slave site
#include site1.conf;
#include site1.slave1.conf;
#include site1.slave2.conf;
# 引入conf.d文件夹下的所有配置文件
include conf.d/*.conf;
# [end] config site1 and slave site
# [start] config upstream
upstream site1{
# site1
server 127.0.0.1:8200 weight=1;
# site1.slave1
server 127.0.0.1:8201 weight=1;
# site1.slave2
server 127.0.0.1:8202 weight=1;
}
# [end] config upstream
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
proxy_pass http://site1;
}
}
}
配置站点到二级目录
相关资源
- nginx-config/config-5
- wwwroot/config-5
配置目的
- 配置site1到8100
- 配置site2到8102,注意,site2站点里面的路径不能使用绝对路径,否则很多文件无法代理上,需要用sub_filter模块来替换
- 把site2代理到 8100/site2
配置示例
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
location /site2/{
proxy_pass http://127.0.0.1:8101/;
}
location /site2/backup/ {
proxy_pass http://127.0.0.1:8101/site2/;
}
}
server{
listen 8101 default;
server_name 127.0.0.1;
location / {
root html/site2;
index index.html;
}
location /site2 {
root html;
index index.html;
}
}
}
配置说明
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
# 用于把来自8101的所有资源都代理到 /site2路径下,即
# 访问任何资源都有site2 路径
#注意要加斜杠,不然会路径拼接
location /site2/{
proxy_pass http://127.0.0.1:8101/;
}
# 把子目录site2给映射到/site2/backup/
location /site2/backup/ {
proxy_pass http://127.0.0.1:8101/site2/;
}
}
server{
listen 8101 default;
server_name 127.0.0.1;
location / {
root html/site2;
index index.html;
}
location /site2 {
root html;
index index.html;
}
}
}
使用 ngx_http_sub_module 模块
Module ngx_http_sub_module
http://nginx.org/en/docs/http/ngx_http_sub_module.html
包含指令
- sub_filter
- sub_filter_last_modified
- sub_filter_once
- sub_filter_types
相关资源
- nginx-config/config-6
- wwwroot/config-6
配置示例
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
sub_filter_once off;
#sub_filter_types text/html; default
sub_filter_types text/css;
sub_filter_types application/javascript;
sub_filter_last_modified on;
sub_filter 'imgerror' 'img';
sub_filter '[placeholder1]' '我是替换[placeholder1]的内容';
sub_filter '[placeholder2]' '世人谓我恋长安,其实只恋长安某。';
sub_filter '[host]' '$host';
}
}
}
配置说明
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
# 关闭只替换一次
sub_filter_once off;
# 指定可以替换的文件类型
#sub_filter_types text/html; default 这个是默认的选项
sub_filter_types text/css;
sub_filter_types application/javascript;
# 允许对原始响应的表头字段 Last-Modified 保留方便缓存响应
sub_filter_last_modified on;
# 匹配到的imgerror替换为 img
sub_filter 'imgerror' 'img';
sub_filter '[placeholder1]' '我是替换[placeholder1]的内容';
sub_filter '[placeholder2]' '世人谓我恋长安,其实只恋长安某。';
# 把 [host] 替换为变量 $host(即主机名称)
sub_filter '[host]' '$host';
}
}
}
使用 ngx_http_autoindex_module 模块
Module ngx_http_autoindex_module
http://nginx.org/en/docs/http/ngx_http_autoindex_module.html
包含指令
- autoindex
- autoindex_exact_size
- autoindex_format
- autoindex_localtime
相关资源
- nginx-config/config-7
- wwwroot/config-7
配置示例
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
location /files{
root html/site1;
autoindex on;
autoindex_exact_size off;
autoindex_format html;
autoindex_localtime on;
}
}
}
配置说明
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
location /files{
root html/site1;
# 开启目录索引
autoindex on;
# 指定视图格式,默认html,其余有xml,json,jsonp
# jsonp的回调函数方法名是callback参数指定,如/files/?callback=getList
autoindex_format html;
# on 在视图格式是html情况下,显示文件大小单位是字节,off则会转换为 kb,mb,gb
autoindex_exact_size off;
# 时间是输出localtime还是UTC
autoindex_localtime on;
}
}
}
使用ngx_http_rewrite_module 模块
Module ngx_http_rewrite_module
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
nginx rewrite规则之last和break_运维_远古大猛犸-CSDN博客
https://blog.csdn.net/shmnh/article/details/54885907
包含指令
- break
- if
- return
- rewrite
- rewrite_log
- set
- uninitialized_variable_warn
break 和 last 都能阻止继续执行后面的 rewrite 指令,但是 last 如果在 location 下用的话,对于重写后的 URI 会重新匹配 location ,但是 break 则不会重新匹配 location 。
相关资源
- nginx-config/config-8
- wwwroot/config-8
配置示例
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
rewrite_log on;
error_log logs/error.log info;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
location /permanent{
rewrite ^(.*)$ /301 permanent;
}
location /redirect{
rewrite ^(.*)$ /302 redirect;
}
location /break{
rewrite ^/break/(.*) /test/$1 break;
echo "break page";
}
location /last/ {
rewrite ^/last/(.*) /test/$1 last;
echo "last page";
}
location /test/ {
echo "test page";
}
location /200 {
default_type application/json;
return 200 '{"status":"OK"}';
}
location /404 {
default_type application/json;
return 200 '{"status":"Not Found"}';
}
location /500 {
default_type application/json;
return 200 '{"status":"Internal Server Error"}';
}
location /301 {
default_type application/json;
return 200 '{"status":"Moved Permanently"}';
}
location /302 {
default_type application/json;
return 200 '{"status":"Moved Temporarily"}';
}
location /uri{
default_type text/plain;
return 200 $uri;
}
}
}
配置说明
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
# 开启重写日志,日志在 error.log
rewrite_log on;
# 开启错误日志 info级别
error_log logs/error.log info;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
#访问此路径 301 永久重定向
location /permanent{
rewrite ^(.*)$ /301 permanent;
}
#访问此路径 302 临时重定向
location /redirect{
rewrite ^(.*)$ /302 redirect;
}
location /break{
# break会终止rewrite命令,继续执行echo,进行内容输出
# 如果注释掉echo,则会去找 /test/xx.html作为内容输出
rewrite ^/break/(.*) /test/$1 break;
echo "break page";
}
location /last/ {
# last会在匹配到路径后,重新发起/test请求,不会继续执行
# echo "last page";,然后/test请求返回 "test page"
rewrite ^/last/(.*) /test/$1 last;
echo "last page";
}
location /test/ {
echo "test page";
}
location /200 {
default_type application/json;
return 200 '{"status":"OK"}';
}
location /404 {
default_type application/json;
return 200 '{"status":"Not Found"}';
}
location /500 {
default_type application/json;
return 200 '{"status":"Internal Server Error"}';
}
location /301 {
default_type application/json;
return 200 '{"status":"Moved Permanently"}';
}
location /302 {
default_type application/json;
return 200 '{"status":"Moved Temporarily"}';
}
location /uri{
default_type text/plain;
return 200 $uri;
}
}
}
把http站点升级为https站点
相关资源
- nginx-config/config-9
- wwwroot/config-9
配置目的
- http端口在8100
- https端口在8101
访问8100 永久重定向到8101- 8100 8101 都能访问
配置示例
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
# rewrite ^(.*)$ https://$host:8101$request_uri permanent;
#return 301 https://$host:8101$request_uri;
#if ($scheme = http ) {
# return 301 https://$host:8101$request_uri;
#}
#if ($server_port = 80 ) {
# return 301 https://$host:8101$request_uri;
#}
}
server{
listen 8101 ssl;
server_name 127.0.0.1;
ssl on;
ssl_certificate ssl-ca/server.crt;
ssl_certificate_key ssl-ca/server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH:AESGCM:HIGH:!RC4:!DH:!MD5:!3DES:!aNULL:!eNULL;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:8100;
proxy_redirect off;
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;
chunked_transfer_encoding off;
}
}
}
配置说明
worker_processes 1;
pid logs/nginx.pid ;
events
{
worker_connections 1024;
}
http{
include mime.types;
default_type application/octet-stream;
access_log logs/access.log;
keepalive_timeout 60;
server{
listen 8100 default;
server_name 127.0.0.1;
location / {
root html/site1;
index index.html;
}
# 下面的方式都可以重定向
# rewrite ^(.*)$ https://$host:8101$request_uri permanent;
#return 301 https://$host:8101$request_uri;
#if ($scheme = http ) {
# return 301 https://$host:8101$request_uri;
#}
#if ($server_port = 80 ) {
# return 301 https://$host:8101$request_uri;
#}
}
server{
listen 8101 ssl;
server_name 127.0.0.1;
ssl on;
ssl_certificate ssl-ca/server.crt; #证书公钥
ssl_certificate_key ssl-ca/server.key; #证书私钥
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH:AESGCM:HIGH:!RC4:!DH:!MD5:!3DES:!aNULL:!eNULL;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:8100;
proxy_redirect off;
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;
chunked_transfer_encoding off;
}
}
}
Nginx为什么比Apache Httpd高效:原理篇
一、进程、线程?
进程是具有一定独立功能的,在计算机中已经运行的程序的实体。在早期系统中(如linux 2.4以前),进程是基本运作单位,在支持线程的系统中(如windows,linux2.6)中,线程才是基本的运作单位,而进程只是线程的容器。程序 本身只是指令、数据及其组织形式的描述,进程才是程序(那些指令和数据)的真正运行实例。若干进程有可能与同一个程序相关系,且每个进程皆可以同步(循序)或异步(平行)的方式独立运行。现代计算机系统可在同一段时间内以进程的形式将多个程序加载到存储器中,并借由时间共享(或称时分复用),以在一个处 理器上表现出同时(平行性)运行的感觉。同样的,使用多线程技术(多线程即每一个线程都代表一个进程内的一个独立执行上下文)的操作系统或计算机架构,同样程序的平行线程,可在多 CPU 主机或网络上真正同时运行(在不同的CPU上)。
二、常见Web服务方式
2.1 三种工作模型比较
Web服务器要为用户提供服务,必须以某种方式,工作在某个套接字上。一般Web服务器在处理用户请求是,一般有如下三种方式可选择:多进程方式、多线程方式、异步方式。
-
多进程方式:为每个请求启动一个进程来处理。由于在操作系统中,生成进程、销毁进程、进程间切换都很消耗CPU和内存,当负载高时,性能会明显降低。
- 优点: 稳定性!由于采用独立进程处理独立请求,而进程之间是独立的,单个进程问题不会影响其他进程,因此稳定性最好。
- 缺点: 资源占用!当请求过大时,需要大量的进程处理请求,进程生成、切换开销很大,而且进程间资源是独立的,造成内存重复利用。
-
多线程方式:一个进程中用多个线程处理用户请求。由于线程开销明显小于进程,而且部分资源还可以共享,因此效率较高。
- 优点:开销较小!线程间部分数据是共享的,且线程生成与线程间的切换所需资源开销比进程间切换小得多。
- 缺点:稳定性!线程切换过快可能造成线程抖动,且线程过多会造成服务器不稳定。
-
异步方式:使用非阻塞方式处理请求,是三种方式中开销最小的。但异步方式虽然效率高,但要求也高,因为多任务之间的调度如果出现问题,就可能出现整体故障,因此使用异步工作的,一般是一些功能相对简单,但却符合服务器任务调度、且代码中没有影响调度的错误代码存在的程序。
- 优点:性能最好!一个进程或线程处理多个请求,不需要额外开销,性能最好,资源占用最低。
- 缺点:稳定性!某个进程或线程出错,可能导致大量请求无法处理,甚至导致整个服务宕机。
2.2 一个Web请求的处理过程:
- 客户发起情况到服务器网卡;
- 服务器网卡接受到请求后转交给内核处理;
- 内核根据请求对应的套接字,将请求交给工作在用户空间的Web服务器进程
- Web服务器进程根据用户请求,向内核进行系统调用,申请获取相应资源(如index.html)
- 内核发现web服务器进程请求的是一个存放在硬盘上的资源,因此通过驱动程序连接磁盘
- 内核调度磁盘,获取需要的资源
- 内核将资源存放在自己的缓冲区中,并通知Web服务器进程
- Web服务器进程通过系统调用取得资源,并将其复制到进程自己的缓冲区中
- Web服务器进程形成响应,通过系统调用再次发给内核以响应用户请求
- 内核将响应发送至网卡
- 网卡发送响应给用户
通过这样的一个复杂过程,一次请求就完成了。
简单来说就是:用户请求-->送达到用户空间-->系统调用-->内核空间-->内核到磁盘上读取网页资源->返回到用户空间->响应给用户。上述简单的说明了一下,客户端向Web服务请求过程,在这个过程中,有两个I/O过程,一个就是客户端请求的网络I/O,另一个就是Web服务器请求页面的磁盘I/O。 下面我们就来说说Linux的I/O模型。
三、各种I/O模型详解
通过上面的对连接的处理分析,我们知道工作在用户空间的web服务器进程是无法直接操作IO的,需要通过系统调用进行,其关系如下:
即进程向内核进行系统调用申请IO,内核将资源从IO调度到内核的buffer中(wait阶段),内核还需将数据从内核buffer中复制(copy阶段)到web服务器进程所在的用户空间,才算完成一次IO调度。这几个阶段都是需要时间的。根据wait和copy阶段的处理等待的机制不同,可将I/O动作分为如下五种模式:
- 阻塞I/O
- 非阻塞I/O
- I/O复用(select和poll)
- 信号(事件)驱动I/O(SIGIO)
- 异步I/O(aio)
3.1 I/O模型简介
这里有必要先解释一下阻塞、非阻塞,同步、异步、I/O的概念。
3.1.1 阻塞和非阻塞:
阻塞和非阻塞指的是执行一个操作是等操作结束再返回,还是马上返回。
比如餐馆的服务员为用户点菜,当有用户点完菜后,服务员将菜单给后台厨师,此时有两种方式:
- 第一种:就在出菜窗口等待,直到厨师炒完菜后将菜送到窗口,然后服务员再将菜送到用户手中;
- 第二种:等一会再到窗口来问厨师,某个菜好了没?如果没有先处理其他事情,等会再去问一次;
第一种就是阻塞方式,第二种则是非阻塞的。
3.1.2 同步和异步:
同步和异步又是另外一个概念,它是事件本身的一个属性。还拿前面点菜为例,服务员直接跟厨师打交道,菜出来没出来,服务员直接指导,但只有当厨师将 菜送到服务员手上,这个过程才算正常完成,这就是同步的事件。同样是点菜,有些餐馆有专门的传菜人员,当厨师炒好菜后,传菜员将菜送到传菜窗口,并通知服务员,这就变成异步的了。其实异步还可以分为两种:带通知的和不带通知的。前面说的那种属于带通知的。有些传菜员干活可能主动性不是很够,不会主动通知你,你就需要时不时的去关注一下状态。这种就是不带通知的异步。
对于同步的事件,你只能以阻塞的方式去做。而对于异步的事件,阻塞和非阻塞都是可以的。非阻塞又有两种方式:主动查询和被动接收消息。被动不意味着一定不好,在这里它恰恰是效率更高的,因为在主动查询里绝大部分的查询是在做无用功。对于带通知的异步事件,两者皆可。而对于不带通知的,则只能用主动查询。
对上面的举例子如下:
同步事件,如坐车回家,在车没有到之前,你只有等车,等到车来了,然后才能回家。
异步事件,如早上出门,你一般是先洗漱,做锻炼,然后上班,洗漱和做锻炼没有顺序要求,有天,厕所被父母先占用了,这时你可以等父母出来,然后进去洗漱、做锻炼、上班,当然,你也可以先做锻炼,然后去洗漱,之后上班,前者就是阻塞,后者就是非阻塞,整个事件是异步事件。
3.1.3 全异步I/O
回到I/O,不管是I还是O,对外设(磁盘)的访问都可以分成请求和执行两个阶段。请求就是看外设的状态信息(比如是否准备好了),执行才是真正的 I/O操作。在Linux 2.6之前,只有“请求”是异步事件,2.6之后才引入AIO(asynchronous I/O )把“执行”异步化。别看Linux/Unix是用来做服务器的,这点上比Windows落后了好多,IOCP(Windows上的AIO,效率极高)在Win2000上就有了。所以学linux的别老觉得Windows这里不好那里不好(Windows的多线程机制也由于linux)。
3.1.4 I/O的五种模型
根据以上分析,I/O可分为五种模型:
- 阻塞I/O:所有过程全阻塞
- 非阻塞I/O:如果没有数据buffer,则立即返回EWOULDBLOCK
- I/O复用(select和poll):在wait和copy阶段分别阻塞
- 信号驱动I/O(SIGIO):在wait阶段不阻塞,但copy阶段阻塞(信号驱动I/O,即通知)
- 异步I/O(aio):完全无阻塞方式,当I/O完成是提供信号
Linux上的前四种I/O模型的“执行”阶段都是同步的,只有最后一种才做到了真正的全异步。第一种阻塞式是最原始的方法,也是最累的办法。当然累与不累要看针对谁。应用程序是和内核打交道的。对应用程序来说,这种方式是最累的,但对内核来说这种方式恰恰是最省事的。还拿点菜这事为例,你就是应用程序,厨师就是内核,如果你去了一直等着,厨师就省事了(不用同时处理其他服务员的菜)。当然现在计算机的设计,包括操作系统,越来越为终端用户考虑了, 为了让用户满意,内核慢慢的承担起越来越多的工作,IO模型的演化也是如此。
非阻塞I/O ,I/O复用,信号驱动式I/O其实都是非阻塞的,当然是针对“请求”这个阶段。非阻塞式是主动查询外设状态。I/O复用里的select,poll也是主动查询,不同的是select和poll可以同时查询多个fd(文件句柄)的状态,另外select有fd个数的限制。epoll是基于回调函数的。信号驱动式I/O则是基于信号消息的。这两个应该可以归到“被动接收消息”那一类中。最后就是伟大的AIO的出现,内核把什么事都干了,对上层应用实现了全异步,性能最好,当然复杂度也最高。
3.2 各I/O模型详细介绍【本部分摘自独孤成博客】:
3.2.1 阻塞I/O
说明:应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好,一直等待数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。这个不用多解释吧,阻塞套接字。下图是它调用过程的图示:(注,一般网络I/O都是阻塞I/O,客户端发出请求,Web服务器进程响应,在进程没有返回页面之前,这个请求会处于一直等待状态)
3.2.2 非阻塞I/O
我们把一个套接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,不要将进程睡眠,而是返回一个错误。这样我们的I/O操作函数将不断的测试数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间,所有一般Web服务器都不使用这种I/O模型。具体过程如下图:
3.2.3 I/O复用(select和poll)
I/O复用模型会用到select或poll函数或epoll函数(Linux2.6以后的内核开始支持),这两个函数也会使进程阻塞,但是和阻塞 I/O所不同的的,这两个函数可以同时阻塞多个I/O操作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正 调用I/O操作函数。具体过程如下图:
3.2.4 信号驱动I/O(SIGIO)
首先,我们允许套接口进行信号驱动I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。具体过程如下图:
3.2.5 异步I/O(aio)
当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入输出操作。具体过程如下图:
3.2.6 I/O 模型总结(如下图)
从上图中我们可以看出,可以看出,越往后,阻塞越少,理论上效率也是最优。其五种I/O模型中,前三种属于同步I/O,后两者属于异步I/O。
同步I/O:
阻塞I/O
非阻塞I/O
I/O复用(select和poll)
异步I/O:
信号驱动I/O(SIGIO) (半异步)
异步I/O(aio) (真正的异步)
异步 I/O 和 信号驱动I/O的区别:
信号驱动 I/O 模式下,内核可以复制的时候通知给我们的应用程序发送SIGIO 消息。
异步 I/O 模式下,内核在所有的操作都已经被内核操作结束之后才会通知我们的应用程序。
3.3 Linux I/O模型的具体实现[转自孤城博客]
3.3.1 主要实现方式有以下几种:
- select
- poll
- epoll
- kqueue
- /dev/poll
- iocp
注,其中iocp是Windows实现的,select、poll、epoll是Linux实现的,kqueue是FreeBSD实现的,/dev /poll是SUN的Solaris实现的。select、poll对应第3种(I/O复用)模型,iocp对应第5种(异步I/O)模型,那么 epoll、kqueue、/dev/poll呢?其实也同select属于同一种模型,只是更高级一些,可以看作有了第4种(信号驱动I/O)模型的某 些特性,如callback机制。
3.3.2 为什么epoll、kqueue、/dev/poll比select高级?
答案是,他们无轮询。因为他们用callback取代了。想想看,当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个 Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成 相关操作,那就避免了轮询,这正是epoll、kqueue、/dev/poll做的。这样子说可能不好理解,那么我说一个现实中的例子,假设你在大学读书,住的宿舍楼有很多间房间,你的朋友要来找你。select版宿管大妈就会带着你的朋友挨个房间去找,直到找到你为止。而epoll版宿管大妈会先记下 每位同学的房间号,你的朋友来时,只需告诉你的朋友你住在哪个房间即可,不用亲自带着你的朋友满大楼找人。如果来了10000个人,都要找自己住这栋楼的 同学时,select版和epoll版宿管大妈,谁的效率更高,不言自明。同理,在高并发服务器中,轮询I/O是最耗时间的操作之一,select、 epoll、/dev/poll的性能谁的性能更高,同样十分明了。
3.3.3 Windows or *nix (IOCP or kqueue、epoll、/dev/poll)?
诚然,Windows的IOCP非常出色,目前很少有支持asynchronous I/O的系统,但是由于其系统本身的局限性,大型服务器还是在UNIX下。而且正如上面所述,kqueue、epoll、/dev/poll 与 IOCP相比,就是多了一层从内核copy数据到应用层的阻塞,从而不能算作asynchronous I/O类。但是,这层小小的阻塞无足轻重,kqueue、epoll、/dev/poll 已经做得很优秀了。
3.3.4 总结一些重点
只有IOCP(windows实现)是asynchronous I/O,其他机制或多或少都会有一点阻塞。
select(Linux实现)低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善
epoll(Linux实现)、kqueue(FreeBSD实现)、/dev/poll(Solaris实现)是Reacor模式,IOCP是Proactor模式。
Apache 2.2.9之前只支持select模型,2.2.9之后支持epoll模型
Nginx 支持epoll模型
Java nio包是select模型
四、Apache Httpd的工作模式
4.1 apache三种工作模式
我们都知道Apache有三种工作模块,分别为prefork、worker、event。
- prefork:多进程,每个请求用一个进程响应,这个过程会用到select机制来通知。
- worker:多线程,一个进程可以生成多个线程,每个线程响应一个请求,但通知机制还是select不过可以接受更多的请求。
- event:基于异步I/O模型,一个进程或线程,每个进程或线程响应多个用户请求,它是基于事件驱动(也就是epoll机制)实现的。
4.2 prefork的工作原理
如果不用“--with-mpm”显式指定某种MPM,prefork就是Unix平台上缺省的MPM.它所采用的预派生子进程方式也是 Apache1.3中采用的模式。prefork本身并没有使用到线程,2.0版使用它是为了与1.3版保持兼容性;另一方面,prefork用单独的子 进程来处理不同的请求,进程之间是彼此独立的,这也使其成为最稳定的MPM之一。
4.3 worker的工作原理
相对于prefork,worker是2.0版中全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理,所以可以处理相对海量的请求,而 系统资源的开销要小于基于进程的服务器。但是,worker也使用了多进程,每个进程又生成多个线程,以获得基于进程服务器的稳定性,这种MPM的工作方 式将是Apache2.0的发展趋势。
4.4 event 基于事件机制的特性
一个进程响应多个用户请求,利用callback机制,让套接字复用,请求过来后进程并不处理请求,而是直接交由其他机制来处理,通过epoll机 制来通知请求是否完成;在这个过程中,进程本身一直处于空闲状态,可以一直接收用户请求。可以实现一个进程程响应多个用户请求。支持持海量并发连接数,消 耗更少的资源。
五、如何提高Web服务器的并发连接处理能力
有几个基本条件:
- 基于线程,即一个进程生成多个线程,每个线程响应用户的每个请求。
- 基于事件的模型,一个进程处理多个请求,并且通过epoll机制来通知用户请求完成。
- 基于磁盘的AIO(异步I/O)
- 支持mmap内存映射,mmap传统的web服务器,进行页面输入时,都是将磁盘的页面先输入到内核缓存中,再由内核缓存中复制一份到web服务 器上,mmap机制就是让内核缓存与磁盘进行映射,web服务器,直接复制页面内容即可。不需要先把磁盘的上的页面先输入到内核缓存去。
刚好,Nginx 支持以上所有特性。所以Nginx官网上说,Nginx支持50000并发,是有依据的。
六、Nginx优异之处
6.1 简介
传统上基于进程或线程模型架构的web服务通过每进程或每线程处理并发连接请求,这势必会在网络和I/O操作时产生阻塞,其另一个必然结果则是对内 存或CPU的利用率低下。生成一个新的进程/线程需要事先备好其运行时环境,这包括为其分配堆内存和栈内存,以及为其创建新的执行上下文等。这些操作都需 要占用CPU,而且过多的进程/线程还会带来线程抖动或频繁的上下文切换,系统性能也会由此进一步下降。另一种高性能web服务器/web服务器反向代 理:Nginx(Engine X),nginx的主要着眼点就是其高性能以及对物理计算资源的高密度利用,因此其采用了不同的架构模型。受启发于多种操作系统设计中基于“事件”的高级 处理机制,nginx采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。在nginx中,连接请求由为数不多的 几个仅包含一个线程的进程worker以高效的回环(run-loop)机制进行处理,而每个worker可以并行处理数千个的并发连接及请求。
6.2 Nginx 工作原理
Nginx会按需同时运行多个进程:一个主进程(master)和几个工作进程(worker),配置了缓存时还会有缓存加载器进程(cache loader)和缓存管理器进程(cache manager)等。所有进程均是仅含有一个线程,并主要通过“共享内存”的机制实现进程间通信。主进程以root用户身份运行,而worker、 cache loader和cache manager均应以非特权用户身份运行。
主进程主要完成如下工作
- 读取并验正配置信息;
- 创建、绑定及关闭套接字;
- 启动、终止及维护worker进程的个数;
- 无须中止服务而重新配置工作特性;
- 控制非中断式程序升级,启用新的二进制程序并在需要时回滚至老版本;
- 重新打开日志文件;
- 编译嵌入式perl脚本;
- worker进程主要完成的任务包括:
- 接收、传入并处理来自客户端的连接;
- 提供反向代理及过滤功能;
- nginx任何能完成的其它任务;
注:如果负载以CPU密集型应用为主,如SSL或压缩应用,则worker数应与CPU数相同;如果负载以IO密集型为主,如响应大量内容给客户端,则worker数应该为CPU个数的1.5或2倍。
6.3 Nginx 架构
Nginx的代码是由一个核心和一系列的模块组成, 核心主要用于提供Web Server的基本功能,以及Web和Mail反向代理的功能;还用于启用网络协议,创建必要的运行时环境以及确保不同的模块之间平滑地进行交互。不过, 大多跟协议相关的功能和某应用特有的功能都是由nginx的模块实现的。这些功能模块大致可以分为事件模块、阶段性处理器、输出过滤器、变量处理器、协 议、upstream和负载均衡几个类别,这些共同组成了nginx的http功能。事件模块主要用于提供OS独立的(不同操作系统的事件机制有所不同) 事件通知机制如kqueue或epoll等。协议模块则负责实现nginx通过http、tls/ssl、smtp、pop3以及imap与对应的客户端 建立会话。在Nginx内部,进程间的通信是通过模块的pipeline或chain实现的;换句话说,每一个功能或操作都由一个模块来实现。例如,压 缩、通过FastCGI或uwsgi协议与upstream服务器通信,以及与memcached建立会话等。
6.4 Nginx 基础功能
- 处理静态文件,索引文件以及自动索引;
- 反向代理加速(无缓存),简单的负载均衡和容错;
- FastCGI,简单的负载均衡和容错;
- 模块化的结构。过滤器包括gzipping, byte ranges, chunked responses, 以及 SSI-filter 。在SSI过滤器中,到同一个 proxy 或者 FastCGI 的多个子请求并发处理;
- SSL 和 TLS SNI 支持;
6.5 Nginx IMAP/POP3 代理服务功能
- 使用外部 HTTP 认证服务器重定向用户到 IMAP/POP3 后端;
- 使用外部 HTTP 认证服务器认证用户后连接重定向到内部的 SMTP 后端;
- 认证方法:
- POP3: POP3 USER/PASS, APOP, AUTH LOGIN PLAIN CRAM-MD5;
- IMAP: IMAP LOGIN;
- SMTP: AUTH LOGIN PLAIN CRAM-MD5;
- SSL 支持;
- 在 IMAP 和 POP3 模式下的 STARTTLS 和 STLS 支持;
6.6 Nginx 支持的操作系统
- FreeBSD 3.x, 4.x, 5.x, 6.x i386; FreeBSD 5.x, 6.x amd64;
- Linux 2.2, 2.4, 2.6 i386; Linux 2.6 amd64;
- Solaris 8 i386; Solaris 9 i386 and sun4u; Solaris 10 i386;
- MacOS X (10.4) PPC;
- Windows 编译版本支持 windows 系列操作系统;
6.7 Nginx 结构与扩展
- 一个主进程和多个工作进程,工作进程运行于非特权用户;
- kqueue (FreeBSD 4.1+), epoll (Linux 2.6+), rt signals (Linux 2.2.19+), /dev/poll (Solaris 7 11/99+), select, 以及 poll 支持;
- kqueue支持的不同功能包括 EV_CLEAR, EV_DISABLE (临时禁止事件), NOTE_LOWAT, EV_EOF, 有效数据的数目,错误代码;
- sendfile (FreeBSD 3.1+), sendfile (Linux 2.2+), sendfile64 (Linux 2.4.21+), 和 sendfilev (Solaris 8 7/01+) 支持;
- 输入过滤 (FreeBSD 4.1+) 以及 TCP_DEFER_ACCEPT (Linux 2.4+) 支持;
- 10,000 非活动的 HTTP keep-alive 连接仅需要 2.5M 内存。
- 最小化的数据拷贝操作;
6.8 Nginx 其他HTTP功能
- 基于IP 和名称的虚拟主机服务;
- Memcached 的 GET 接口;
- 支持 keep-alive 和管道连接;
- 灵活简单的配置;
- 重新配置和在线升级而无须中断客户的工作进程;
- 可定制的访问日志,日志写入缓存,以及快捷的日志回卷;
- 4xx-5xx 错误代码重定向;
- 基于 PCRE 的 rewrite 重写模块;
- 基于客户端 IP 地址和 HTTP 基本认证的访问控制;
- PUT, DELETE, 和 MKCOL 方法;
- 支持 FLV (Flash 视频);
- 带宽限制;
6.9 为什么选择Nginx
-
- 在高连接并发的情况下,Nginx是Apache服务器不错的替代品: Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一. 能够支持高达 50,000 个并发连接数的响应, 感谢Nginx为我们选择了 epoll and kqueue 作为开发模型。
- Nginx作为负载均衡服务器: Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务, 也可以支持作为 HTTP代理 服务器对外进行服务. Nginx采用C进行编写, 不论是系统资源开销还是CPU使用效率都比 Perlbal 要好很多。
- 作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器), Last.fm 描述了成功并且美妙的使用经验.
- Nginx 是一个 [#installation 安装] 非常的简单 , 配置文件 非常简洁(还能够支持perl语法),Bugs 非常少的服务器: Nginx 启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动. 你还能够 不间断服务的情况下进行软件版本的升级 。
- Nginx 的诞生主要解决C10K问题
Nginx教程
作者:Maxsu
Java技术QQ群:227270512
Linux QQ群:479429477
原文出自易百教程,原文链接: https://www.yiibai.com/nginx/
[TOC]
Nginx[读音:engine x
]是HTTP和反向代理服务器,邮件代理服务器,以及Igor Sysoev最初编写的通用TCP/UDP代理服务器。在很长一段时间以来,它一直在许多负载重的俄罗斯网站上运行,包括:Yandex,Mail.Ru,VK和Rambler。 根据Netcraft的说法,Nginx在2017年3月份服务或代理了28.50%
的最繁忙的网站。这里有一些成功案例:Netflix,Wordpress.com,FastMail.FM。
源代码和文档按照两条BSD类许可证分发。
商业支持可从Nginx,Inc.获得。
1.基本的HTTP服务器功能
- 提供静态和索引文件,自动索引; 打开文件描述符缓存;
- 加速反向代理与缓存; 负载均衡和容错;
- 通过缓存FastCGI,uwsgi,SCGI和memcached服务器来加速支持; 负载均衡和容错;
- 模块化架构。 过滤器包括gzip,字节范围,分块响应,XSLT,SSI和图像变换过滤器。 如果由代理或FastCGI/uwsgi/SCGI服务器处理,则单页内的多个SSI包含可以并行处理;
- SSL和TLS SNI支持;
- 支持具有加权和依赖关系优先级的HTTP/2。
2..其他HTTP服务器功能
- 基于名称和基于IP的虚拟服务器;
- 保持活动和管道连接的支持;
- 访问日志格式,缓冲日志写入,快速日志轮换和syslog日志记录;
- 3xx - 5xx 错误代码重定向;
- 重写模块:使用正则表达式更改URI;
- 根据客户端地址执行不同的功能;
- 根据客户端IP地址,密码(HTTP Basic认证)和子请求结果进行访问控制;
- HTTP引用的验证
- PUT,DELETE,MKCOL,COPY和MOVE方法;
- FLV和MP4流媒体;
- 响应速度限制;
- 限制来自一个地址的同时连接或请求的数量;
- 基于IP的地理定位;
- A/B测试;
- 嵌入式Perl
- nginScript。
3.邮件代理服务器功能
- 使用外部HTTP认证服务器将用户重定向到IMAP或POP3服务器;
- 使用外部HTTP认证服务器进行用户认证,并将连接重定向到内部SMTP服务器;
- 认证方式:
- POP3:USER / PASS,APOP,AUTH LOGIN / PLAIN / CRAM-MD5;
- IMAP:LOGIN,AUTH LOGIN / PLAIN / CRAM-MD5;
- SMTP:AUTH LOGIN / PLAIN / CRAM-MD5;
- SSL支持;
- STARTTLS和STLS支持。
4.TCP/UDP代理服务器功能
- TCP和UDP的通用代理;
- SSL和TLS SNI支持TCP;
- 负载均衡和容错;
- 基于客户地址的访问控制;
- 根据客户端地址执行不同的功能;
- 限制来自一个地址的同时连接数;
- 访问日志格式,缓冲日志写入,快速日志轮换和syslog日志记录;
- 基于IP的地理定位;
- A/B测试;
- nginScript。
5.架构和可扩展性
- 一个主和几个工作进程; 工作进程在非特权用户下运行;
- 灵活配置;
- 重新配置和升级可执行文件,而不会中断客户端服务;
- 支持kqueue(FreeBSD 4.1+),epoll(Linux 2.6+),/ dev / poll(Solaris 7 11/99 +),事件端口(Solaris 10),select和poll;
- 支持各种kqueue功能,包括EV_CLEAR,EV_DISABLE(临时禁用事件),NOTE_LOWAT,EV_EOF,可用数据数,错误代码;
- 支持各种epoll功能,包括EPOLLRDHUP(Linux 2.6.17+,glibc 2.8+)和EPOLLEXCLUSIVE(Linux 4.5+,glibc 2.24+);
- 支持sendfile(FreeBSD 3.1+,Linux 2.2+,macOS 10.5+),sendfile64(Linux 2.4.21+)和sendfilev(Solaris 8 7/01 +);
- 文件AIO(FreeBSD 4.3+,Linux 2.6.22+);
- DIRECTIO(FreeBSD 4.4+,Linux 2.4+,Solaris 2.6+,macOS);
- 接受过滤器(FreeBSD 4.1+,NetBSD 5.0+)和TCP_DEFER_ACCEPT(Linux 2.4+)支持;
- 10,000个不活动的HTTP保持连接大约需要
2.5M
内存; - 数据复制操作保持最小。
6.经测试的操作系统和平台
- FreeBSD 3 — 11 / i386; FreeBSD 5 — 11 / amd64;
- Linux 2.2 — 4 / i386; Linux 2.6 — 4 / amd64; Linux 3 — 4 / armv6l, armv7l, aarch64, ppc64le;
- Solaris 9 / i386, sun4u; Solaris 10 / i386, amd64, sun4v;
- AIX 7.1 / powerpc;
- HP-UX 11.31 / ia64;
- macOS / ppc, i386;
- Windows XP, Windows Server 2003.
Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性:
作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型.
作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。
作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。
Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在 不间断服务的情况下进行软件版本的升级。
7.Nginx特性
NGINX有什么不同? NGINX使用可扩展的事件驱动架构,而不是更传统的过程驱动架构。 这需要更低的内存占用,并且当并发连接扩大时,使内存使用更可预测。
在传统的Web服务器体系结构中,每个客户端连接作为一个单独的进程或线程处理,随着网站的流行度增加,并发连接数量的增加,Web服务器减慢,延迟了对用户的响应。
从技术的角度来看,产生一个单独的进程/线程需要将CPU切换到新的任务并创建一个新的运行时上下文,消耗额外的内存和CPU时间,从而对性能产生负面影响。
NGINX开发的目标是实现10
倍以上的性能,优化服务器资源的使用,同时也能够扩展和支持网站的动态增长。 因此,NGINX成为最知名的模块化,事件驱动,异步,单线程Web服务器和Web代理之一。
Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性:
作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型.
作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。
作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。
Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在 不间断服务的情况下进行软件版本的升级。
8.为什么需要Nginx?
当前信息时代,哪里都是应用程序。这些应用程序们不仅仅是运行人们工作场所的工具 - 它们现在正在经营人们的生活。 对即时响应的需求,完美的行为和更多的功能是前所未有的。 而且,当然,人们期望应用程序在不同类型的设备上运行平稳,特别是在移动设备上。 应用程序执行的速度与它所做的一样重要。
NGINX的核心功能,例如其具有高性能HTTP和反向代理服务器的大规模可扩展事件驱动架构,访问和带宽控制以及与各种应用程序高效集成的能力,有助于使其成为任何网站或服务需要性能,可扩展性和可靠性。
比如说,使用其它传统服务器软件,每个客户端连接作为一个单独的进程或线程处理,随着网站的流行度增加,并发连接数量的增加,Web服务器减慢,延迟了对用户的响应,到了最后实在撑不下去了,服务器软件响应不过来或死掉了,网站或应用程序也挂了。
所以说像NGINX这样一个可扩展性和可靠性的服务器软件,简单耐操,实在没有什么好的理由拒绝使用它。
9.Nginx的优势(优点)
处理高性能和高效率的并发一直是部署nginx的主要优势。现在我们来了解有关Nginx更多的优点。
在过去几年中,Web架构师已经接受了将应用程序基础架构与Web服务器分离和分离的想法。 然而,以前以LAMP(Linux,Apache,MySQL,PHP,Python或Perl)为基础的网站的形式可能不仅仅是一个基于LEMP的(“E”代表“Engine x”)) ,但是越来越多地将网络服务器推送到基础设施的边缘,并以不同的方式将相同或更新的一组应用程序和数据库工具集成在网络服务器周围。
nginx非常适合这一点,因为它提供了方便卸载并发,延迟处理,SSL(安全套接字层),静态内容,压缩和缓存,连接和请求限制所需的关键功能,甚至可以从应用程序中传输HTTP媒体流层到更有效的Web服务器层。 它还允许与memcached/Redis或其他“NoSQL”解决方案直接集成,以便在为大量并发用户服务时提高性能。
随着近来开发套件和编程语言的广泛使用,越来越多的公司正在改变其应用开发和部署习惯。 nginx已经成为这些变化范式中最重要的组成部分之一,它已经帮助许多公司快速启动和开发他们的网络服务。
nginx的第一行是在2002年写的。2004年,它根据BSD许可证的两个条款向公众发布。 nginx用户的数量一直在增长,他们提出了想法,并提交了对整个社区非常有益和有益的错误报告,建议和意见。
nginx代码库是原始的,并且是从头开始以C编程语言编写的。 nginx已被移植到许多架构和操作系统,包括Linux,FreeBSD,Solaris,Mac OS X,AIX和Microsoft Windows。 nginx拥有自己的库,其标准模块不会超出系统的C库,除了zlib,PCRE和OpenSSL之外,如果不需要,或者由于潜在的许可证冲突,可以选择将其从构建中排除。
关于Windows版本的nginx
当nginx在Windows环境中工作时,nginx的Windows版本更像是一个概念证明,而不是一个功能完整的端口。 在这个时候,nginx和Windows内核架构有一些不能很好地交互的局限性。 用于Windows的nginx版本的已知问题包括并发连接数量低得多,性能下降,无缓存,无带宽监管。 nginx for Windows的未来版本将更加紧密地匹配主流功能。
Nginx 是一个高性能的 Web 和反向代理服务器, 它具有有很多非常优越的特性:
作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应,感谢 Nginx 为我们选择了 epoll and kqueue 作为开发模型.
作为负载均衡服务器:Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。
作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器),Last.fm 描述了成功并且美妙的使用经验。
Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在 不间断服务的情况下进行软件版本的升级。
10.Nginx架构
处理并发连接的传统的基于进程或线程的模型涉及使用单独的进程或线程处理每个连接,并阻止网络或输入/输出操作。 根据应用,在内存和CPU消耗方面可能非常低效。 产生一个单独的进程或线程需要准备一个新的运行时环境,包括分配堆和堆栈内存,以及创建新的执行上下文。 额外的CPU时间也用于创建这些项目,这可能会导致由于线程在过多的上下文切换上的转机而导致性能下降。 所有这些并发症都表现在较老的Web服务器架构(如Apache)中。 这是提供丰富的一般应用功能和优化的服务器资源使用之间的一个折衷。
从一开始nginx就是一个专门的工具,可以实现更高性能,更密集和经济地使用服务器资源,同时实现网站的动态发展,所以它采用了不同的模式。 它实际上受到各种操作系统中高级事件机制的不断发展的启发。发展结果变成是一个模块化的,事件驱动的,异步的,单线程的非阻塞架构的nginx代码基础。
nginx大量使用复用和事件通知,并专门用于分离进程的特定任务。 连接在有限数量的单线程进程称为工作(worker
)的高效运行循环中处理。 在每个工作(worker
)中,nginx可以处理每秒数千个并发连接和请求。
11.代码结构
nginx工作(worker
)码包括核心和功能模块。 nginx的核心是负责维护严格的运行循环,并在请求处理的每个阶段执行模块代码的适当部分。 模块构成了大部分的演示和应用层功能。 模块读取和写入网络和存储,转换内容,执行出站过滤,应用服务器端包含操作,并在代理启动时将请求传递给上游服务器。
nginx的模块化架构通常允许开发人员扩展一组Web服务器功能,而无需修改nginx内核。 nginx模块略有不同,即核心模块,事件模块,阶段处理程序,协议,可变处理程序,过滤器,上游和负载平衡器。nginx不支持动态加载的模块; 即在构建阶段将模块与核心一起编译。
在处理与接受,处理和管理网络连接和内容检索相关的各种操作时,nginx在基于Linux,Solaris和BSD的操作系统中使用事件通知机制和一些磁盘I/O性能增强,如:kqueue,epoll, 和事件端口。 目标是为操作系统提供尽可能多的提示,以便及时获取入站和出站流量,磁盘操作,读取或写入套接字,超时等异步反馈。 对于每个基于Unix的nginx运行的操作系统,大量优化了复用和高级I/O操作的不同方法的使用。
nginx架构的高级概述如下图所示 -
12.工作模式
如前所述,nginx不会为每个连接生成一个进程或线程。 相反,工作(worker
)进程接受来自共享“listen”套接字的新请求,并在每个工作(worker
)内执行高效的运行循环,以处理每个工作(worker
)中的数千个连接。 没有专门的仲裁或分配与nginx工作(worker
)的联系; 这个工作(worker
)是由操作系统内核机制完成的。 启动后,将创建一组初始侦听套接字。 然后,工作(worker
)在处理HTTP请求和响应时不断接受,读取和写入套接字。
运行循环是nginx工作(worker
)代码中最复杂的部分。 它包括全面的内部调用,并且在很大程度上依赖异步任务处理的想法。 异步操作通过模块化,事件通知,广泛使用回调函数和微调定时器来实现。 总体而言,关键原则是尽可能不阻塞。 nginx仍然可以阻塞的唯一情况是工作(worker
)进程没有足够的磁盘存储。
由于nginx不会连接一个进程或线程,所以在绝大多数情况下,内存使用非常保守,非常有效。 nginx也节省CPU周期,因为进程或线程没有持续的创建 - 销毁模式。 nginx的作用是检查网络和存储的状态,初始化新连接,将其添加到运行循环中,并异步处理直到完成,此时连接被重新分配并从运行循环中删除。 结合仔细使用系统调用(syscall
)和精确实现支持接口(如pool
和slab
内存分配器),nginx通常可以在极端工作负载下实现中到低的CPU使用。
在一些磁盘使用和CPU负载模式,应调整nginx工作(worker
)的数量。 在这里说一点基础规则:系统管理员应该为其工作负载尝试几个配置。 一般建议可能如下:
如果负载模式是CPU密集型的,例如,处理大量TCP/IP,执行SSL或压缩,则nginx工作(worker
)的数量应与CPU内核数量相匹配;
如果负载大多是磁盘I/O绑定,例如,从存储或重代理服务不同的内容集合 - 工作(worker
)的数量可能是核心数量的一到两倍。有些工程师会根据个人存储单元的数量选择工作(worker
)的数量,但这种方法的效率取决于磁盘存储的类型和配置。
nginx的开发人员将在即将推出的版本中解决的一个主要问题是如何避免磁盘I/O上的大多数阻塞。 目前,如果没有足够的存储性能来提供特定工作(worker
)生成的磁盘操作,该工作(worker
)可能仍然阻止从磁盘读取/写入。 存在许多机制和配置文件指令来减轻此类磁盘I/O阻塞情况。要注意的是,诸如:sendfile和AIO之类的选项的组合通常会为磁盘性能带来很大的余量。 应该根据数据集,可用于nginx的内存量和底层存储架构来规划安装一个nginx服务器。
现有工作(worker
)模式的另一个问题是与嵌入式脚本的有限支持有关。 一个使用标准的nginx分发,只支持嵌入Perl脚本。一个简单的解释:关键问题是嵌入式脚本阻止任何操作或意外退出的可能性。 这两种类型的行为将立即导致工作(worker
)挂起的情况,同时影响到数千个连接。 更多的工作(worker
)计划是使nginx的嵌入式脚本更简单,更可靠,适用于更广泛的应用。
13.nginx进程角色
nginx在内存中运行多个进程; 有一个主进程和几个工作(worker
)进程。 还有一些特殊用途的过程,特别是缓存加载器和缓存管理器。 所有进程都是单线程版本为1.x
的nginx。 所有进程主要使用共享内存机制进行进程间通信。主进程作为root
用户运行。 缓存加载器,缓存管理器和工作(worker
)则以无权限用户运行。
主程序负责以下任务:
- 读取和验证配置
- 创建,绑定和关闭套接字
- 启动,终止和维护配置的工作(
worker
)进程数 - 重新配置,无需中断服务
- 控制不间断的二进制升级(如果需要,启动新的二进制并回滚)
- 重新打开日志文件
- 编译嵌入式Perl脚本
工作(worker
)进程接受,处理和处理来自客户端的连接,提供反向代理和过滤功能,并执行几乎所有其他的nginx能力。 关于监视nginx实例的行为,系统管理员应该关注工作(worker
)进程,因为它们是反映Web服务器实际日常操作的过程。
缓存加载器进程负责检查磁盘缓存项目,并使用缓存元数据填充nginx的内存数据库。 本质上,缓存加载器准备nginx实例来处理已经存储在磁盘上的特定分配的目录结构中的文件。 它遍历目录,检查缓存内容元数据,更新共享内存中的相关条目,然后在所有内容清洁并准备使用时退出。
缓存管理器主要负责缓存到期和无效。 在正常的nginx操作期间它保持在内存中,并且在失败的情况下由主进程重新启动。
14.nginx缓存简介
在nginx中的缓存以文件系统上的分层数据存储的形式实现。 缓存密钥是可配置的,并且可以使用不同的请求特定参数来控制进入缓存的内容。 缓存密钥和缓存元数据存储在共享存储器段中,高速缓存加载器,缓存管理器和工作(worker
)可以访问它们。 目前,除了操作系统的虚拟文件系统机制暗示的优化之外,没有任何内存中的文件缓存。 每个缓存的响应都放在文件系统上的不同文件中。 层次结构(级别和命名细节)通过nginx配置指令进行控制。 当响应写入缓存目录结构时,文件的路径和名称将从代理URL的MD5哈希导出。
将内容放置在缓存中的过程如下:当nginx从上游服务器读取响应时,内容首先写入缓存目录结构之外的临时文件。 当nginx完成处理请求时,它重命名临时文件并将其移动到缓存目录。 如果用于代理的临时文件目录位于另一个文件系统上,则该文件将被复制,因此建议将临时文件目录和缓存目录保存在同一文件系统上。 当需要显式清除缓存目录结构时,从文件中删除文件也是非常安全的。 nginx有第三方扩展,可以远程控制缓存的内容,还有更多的工作计划将此功能集成到主分发中。
15.Nginx安装
根据操作系统的不同,nginx可以安装也不太相同,安装nginx有以下几种不同的方式。
在Linux上安装
对于Linux,可以使用来自nginx.org的nginx软件包。参考网址:
在FreeBSD上安装
在FreeBSD上,可以从包或通过ports系统安装nginx。 端口系统提供更大的灵活性,允许在各种选项之间进行选择。 端口将使用指定的选项编译nginx并进行安装。
在Window上安装
先省略了,不要问为什么!
从源代码构建[推荐]
如果需要一些特殊的功能,在包和端口不可用的情况下,也可以从源代码编译来安装nginx。虽然源代码编译安装更灵活,但这种方法对于初学者来说可能很复杂(建议初学者自己使用源代码编译安装来安装nginx)。有关更多信息,请参阅从源构建nginx。
在本文中,主要介绍从源代码安装nginx,这篇教程是基于CentOS7 64bit
系统来安装的,非Centos系统不适用。现在我们就开始吧!
15.1.Nginx编译安装
15.1.1. 安装前工作
首先更新系统软件源,使用以下命令更新系统 -
yum update
有关两个命令的一点解释:
yum -y update
- 升级所有包,改变软件设置和系统设置,系统版本内核都升级
yum -y upgrade
- 升级所有包,不改变软件设置和系统设置,系统版本升级,内核不改变
依赖包安装
yum -y install gcc gcc-c++ autoconf automake libtool make cmake
yum -y install zlib zlib-devel openssl openssl-devel pcre-devel
15.1.2. 下载Nginx安装源文件
源码下载,可官网下载地址:http://nginx.org/en/download.html 下载并上传到服务器(这里选择最新稳定版本:nginx-1.10.3
)
或直接在服务上执行以下命令下载
cd /usr/local/src
wget -c http://nginx.org/download/nginx-1.10.3.tar.gz
tar zxvf nginx-1.10.3.tar.gz
在编译之前还要做一些前期的准备工作,如:依懒包安装,Nginx用户和用户组等。
15.1.3. 新建nginx用户及用户组
使用 root 用户身份登录系统,执行以下命令创建新的用户。
groupadd nginx
useradd -g nginx -M nginx
useradd
命令的-M
参数用于不为nginx
建立home
目录
修改/etc/passwd
,使得nginx
用户无法bash登陆(nginx用户后面由/bin/bash
改为/sbin/nologin
),
vi /etc/passwd
然后找到有 nginx 那一行,把它修改为(后面由/bin/bash
改为/sbin/nologin
):
nginx:x:1002:1003::/home/nginx:/sbin/nologin
15.1.4. 编译配置、编译、安装
下面我们进入解压的nginx源码目录:/usr/local/src/
执行以下命令 -
cd /usr/local/src/nginx*
pwd
/usr/local/src/nginx-1.10.3
./configure --prefix=/usr/local/nginx \
--pid-path=/usr/local/nginx/run/nginx.pid \
--with-http_ssl_module \
--user=nginx \
--group=nginx \
--with-pcre \
--without-mail_pop3_module \
--without-mail_imap_module \
--without-mail_smtp_module
注意:上面的反斜杠
\
表示换行继续。
--prefix=/usr/local/nginx
指定安装到 /usr/local/nginx
目录下。
上面配置完成后,接下来执行编译 -
make
make install
... ...
cp conf/nginx.conf '/usr/local/nginx/conf/nginx.conf.default'
上面编译时间跟你的电脑配置相关,所以可能需要一些等待时间。
查看安装后的程序版本:
/usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.10.3
修改Nginx默认端口(可选):
vi /usr/local/nginx/conf/nginx.conf
默认是 80 端口(http协议默认端口),可以改为其他端口
启动Nginx程序、查看进程
/usr/local/nginx/sbin/nginx
ps -ef | grep nginx
nginx停止、重启
未添加nginx服务前对nginx的管理只能通过一下方式管理:
# nginx 管理的几种方式
# 启动Nginx
/usr/local/nginx/sbin/nginx
# 从容停止Nginx:
kill -QUIT 主进程号 # 如上一步中的 ps 命令输出的 29151,就是 Nginx的主进程号
# 快速停止Nginx:
kill -TERM 主进程号
# 强制停止Nginx:
pkill -9 nginx
# 平滑重启nginx
/usr/nginx/sbin/nginx -s reload
现在我们来看看安装的Nginx的运行结果,可以简单地使用curl
命令访问localhost测试,结果如下
curl localhost
或者也可以打开浏览访问目标服务器的IP
提示: 如果没有看到以上界面,在确保Nginx启动的前提下,检查SeLinux和防火墙是否已关闭。关闭防火墙命令:systemctl stop firewalld.service
。
15.2.Nginx安装(从Linx包安装)
目前,nginx软件包可用于以下发行版和版本:
RHEL/CentOS:
版本 | 支持的平台 |
---|---|
5.x | x86_64, i386 |
6.x | x86_64, i386 |
7.x | x86_64, ppc64le |
Debian:
版本 | 代码名称(codename ) |
支持的平台 |
---|---|---|
7.x | wheezy | x86_64, i386 |
8.x | jessie | x86_64, i386 |
Ubuntu:
版本 | 代码名称(codename ) |
支持的平台 |
---|---|---|
12.04 | precise | x86_64, i386 |
14.04 | trusty | x86_64, i386, aarch64/arm64 |
16.04 | xenial | x86_64, i386, ppc64el |
16.10 | yakkety | x86_64, i386 |
SLES:
版本 | 支持的平台 |
---|---|
12 | x86_64 |
要实现Linux软件包的自动更新,可以为RHEL/CentOS发行版设置yum
存储库,Debian/Ubuntu
发行版的apt
存储库,以及SLES的zypper
存储库。
在本文中,我们重点以Debian/Ubuntu
发行版的apt
存储库作为一个演示,并在Ubuntu
系统上安装Nginx。
15.2.1. 用于稳定版本的预构建软件包
15.2.1.1.RHEL/CentOS系统平台
要设置RHEL/CentOS
的yum存储库,需要创建一个名称为/etc/yum.repos.d/nginx.repo
的文件,其中包含以下内容:
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/{OS}/{OSRELEASE}/$basearch/
gpgcheck=0
enabled=1
根据所使用的分配,将“OS
”替换为“rhel
”或“centos
”,对于5.x
,6.x
或7.x
,请将“OSRELEASE
”替换为“5
”,“6
”或“7
” 版本。
有关于如何查看系统版本 -
lsb_release -a
bash:lsb_release: command not found
yum install lsb –y
lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch:cxx-4.1-amd64:cxx-4.1-noarch:desktop-4.1-amd64:desktop-4.1-noarch:languages-4.1-amd64:languages-4.1-noarch:printing-4.1-amd64:printing-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.3.1611 (Core)
Release: 7.3.1611
Codename: Core
第二种方法:
cat /etc/redhat-release
15.2.1.2. Debian/Ubuntu系统平台
对于Debian/Ubuntu,为了验证nginx存储库签名,并且在安装nginx软件包时消除关于缺少PGP密钥的警告,必须将用于将nginx软件包和存储库签署的密钥添加到apt
程序密钥环中。 请从Nginx官方网站下载密钥:http://nginx.org/keys/nginx_signing.key , 并使用以下命令将其添加到apt
程序密钥环:
sudo apt-key add nginx_signing.key
Debian系统则将Debian代码替换为Debian发行版代码(codename
),并将以下内容附加到/etc/apt/sources.list
文件的末尾:
deb http://nginx.org/packages/debian/ codename nginx
deb-src http://nginx.org/packages/debian/ codename nginx
对于Ubuntu将Ubuntu发行版代号替换codename
,并将以下内容附加到/etc/apt/sources.list
文件的末尾:
deb http://nginx.org/packages/ubuntu/ codename nginx
deb-src http://nginx.org/packages/ubuntu/ codename nginx
对于Debian / Ubuntu,请运行以下命令:
apt-get update
apt-get install nginx
15.2.1.3. SLES系统平台
对于SLES,运行以下命令:
zypper addrepo -G -t yum -c 'http://nginx.org/packages/sles/12' nginx
15.2.2. 源码包
包源码包可以在包源码源码库中找到: http://hg.nginx.org/pkg-oss?_ga=1.85593177.1509956953.1490042234 。
默认分支保存当前主线版本的包源码,而stable-*
分支则用于稳定版本的最新的源码包。 要构建二进制包,可在Debian/Ubuntu
上的debian/
目录中或在RHEL/CentOS/SLES
上的rpm/SPECS/
中运行make
命令。
包源码分布在与nginx相同的2
条BSD类许可证下。
15.2.3. Ubuntu Server安装Nginx实例
对于Debian/Ubuntu,为了验证nginx存储库签名,并且在安装nginx软件包时消除关于缺少PGP密钥的警告,必须将用于将nginx软件包和存储库签署的密钥添加到apt
程序密钥环中。 请从Nginx官方网站下载密钥:http://nginx.org/keys/nginx_signing.key , 并使用以下命令将其添加到apt
程序密钥环:
wget -c http://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.key
查看 Ubuntu发行版代号,使用以下命令
sudo lsb_release -a
Ubuntu将Ubuntu发行版代号替换codename
,并将以下两行内容附加到/etc/apt/sources.list
文件的末尾:
deb http://nginx.org/packages/ubuntu/ xenial nginx
deb-src http://nginx.org/packages/ubuntu/ xenial nginx
现在,可以运行下面命令来安装nginx了:
sudo apt-get update
sudo apt-get install nginx
配置文件默认会被安装到: /etc/nginx
目录下
1. 启动 Nginx 测试
sudo /etc/init.d/nginx start
2. 查询nginx进程
yiibai@ubuntu:~$ ps -ef | grep nginx
上面输出结果中,master
就代表该进程是nginx的主进程,它的进程ID是:9933
。
3. 停止nginx
要停止Nginx,可以使用以下命令 -
kill -QUIT 主进程号
本例中就是 : kill -QUIT 9933
当然还有通用的停止进程的命令,那就是暴力停止了。
kill -9 进程号
kill一个进程,在查询一下进程是否还存在,一个个的kill,全部kill完就可以了。
4. 测试nginx服务
打开浏览器或或在终端上使用 curl localhost
访问目标服务器。
15.2.4. Nginx从源码构建安装配置
使用configure
命令配置构建。 它定义了系统的各个方面,包括允许使用nginx进行连接处理的方法。 最后它创建一个Makefile
。 configure
命令支持以下参数:
--prefix = path
- 定义将保留服务器文件的目录。 这个同一个目录也将用于由configure
(除了库源的路径)和nginx.conf
配置文件中设置的所有相关路径。 它默认设置为/usr/local/nginx
目录。--sbin-path = path
- 设置nginx可执行文件的名称。此名称仅在安装期间使用。默认情况下文件名为prefix/sbin/nginx
。--conf-path = path
- 设置nginx.conf
配置文件的名称。 如果需要,nginx可以始终使用不同的配置文件启动,方法是在命令行参数-c file
指定。 默认情况下,该文件名为:prefix/conf/nginx.conf
。--pid-path = path
- 设置将存储主进程的进程ID的nginx.pid
文件的名称。 安装后,可以使用pid指令在nginx.conf
配置文件中更改文件名。 默认情况下,文件名为:prefix/logs/nginx.pid
。--error-log-path = path
- 设置主错误,警告和诊断文件的名称。 安装后,可以在nginx.conf
配置文件中使用error_log
指令更改文件名。 默认情况下,文件名为:prefix/logs/error.log
。--http-log-path = path
- 设置HTTP服务器主要请求日志文件的名称。 安装后,可以使用access_log
指令在nginx.conf
配置文件中更改文件名。 默认情况下,文件名为:prefix/logs/access.log
。--build = name
- 设置一个可选的nginx构建名称。--user = name
- 设置非特权用户的名称,该用户的凭据将由工作进程使用。 安装后,可以使用user
指令在nginx.conf
配置文件中更改名称。 默认的用户名是:nobody
。--group = name
- 设置由工作进程使用其凭据的组的名称。 安装后,可以使用user
指令在nginx.conf
配置文件中更改名称。 默认情况下,组名称设置为非特权用户的名称。--with-select_module
和--without-select_module
— 启用或禁用构建允许服务器使用select()
方法的模块。 如果平台似乎不支持更合适的方法(如kqueue
,epoll
或/dev/poll
),则会自动构建该模块。--with-poll_module
和--without-poll_module
— 启用或禁用构建允许服务器使用poll()
方法的模块。 如果平台似乎不支持更合适的方法(如kqueue
,epoll
或/dev/poll
),则会自动构建该模块。--without-http_gzip_module
- 禁用构建压缩HTTP服务器响应的模块。 需要zlib
库来构建和运行此模块。--without-http_rewrite_module
- 禁用构建一个允许HTTP服务器重定向请求并更改请求URI的模块。 需要PCRE库来构建和运行此模块。--without-http_proxy_module
- 禁用构建HTTP服务器代理模块。--with-http_ssl_module
- 可以构建一个将HTTPS协议支持添加到HTTP服务器的模块。 默认情况下不构建此模块。 OpenSSL库是构建和运行该模块所必需的。--with-pcre = path
- 设置PCRE库源的路径。库发行版(4.4 - 8.40版)需要从PCRE站点下载并提取。 其余的由nginx的./configure
和make
完成。 该库是location
指令和ngx_http_rewrite_module
模块中正则表达式支持所必需的。--with-pcre-jit
- 使用“即时编译”支持构建PCRE库。--with-zlib = path
- 设置zlib库的源路径。 库分发(版本1.1.3 - 1.2.11)需要从zlib站点下载并提取。 其余的由nginx的./configure
和make
完成。 该库是ngx_http_gzip_module
模块所必需的。--with-cc-opt = parameters
- 设置将添加到CFLAGS变量的其他参数。 在FreeBSD下使用系统PCRE库时,应指定--with-cc-opt="-I /usr/local/include"
。 如果需要增加select()所支持的文件数,那么也可以在这里指定,如:--with-cc-opt="-D FD_SETSIZE=2048"
。--with-ld-opt = parameters
- 设置链接过程中使用的其他参数。 当在FreeBSD下使用系统PCRE库时,应指定--with-ld-opt="-L /usr/local/lib"
。
参数使用示例(所有这些都需要在一行中完成):
./configure
--sbin-path=/usr/local/nginx/nginx
--conf-path=/usr/local/nginx/nginx.conf
--pid-path=/usr/local/nginx/nginx.pid
--with-http_ssl_module
--with-pcre=../pcre-8.40
--with-zlib=../zlib-1.2.11
配置完成后,使用make
编译和安装nginx。
16.Nginx快速入门
本文主要介绍nginx的基本配置和操作,并介绍了一些可以完成的简单任务。假设您已经学习过并已经安装好了nginx服务器。 如果没有,请参阅安装nginx页面(http://www.yiibai.com/nginx/nginx-install.html )。 本指南介绍如何启动和停止nginx,并重新加载其配置,解释配置文件的结构,并介绍如何设置nginx以提供静态内容,如何配置nginx作为代理服务器,以及如何将其连接到 一个FastCGI应用程序。
nginx有一个主进程和几个工作进程。 主进程的主要目的是读取和评估配置,并维护工作进程。 工作进程对请求进行实际处理。 nginx采用基于事件的模型和依赖于操作系统的机制来有效地在工作进程之间分配请求。 工作进程的数量可在配置文件中定义,并且可以针对给定的配置进行修改,或者自动调整到可用CPU内核的数量(请参阅worker_processes)。
在配置文件中确定nginx及其模块的工作方式。 默认情况下,配置文件名为nginx.conf
,并放在目录:/usr/local/nginx/conf
, /etc/nginx
, 或 /usr/local/etc/nginx
中。
在前面安装文章配置中,使用的安装配置目录是:/usr/local/nginx/conf
。所以可以在这个目录下找到这个配置文件。
16.1. 启动,停止和重新加载Nginx配置
要启动nginx,请运行可执行文件。 当nginx启动后,可以通过使用-s
参数调用可执行文件来控制它。 使用以下语法:
nginx -s signal
信号(signal
)的值可能是以下之一:
stop
- 快速关闭服务quit
- 正常关闭服务reload
- 重新加载配置文件reopen
- 重新打开日志文件
例如,要通过等待工作进程完成服务当前请求来停止nginx
进程,可以执行以下命令:
nginx -s quit
注:该命令应该在启动nginx的同一用户下执行。
在将重新配置命令的命令发送到nginx或重新启动之前,配置文件中的更改将不会被应用。 要重新加载配置文件,请执行:
nginx -s reload
当主进程收到要重新加载配置的信号,它将检查新配置文件的语法有效性,并尝试应用其中提供的配置。 如果这是成功的,主进程将启动新的工作进程,并向旧的工作进程发送消息,请求它们关闭。 否则,主进程回滚更改,并继续使用旧配置。 老工作进程,接收关闭命令,停止接受新连接,并继续维护当前请求,直到所有这些请求得到维护。 之后,旧的工作进程退出。
还可以借助Unix工具(如kill utility)将信号发送到nginx进程。 在这种情况下,信号直接发送到具有给定进程ID的进程。 默认情况下,nginx主进程的进程ID写入目录/usr/local/nginx/logs
或/var/run
中的nginx.pid。 例如,如果主进程ID为1628
,则发送QUIT信号导致nginx的正常关闭,请执行:
kill -s QUIT 1628
要获取所有运行的nginx进程的列表,可以使用ps
命令,例如,以下列方式:
ps -ax | grep nginx
16.2. 配置文件的结构
nginx由配置文件中指定的指令控制的模块组成。 指令分为简单指令和块指令。 一个简单的指令由空格分隔的名称和参数组成,并以分号(;
)结尾。 块指令具有与简单指令相同的结构,但不是以分号结尾,而是以大括号({
和}
)包围的一组附加指令结束。 如果块指令可以在大括号内部有其他指令,则称为上下文(例如:events
,http
,server
和location
)。
配置文件中放置在任何上下文之外的伪指令都被认为是主上下文。 events
和http
指令驻留在主上下文中,server
在http
中的,而location
在http
块中。
#
号之后的一行的部分被视为注释。
16.3. 提供静态内容服务(静态网站)
一个重要的Web服务器任务是提供文件(如图像或静态HTML页面)。这里我们来学习如何实现一个示例,根据请求,文件将从不同的本地目录提供:/data/www
(可能包含HTML文件)和/ data/images
(包含图像)。这将需要编辑配置文件,并使用两个位置块在http块内设置服务器块。
首先,创建/data/www
目录,并将一个包含任何文本内容的index.html
文件放入其中,并创建/data/images
目录并在其中放置一些图像。创建两个目录 -
[root@localhost ~]# mkdir -p /data/www
[root@localhost ~]# mkdir -p /data/images
[root@localhost ~]#
分别在上面创建的两个目录中放入两个文件:/data/www/index.html
和 /data/images/logo.png
,/data/www/index.html
文件的内容就一行,如下 -
<h2> New Static WebSite Demo.</h2>
接下来,打开配置文件(/usr/local/nginx/conf/nginx.conf
)。 默认的配置文件已经包含了服务器块的几个示例,大部分是注释掉的。 现在注释掉所有这样的块,并启动一个新的服务器块:
http {
server {
}
}
通常,配置文件可以包括服务器监听的端口和服务器名称区分的几个server
块。当nginx决定哪个服务器处理请求后,它会根据服务器块内部定义的location
指令的参数测试请求头中指定的URI。
将以下location
块添加到服务器(server
)块:
http {
server {
location / {
root /data/www;
}
}
}
该location
块指定与请求中的URI相比较的“/
”前缀。 对于匹配请求,URI将被添加到root
指令中指定的路径(即/data/www
),以形成本地文件系统上所请求文件的路径。 如果有几个匹配的location
块,nginx将选择具有最长前缀来匹配location
块。 上面的location
块提供最短的前缀长度为1
,因此只有当所有其他location
块不能提供匹配时,才会使用该块。
接下来,添加第二个location
块:
http {
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
}
它将是以/images/
(位置/
也匹配这样的请求,但具有较短前缀,也就是“/images/
”比“/
”长)的请求来匹配。
server
块的最终配置应如下所示:
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
这已经是一个在标准端口80
上侦听并且可以在本地机器上访问的服务器( http://localhost/
)的工作配置。 响应以/images/
开头的URI的请求,服务器将从/data/images
目录发送文件。 例如,响应http://localhost/images/logo.png
请求,nginx将发送服务上的/data/images/logo.png
文件。 如果文件不存在,nginx将发送一个指示404
错误的响应。 不以/images/
开头的URI的请求将映射到/data/www
目录。 例如,响应http://localhost/about/example.html
请求时,nginx将发送/data/www/about/example.html
文件。
要应用新配置,如果尚未启动nginx或者通过执行以下命令将重载信号发送到nginx的主进程:
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload
如果错误或异常导致无法正常工作,可以尝试查看目录
/usr/local/nginx/logs
或/var/log/nginx
中的access.log
和error.log
文件中查找原因。
完整的nginx.conf
文件配置内容如下:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include 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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
## 新服务(静态网站)
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
}
16.4. 设置简单的代理服务器
nginx的一个常见用途是将其设置为代理服务器,这意味着它可作为一个接收请求的服务器,将其传递给代理服务器,从代理服务器中检索响应,并将其发送给客户端。
我们将配置一个基本的代理服务器,它为来自本地目录的文件提供图像请求,并将所有其他请求发送到代理的服务器。 在此示例中,两个服务器将在单个nginx
实例上定义。
首先,通过向nginx配置文件添加一个server
块来定义代理服务器,其中包含以下内容:
server {
listen 8080;
root /data/up1;
location / {
}
}
这将是一个监听端口8080
的简单服务器(以前,由于使用了标准端口80
,所以没有指定listen
指令),并将所有请求映射到本地文件系统上的/data/up1
目录。 创建此目录并将index.html
文件放入其中。 请注意,root
指令位于server
块上下文中。 当选择用于服务请求的location
块不包含自己的root
指令时,将使用此root
指令。
在上面创建的目录/data/up1
中放入一个文件:/data/www/demo.html
,文件的内容就一行,如下 -
<h2>About proxy_pass Page at port 8080</h2>
接下来,使用上一节中的服务器配置进行修改,使其成为代理服务器配置。 在第一个位置块中,将proxy_pass
指令与参数中指定的代理服务器的协议,名称和端口(在本例中为http://localhost:8080
):
server {
location / {
proxy_pass http://localhost:8080;
}
location /images/ {
root /data;
}
}
我们将修改当前使用/images/prefix
将请求映射到/data/images
目录下的文件的第二个location
块,使其与典型文件扩展名的图像请求相匹配。 修改后的位置块如下所示:
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
该参数是一个正则表达式,匹配所有以.gif
,.jpg
或.png
结尾的URI。正则表达式之前应该是~
字符。 相应的请求将映射到/data/images
目录。
当nginx选择一个location
块来提供请求时,它首先检查指定前缀的location
指令,记住具有最长前缀的location
,然后检查正则表达式。 如果与正则表达式匹配,nginx会选择此location
,否则选择之前记住的那一个。
代理服务器的最终配置将如下所示:
server {
location / {
proxy_pass http://localhost:8080/;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
此服务器将过滤以.gif
,.jpg
或.png
结尾的请求,并将它们映射到/data/images
目录(通过向root
指令的参数添加URI),并将所有其他请求传递到上面配置的代理服务器。
要应用新配置,如果尚未启动nginx或者通过执行以下命令将重载信号发送到nginx的主进程:
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload
首先测试上面配置的 8080
端口的服务,访问服务的8080
端口
再次访问 80
端口(这里只是一个代理,它会把请求转发给8080
的服务,由8080
端口这这个服务处理并返回结果到客户端)。
完整的配置nginx.conf
文件内容如下 -
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include 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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
## 新服务(服务处理)
server {
listen 8080;
root /data/up1;
location / {
}
}
## 代理配置,数据转发
server {
location / {
proxy_pass http://localhost:8080/;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
}
16.5. 设置FastCGI代理
nginx可用于将请求路由到运行使用各种框架和PHP等编程语言构建的应用程序的FastCGI服务器。
使用FastCGI服务器的最基本nginx配置包括使用fastcgi_pass
指令(而不是proxy_pass
指令),以及fastcgi_param
指令来设置传递给FastCGI
服务器的参数。 假设FastCGI
服务器可以在localhost:9000
上访问。 以上一节的代理配置为基础,用fastcgi_pass
指令替换proxy_pass
指令,并将参数更改为localhost:9000
。 在PHP中,SCRIPT_FILENAME
参数用于确定脚本名称,QUERY_STRING
参数用于传递请求参数。 最终的配置将是:
server {
location / {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
}
location ~ \.(gif|jpg|png)$ {
root /data/images;
}
}
这将设置一个服务器,将除静态图像请求之外的所有请求路由到通过FastCGI协议在localhost:9000
上运行的代理服务器。
有关Nginx+PHP+FastCGI
服务器,我们将在单独的一篇文章:LANM安装和配置中讲解,请从左侧菜单中查看文章标题进入。
17. Nginx进程和运行时控制
本节介绍NGINX在运行时启动的过程以及如何控制它们。
在这个部分中,主要涉及两个部分的内容:
- 主进程和工作进程
- 控制NGINX
17.主进程和工作进程
NGINX有一个主进程和一个或多个工作进程。 如果启用缓存,缓存加载程序和缓存管理器进程也将在启动时运行。
主程序的主要目的是读取和评估配置文件以及维护工作进程。
工作进程执行请求的实际处理。 NGINX依赖于操作系统的机制来有效地在工作进程之间分配请求。 工作进程的数量可在nginx.conf
配置文件中定义,可以针对给定的配置进行修复,或者自动调整为可用CPU内核数(请参阅worker_processes)。
18.控制NGINX
要重新加载配置文件,可以停止或重新启动NGINX,或者发送信号到主进程。 可以使用-s
参数运行nginx命令(调用NGINX可执行文件)来发送信号。
nginx -s signal
信号的值可以是以下之一:
quit
– 正常地关闭reload
– 重新加载配置文件reopen
– 重新打开日志文件stop
– 立即关闭(快速关闭)
杀死实用程序也可以使用,将信号直接发送到主进程。 默认情况下,主进程的进程ID被写入位于/usr/local/nginx/logs
或/var/run
目录中的nginx.pid
文件。
nginx可以用信号控制。 默认情况下,主进程的进程ID将写入文件/usr/local/nginx/logs/nginx.pid
。 该名称可能在配置时更改,或使用pid
指令在nginx.conf
文件中进行更改。主程序支持以下信号:
TERM
,INT
- 快速关闭QUIT
- 正常关闭HUP
- 改变配置,跟上改变的时区(仅适用于FreeBSD和Linux),使用新配置启动新的工作进程,正常关闭旧的工作进程USR1
- 重新打开日志文件USR2
- 升级可执行文件WINCH
- 正常关闭工作进程
个别工作进程可以用信号来控制,尽管这不是必需的。 支持的信号有:
- TERM, INT - 快速关闭
- QUIT - 正常关闭
- USR1 - 重新打开日志文件
- WINCH - 调试异常终止(需要启用
debug_points
)
更改配置
为了使nginx重新读取配置文件,应将HUP信号发送到主进程。 主进程首先检查语法有效性,然后尝试应用新配置,即打开日志文件和新的监听套接字。 如果失败,它会回滚更改,并继续使用旧配置。 如果此操作成功,它将启动新的工作进程,并向旧的工作进程发送消息,请求它们正常关闭。 旧工作进程密切监听套接字,并继续为旧客户端服务。 在所有客户端被服务之后,旧的工作进程被关闭。
我们来举例说明一下。 想象一下,nginx是在FreeBSD 4.x上运行,执行以下命令:
ps axw -o pid,ppid,user,%cpu,vsz,wchan,command | egrep '(nginx|PID)'
产生以下输出:
PID PPID USER %CPU VSZ WCHAN COMMAND
33126 1 root 0.0 1148 pause nginx: master process /usr/local/nginx/sbin/nginx
33127 33126 nobody 0.0 1380 kqread nginx: worker process (nginx)
33128 33126 nobody 0.0 1364 kqread nginx: worker process (nginx)
33129 33126 nobody 0.0 1364 kqread nginx: worker process (nginx)
如果将HUP发送到主进程,则输出变为:
PID PPID USER %CPU VSZ WCHAN COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33129 33126 nobody 0.0 1380 kqread nginx: worker process is shutting down (nginx)
33134 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33135 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33136 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
PID 33129
的老工作流程仍然继续运行。 一段时间后,它退出:
PID PPID USER %CPU VSZ WCHAN COMMAND
33126 1 root 0.0 1164 pause nginx: master process /usr/local/nginx/sbin/nginx
33134 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33135 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
33136 33126 nobody 0.0 1368 kqread nginx: worker process (nginx)
循环日志文件
要循环日志文件,需要首先重命名。 之后,USR1信号应发送到主进程。 然后,主进程将重新打开所有当前打开的日志文件,并将其分配给正在运行的工作进程的非特权用户作为所有者。 成功重新打开后,主程序关闭所有打开的文件,并将消息发送到工作进程,要求他们重新打开文件。 工作进程也会打开新文件并立即关闭旧文件。 因此,旧文件几乎立即可用于后处理,如压缩。
19.Nginx配置文件
NGINX与其他服务类似,因为它具有以特定格式编写的基于文本的配置文件。 默认情况下,文件名为nginx.conf
并放在/etc/nginx
目录中(对于开源NGINX产品,位置取决于用于安装NGINX和操作系统的软件包系统,它通常位于/usr/local/nginx/conf/etc/nginx
或/usr/local/etc/nginx
。)
配置文件由指令及其参数组成。 简单(单行)指令各自以分号结尾。 其他指令作为“容器”,将相关指令组合在一起,将其包围在花括号({}
)中。 以下是简单指令的一些示例。
user nobody;
error_log logs/error.log notice;
worker_processes 1;
为了使配置更易于维护,建议您将其拆分为存储在/etc/nginx/conf.d
目录中的一组功能特定文件,并在主nginx.conf
文件中使用include
指令引用(包函)指定文件的内容。如下所示 -
include conf.d/http;
include conf.d/stream;
include conf.d/exchange-enhanced;
几个顶级指令(称为上下文)将适用于不同流量类型的指令组合在一起:
指定在这些上下文之外的指令是在主上下文中。
在每个流量处理上下文中,可包括一个或多个服务器上下文来定义控制请求处理的虚拟服务器。 您可以在服务器环境中包含的指令根据流量类型而有所不同。
对于HTTP流量(http上下文),每个服务器指令控制对特定域或IP地址上的资源请求的处理。 服务器上下文中的一个或多个位置上下文定义了如何处理特定的URI集合。
对于邮件和TCP流量(mail
和 stream
上下文),服务器指令各自控制到达特定TCP端口或UNIX套接字的流量处理。
以下配置说明了上下文的使用情况。
user nobody; # a directive in the 'main' context
events {
# configuration of connection processing
}
http {
# Configuration specific to HTTP and affecting all virtual servers
server {
# configuration of HTTP virtual server 1
location /one {
# configuration for processing URIs with '/one'
}
location /two {
# configuration for processing URIs with '/two'
}
}
server {
# configuration of HTTP virtual server 2
}
}
stream {
# Configuration specific to TCP and affecting all virtual servers
server {
# configuration of TCP virtual server 1
}
}
对于大多数指令,在另一个上下文(子上下文)中定义的上下文将继承父级中包含的伪指令的值。 要覆盖从父进程继承的值,请在子上下文中包含该指令。 有关上下文遗留的更多信息,请参阅proxy_set_header伪指令的文档。
要更改配置文件才能生效,NGINX必须重新加载该文件。可以重新启动nginx进程或发送reload
信号来升级配置,而不会中断当前请求的处理。
20.Nginx配置Web服务器
本文介绍如何将NGINX配置作为Web服务器,并包括以下部分:
- 设置虚拟服务器
- 配置位置
- 使用变量
- 返回特定状态码
- 重写请求中的URI
- 重写HTTP响应
- 处理错误
在高层次上,将NGINX配置作为Web服务器有一些问题需要了解,定义它处理哪些URL以及如何处理这些URL上的资源的HTTP请求。 在较低层次上,配置定义了一组控制对特定域或IP地址的请求的处理的虚拟服务器。
用于HTTP流量的每个虚拟服务器定义了称为位置的特殊配置实例,它们控制特定URI集合的处理。 每个位置定义了自己的映射到此位置的请求发生的情况。 NGINX可以完全控制这个过程。 每个位置都可以代理请求或返回一个文件。 此外,可以修改URI,以便将请求重定向到另一个位置或虚拟服务器。 此外,可以返回特定的错误代码,也可以配置特定的页面以对应于每个错误代码。
20.1. 设置虚拟服务器
NGINX配置文件必须至少包含一个服务器指令来定义虚拟服务器。 当NGINX处理请求时,它首先选择提供请求的虚拟服务器。
虚拟服务器由http
上下文中的服务器指令定义,例如:
http {
server {
# Server configuration
}
}
可以将多个server
指令添加到http
上下文中以定义多个虚拟服务器。
server
配置块通常包括一个listen
指令,用于指定服务器侦听请求的IP地址和端口(或Unix域套接字和路径)。IPv4和IPv6地址均被接受。
下面的示例显示了监听IP地址127.0.0.1
和端口8080
的服务器的配置:
server {
listen 127.0.0.1:8080;
# The rest of server configuration
}
如果省略端口,则使用标准端口。 同样地,如果省略一个地址,服务器将侦听所有地址。 如果没有包含listen指令,则“标准”端口为80/tcp
,“default”端口为8000/tcp
,具体取决于超级用户权限。
如果有多个服务器与请求的IP地址和端口相匹配,则NGINX将根据服务器块中的server_name
指令测试请求的主机头域。 server_name
的参数可以是完整(精确)名称,通配符或正则表达式。 通配符是一个字符串,其开头,结尾或两者都包含星号(*
); 星号匹配任何字符序列。 NGINX将Perl语法用于正则表达式; 在它们之前使用波浪号(〜
)。 此示例说明了一个确切的名称。
server {
listen 80;
server_name example.org www.example.org;
...
}
如果匹配主机头几个名称,则NGINX通过按以下顺序搜索名称并使用其找到的第一个匹配来选择一个:
- 确切的名字(完整准确的名称)
- 以星号开头的最长通配符,例如:
*.example.org
- 以星号结尾的最长通配符,如:
mail.*
- 第一个匹配正则表达式(按照出现在配置文件中的顺序)
如果主机头字段与服务器名称不匹配,则NGINX会将请求路由到请求到达端口的默认服务器。 默认服务器是nginx.conf
文件中列出的第一个服务器,除非您将listen_server
参数包含在listen
指令中以明确指定服务器为默认值。
server {
listen 80 default_server;
...
}
一个完整的Nginx虚拟机配置示例,这里我们演示配置两个虚拟机,对应域名分别为:vhost1.com
和 vhost2.com
,vhost1.com
网站的主目录在/data/www/vhost1
,vhost2.com
网站的主目录在/data/www/vhost2
:
server {
listen 80;
server_name vhost1.com www.vhost1.com;
index index.html index.html;
root /data/www/vhost1;
access_log /var/log/vhost1.com.log;
}
server {
listen 80;
server_name vhost2.com www.vhost2.com;
index index.html index.html;
root /data/www/vhost2;
access_log /var/log/vhost2.com.log;
}
20.2. 配置位置(location)
NGINX可以根据请求URI向不同的代理发送流量或提供不同的文件。 这些块是使用放置在server
指令中的location
指令来定义的。
例如,您可以定义三个location
块,以指示虚拟服务器向一个代理服务器发送一些请求,将其他请求发送到不同的代理服务器,并通过从本地文件系统传递文件来提供其余请求。
NGINX测试根据所有location
指令的参数请求URI,并应用匹配location
中定义的指令。 在每个location
块内,通常可能(除了一些例外)放置更多的location
指令以进一步细化特定组请求的处理。
注意:在本教程文章中,单词
location
是指单个location
上下文。
location
指令有两种类型的参数:前缀字符串(路径名)和正则表达式。 对于要匹配前缀字符串的请求URI,必须以前缀字符串开头。
具有pathname
参数的以下示例位置匹配以/some/path/
开头的请求URI,例如/some/path/document.html
,它不匹配/my-site/some/path
,因为/some/path
不在该URI的开头出现。
location /some/path/ {
...
}
正则表达式之前是区分大小写匹配的波形符号(~
),或者不区分大小写匹配的波形符号(~*
)。 以下示例将包含字符串.html
或.html
的URI与任何位置相匹配。
location ~ \.html? {
...
}
要找到最符合URI的位置,NGINX首先将URI与前缀字符串的位置进行比较。然后用正则表达式搜索位置。
除非使用^~
修饰符对正则表达式给予更高的优先级。在前缀字符串中,NGINX选择最具体的字符串(也就是最长和最完整的字符串)。 下面给出了选择处理请求的位置的确切逻辑:
- 测试所有URI的前缀字符串。
=
(等号)修饰符定义了URI和前缀字符串完全匹配。如果找到完全匹配,则搜索停止。- 如果
^~
(插入符号)修饰符预先添加最长匹配前缀字符串,则不会检查正则表达式。 - 存储最长匹配的前缀字符串。
- 根据正则表达式测试URI。
- 断开第一个匹配的正则表达式并使用相应的位置。
- 如果没有正则表达式匹配,则使用与存储的前缀字符串相对应的位置。
=
修饰符的典型用例是/
(正斜杠)的请求。 如果请求/
是频繁的,则指定=/
作为location
指令的参数加速处理,因为搜索匹配在第一次比较之后停止。
location = / {
...
}
location
上下文可以包含定义如何解析请求的指令 - 提供静态文件或将请求传递给代理的服务器。 在以下示例中,匹配第一个location
上下文的请求将从/data/images
目录中提供文件,并将匹配第二个位置的请求传递给承载 www.example.com
域内容的代理服务器。
server {
location /images/ {
root /data;
}
location / {
proxy_pass http://www.example.com;
}
}
root
指令指定要在其中搜索要提供的静态文件的文件系统路径。 与该位置相关联的请求URI将附加到路径,以获取要提供的静态文件的全名。 在上面的示例中,要响应/images/logo.png
的请求,NGINX提供服务器本地实际对应文件是:/data/images/logo.png
。
proxy_pass
指令将请求传递给使用配置的URL访问代理服务器。然后将代理服务器的响应传回客户端。在上面的示例中,所有不以/images/
开头的URI的请求都将被传递给代理的服务器(也就是:www.example.com
)。
20.3. 使用变量
可以使用配置文件中的变量,使NGINX进程的请求根据定义的情况而有所不同。 变量是在运行时计算的命名值,用作指令的参数。 一个变量由它的名字开头的$
(美元)符号表示。 变量根据NGINX的状态定义信息,例如正在处理的请求的属性。
有许多预定义的变量,如核心HTTP变量,您可以使用set
,map
和geo
指令定义自定义变量。 大多数变量在运行时计算的,并包含与特定请求相关的信息。 例如,$remote_addr
包含客户端IP地址,$uri
保存当前的URI值。
20.4. 返回特定状态码
一些网站URI需要立即返回具有特定错误或重定向代码的响应,例如当页面被暂时移动或永久移动时。 最简单的方法是使用return
指令。 例如返回未找到的404
状态码:
location /wrong/url {
return 404;
}
返回的第一个参数是响应代码。可选的第二个参数可以是重定向的URL(代码301
,302
,303
和307
)或在响应体中返回文本。 例如:
location /permanently/moved/url {
return 301 http://www.example.com/moved/here;
}
返回指令可以包含在 location
和 server
上下文中。
20.5. 重写URI请求
可以通过使用rewrite
指令在请求处理期间多次修改请求URI,该指令具有一个可选参数和两个必需参数。 第一个(必需)参数是请求URI必须匹配的正则表达式。 第二个参数是用于替换匹配URI的URI。 可选的第三个参数是可以停止进一步重写指令的处理或发送重定向(代码301
或302
)的标志。例如:
location /users/ {
rewrite ^/users/(.*)$ /show?user=$1 break;
}
如该示例所示,用户通过匹配正则表达式捕获第二个参数。
您可以在location
和 server
上下文中包含多个rewrite
指令。 NGINX按照它们发生的顺序逐个执行指令。 当选择该上下文时,server
上下文中的rewrite
指令将被执行一次。
在NGINX处理一组rewrite
指令之后,它根据新的URI选择一个location
上下文。 如果所选location
块包含rewrite
指令,则依次执行它们。 如果URI与其中任何一个匹配,则在处理所有定义的rewrite
指令之后,将搜索新location
块。
以下示例显示了与返回指令相结合的rewrite
指令。
server {
...
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
return 403;
...
}
此示例配置区分两组URI。 诸如/download/some/media/file
之类的URI更改为/download/some/mp3/file.mp3
。由于最后一个标志,所以跳过后续指令(第二次rewrite
和return
指令),但NGINX继续处理该请求,该请求现在具有不同的URI。类似地,诸如/download/some/audio/file
的URI被替换为/download/some/mp3/file.ra
。 如果URI与rewrite
指令不匹配,则NGINX将403
错误代码返回给客户端。
有两个中断处理重写指令的参数:
last
- 停止执行当前服务器或位置上下文中的重写指令,但是NGINX会搜索与重写的URI匹配的位置,并且应用新位置中的任何重写指令(URI可以再次更改,往下继续匹配)。break
- 像break
指令一样,在当前上下文中停止处理重写指令,并取消搜索与新URI匹配的位置。新位置(location
)块中的rewrite
指令不执行。
20.6. 重写HTTP响应
有时您需要重写或更改HTTP响应中的内容,将一个字符串替换为另一个字符串。 您可以使用sub_filter
指令来定义要应用的重写。 该指令支持变量和替代链,使更复杂的更改成为可能。
例如,您可以更改引用除代理服务器之外的绝对链接:
location / {
sub_filter /blog/ /blog-staging/;
sub_filter_once off;
}
另一个示例将方法从http://
更改为http://
,并从请求头域替换本地主机地址到主机名。 sub_filter_once
指令告诉NGINX在一个位置(location
)内连续应用sub_filter
伪指令:
location / {
sub_filter 'href="http://127.0.0.1:8080/' 'href="http://$host/';
sub_filter 'img src="http://127.0.0.1:8080/' 'img src="http://$host/';
sub_filter_once on;
}
请注意,如果发生另一个sub_filter
匹配,则使用sub_filter
修改的响应部分将不再被替换。
20.7.处理错误
使用error_page
指令,您可以配置NGINX返回自定义页面以及错误代码,替换响应中的其他错误代码,或将浏览器重定向到其他URI。 在以下示例中,error_page
指令指定要返回404
页面错误代码的页面(/404.html
)。
error_page 404 /404.html;
请注意,此伪指令并不立即返回该错误(返回指令执行该操作),而仅仅是指定发生时如何处理错误。 错误代码可以来自代理服务器,或者在NGINX处理期间发生(例如,当NGINX找不到客户端请求的文件时,显示404
对应的结果)。
在以下示例中,当NGINX找不到页面时,它会将代码301
替换为代码404
,并将客户端重定向到http:/example.com/new/path.html
。 当客户端仍尝试访问其旧URI的页面时,此配置非常有用。 301
代码通知浏览器页面已经永久移动,并且需要在返回时自动替换旧地址。
location /old/path.html {
error_page 404 =301 http:/example.com/new/path.html;
}
以下配置是在未找到文件时将请求传递给后端的示例。 因为在error_page
指令的等号之后没有指定状态代码,所以对客户机的响应具有代理服务器返回的状态代码(不一定是404
)。
server {
...
location /images/ {
# Set the root directory to search for the file
root /data/www;
# Disable logging of errors related to file existence
open_file_cache_errors off;
# Make an internal redirect if the file is not found
error_page 404 = /fetch$uri;
}
location /fetch/ {
proxy_pass http://backend/;
}
}
当没有找到文件时,error_page
指令指示NGINX进行内部重定向。 error_page
指令的最终参数中的$uri
变量保存当前请求的URI,该URI在重定向中被传递。
例如,如果没有找到/images/some/file
,它将被替换为/fetch/images/some/file
,并且从新的搜索位置(location
)开始。最后请求最终在第二个location
上下文中,并被代理到http://backend/
。
如果没有找到文件,则open_file_cache_errors指令可防止写入错误消息。 因为丢失的文件可被正确地处理,但这不是必需的。
21.Nginx配置静态内容服务器
本节介绍如何使用NGINX来提供静态内容服务,定义搜索路径以查找请求的文件的方法,以及如何设置索引文件。
在这个部分,我们主要涉及以下几个方面的内容:
- 根目录和索引文件
- 尝试几个选项
- 优化NGINX服务内容的速度
21.1. 根目录和索引文件
root指令指定将用于搜索文件的根目录。 要获取请求文件的路径,NGINX将请求URI附加到root
指令指定的路径。 该指令可以放置在http
,server
或location
上下文中的任何级别上。 在下面的示例中,为虚拟服务器定义了root
指令。 它适用于不包括root
指令的所有location
块以显式重新定义根:
server {
root /www/data;
location / {
}
location /images/ {
}
location ~ \.(mp3|mp4) {
root /www/media;
}
}
这里,NGINX在文件系统的/www/data/images/
目录中搜索以/images/
开头的URI。 但是,如果URI以.mp3
或.mp4
扩展名结尾,则NGINX会在/www/media/
目录中搜索.mp3
或.mp4
文件,因为它在匹配的location
块中定义。
如果请求以斜杠结尾,则NGINX将其视为对目录的请求,并尝试在目录中找到索引文件。index
指令定义索引文件的名称(默认值为index.html
)。继续示例,如果请求URI为/images/some/path/
,则NGINX会传递文件/www/data/images/some/path/index.html
(如果存在)。 如果不存在文件,NGINX默认返回HTTP代码404
(未找到)。 要配置NGINX以返回自动生成的目录列表,请将on
参数添加到autoindex
指令中:
location /images/ {
autoindex on;
}
可以在索引指令中列出多个文件名。 NGINX以指定的顺序搜索文件,并返回它找到的第一个文件。
location / {
index index.$geo.html index.html index.html;
}
这里使用的$geo
变量是通过geo指令设置的自定义变量。 变量的值取决于客户端的IP地址。
要返回索引文件,NGINX检查其是否存在,然后通过将索引文件的名称附加到基本URI来对通过URI获取的内部重定向。内部重定向会导致对某个位置(location
)的新搜索,并且可能会在另一个位置(location
)中结束,如以下示例所示:
location / {
root /data;
index index.html index.php;
}
location ~ \.php {
fastcgi_pass localhost:8000;
...
}
在这里,如果请求中的URI是/path/
,并且/data/path/index.html
不存在,但是/data/path/index.php
存在,则将/path/index.php
内部重定向映射到第二个位置(location
)。 因此,请求被代理。
21.2. 尝试几个选项
try_files指令可用于检查指定的文件或目录是否存在并进行内部重定向,如果没有指定的文件或目录,则返回特定的状态代码。 例如,要检查与请求URI相对应的文件的存在,请使用try_files
指令和$uri
变量,如下所示:
server {
root /www/data;
location /images/ {
try_files $uri /images/default.gif;
}
}
该文件以URI的形式指定,它使用在当前位置或虚拟服务器的上下文中设置的 root
或 alias
伪指令进行处理。 在这种情况下,如果与原始URI相对应的文件不存在,则NGINX将内部重定向到最后一个参数中指定的URI,也就是返回/www/data/images/default.gif
。
最后一个参数也可以是一个状态代码(直接在前面的等号)或位置的名称。 在以下示例中,如果try_files
指令的任何参数都不会解析为现有文件或目录,则会返回404错误,可以改成500等其他错误码,否则默认就是404看不出效果。
location / {
try_files $uri $uri/ $uri.html =404;
}
在下一个示例中,如果原始URI和带有附加尾部斜线的URI都不能解析为现有文件或目录,则将请求重定向到将其传递给代理服务器的命名位置(location
)。
location / {
try_files $uri $uri/ @backend;
}
location @backend {
proxy_pass http://backend.example.com;
}
PS:try_files 就是从左往右逐个检查每个参数,如果有匹配就返回值。
21.3. 优化NGINX服务内容的速度
加载速度是服务任何内容的关键因素。 对您的NGINX配置进行小幅优化可能会提高生产力并帮助实现最佳性能。
21.3.1.启用sendfile
默认情况下,NGINX会自动处理文件传输,并在发送文件之前将其复制到缓冲区中。 启用sendfile指令将消除将数据复制到缓冲区中的步骤,并允许将数据从一个文件描述符直接复制到另一个文件描述符。 或者,为了防止一个快速连接完全占用工作进程,您可以通过定义sendfile_max_chunk指令来限制在单个sendfile()
调用中传输的数据量:
location /mp3 {
sendfile on;
sendfile_max_chunk 1m;
}
21.3.2.启用tcp_nopush
将tcp_nopush选项与sendfile
一起使用。 该选项将使NGINX能够通过sendfile
获取数据块之后,在一个数据包中发送HTTP响应头
location /mp3 {
sendfile on;
tcp_nopush on;
...
}
21.3.3.启用tcp_nodelay
tcp_nodelay选项可以覆盖Nagle的算法,最初是为了解决慢网络中的小数据包问题而设计的。 该算法将大量小数据包整合到较大的数据包中,并以200 ms
的延迟发送数据包。
如今,当服务大型静态文件时,无论数据包大小如何,都可以立即发送数据。 延迟也会影响在线应用程序(ssh,在线游戏,网上交易)。 默认情况下,tcp_nodelay
指令设置为on
,表示Nagle的算法被禁用。 该选项仅用于Keepalive
连接:
location /mp3 {
tcp_nodelay on;
keepalive_timeout 65;
...
}
21.3.4优化积压队列
其中一个重要因素是NGINX可以处理传入连接的速度。 一般规则是建立连接时,将其放入监听套接字的“侦听”队列中。 在正常负载下,有一个低队列,或根本没有队列。 但是在高负载下,队列可能会急剧增长,这可能会导致性能不均衡,连接丢失和延迟。
21.3.4.1. 测量侦听队列
让我们来查看当前的侦听队列。 运行命令:
netstat -Lan
命令输出可能如下所示:
Current listen queue sizes (qlen/incqlen/maxqlen)
Listen Local Address
0/0/128 *.12345
10/0/128 *.80
0/0/128 *.8080
命令输出显示端口80
的监听队列中有10
个不接受的连接,而连接限制为128
个连接,这种情况是正常的。
但是,命令输出可能如下所示:
Current listen queue sizes (qlen/incqlen/maxqlen)
Listen Local Address
0/0/128 *.12345
192/0/128 *.80
0/0/128 *.8080
命令输出显示超过128个连接限制的192个不可接受的连接。 当网站的流量很大时,这是很常见的。 为了达到最佳性能,您需要增加NGINX在操作系统和NGINX配置中排队等待接收的最大连接数。
21.3.4.2. 调整操作系统
将net.core.somaxconn
键的值从其默认值(128
)增加到足够高的值以能够处理高突发流量:
对于FreeBSD,运行命令:
sudo sysctl kern.ipc.somaxconn=4096
对于FreeBSD,运行命令:
sudo sysctl -w net.core.somaxconn=4096
打开文件:/etc/sysctl.conf
,将下面一行添加到文件并保存文件:
net.core.somaxconn = 4096
21.3.4.3. 调整NGINX
如果将somaxconn
键设置为大于512
的值,请更改NGINX listen指令的backlog
参数以匹配:
server {
listen 80 backlog 4096;
# The rest of server configuration
}
22. Nginx反向代理
本文介绍代理服务器的基本配置。 您将学习如何通过不同协议将NGINX请求传递给代理的服务器,修改发送到代理服务器的客户端请求标头,以及配置来自代理服务器的响应缓冲。
代理服务器的基本配置目录
- 代理服务器介绍
- 将请求传递给代理的服务器
- 传递请求标头
- 配置缓冲区
- 选择传出IP地址
22.1. 代理服务器介绍
代理通常用于在多个服务器之间分配负载,无缝地显示来自不同网站的内容,或者通过HTTP以外的协议将请求传递给应用服务器。
22.2. 将请求传递给代理的服务器
当NGINX代理请求时,它将请求发送到指定的代理服务器,获取响应,并将其发送回客户端。 可以使用指定的协议将请求代理到HTTP服务器(另一个NGINX服务器或任何其他服务器)或非HTTP服务器(可以运行使用特定框架开发的应用程序,如PHP或Python)。 支持的协议包括FastCGI,uwsgi,SCGI和memcached。
要将请求传递给HTTP代理服务器,则在一个location块内指定proxy_pass指令。 例如:
location /some/path/ {
proxy_pass http://www.example.com/link/;
}
此示例配置将在此location
处理的所有请求传递到指定地址(http://www.example.com/link/
)处的代理服务器。该地址可以指定为域名或IP地址。 该地址还可能包括一个端口:
location ~ \.php {
proxy_pass http://127.0.0.1:8000;
}
请注意,在上述第一个示例中,代理服务器的地址后面是URI为 /link/
。 如果URI与地址一起指定,它将替换与location
参数匹配请求URI的部分。 例如,这里使用/some/path/page.html
的URI请求将被代理到http://www.example.com/link/page.html
。 如果地址被指定为没有URI,或者不可能确定要替换的URI部分,则会传递完整的请求URI(可能是修改)。
要将请求传递给非HTTP代理服务器,应使用适当的**_ pass
指令:
fastcgi_pass
将请求传递给FastCGI服务器uwsgi_pass
将请求传递给uwsgi服务器scgi_pass
将请求传递给SCGI服务器memcached_pass
将请求传递给memcached服务器
请注意,在这些情况下,指定地址的规则可能不同。 您可能还需要向服务器传递其他参数(有关详细信息,请参阅参考文档)。
proxy_pass
指令也可以指向一组命名的服务器。 在这种情况下,根据指定的方法在组中的服务器之间分配请求。
22.3. 传递请求标头
默认情况下,NGINX在代理请求“Host”
和 “Connection”
中重新定义了两个头字段,并消除了其值为空字符串的头字段。 “Host”设置为$proxy_host
变量,“Connection”
设置为关闭(close
)。
要更改这些设置,以及修改其他header
字段,请使用proxy_set_header
指令。 该指令可以在一个或多个位置(location
)指定。 它也可以在特定的server
上下文或http
块中指定。 例如:
location /some/path/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:8000;
}
在此配置中,“Host”
字段设置为 $host 变量。
为了防止头域被传递给代理服务器,请将其设置为空字符串,如下所示:
location /some/path/ {
proxy_set_header Accept-Encoding "";
proxy_pass http://localhost:8000;
}
22.4. 配置缓冲区
Nginx 缓冲区设置 proxy_buffers相关配置https://blog.csdn.net/benpaodelulu_guajian/article/details/79198084
默认情况下,NGINX缓存来自代理服务器的响应。 响应存储在内部缓冲区中,并且不会发送到客户端,直到收到整个响应。 缓冲有助于通过慢客户端优化性能,如果响应从NGINX同步传递到客户端,这可能会浪费代理服务器时间。 然而,当启用缓冲时,NGINX允许代理服务器快速处理响应,而NGINX存储响应时间与客户端需要下载的时间一样长。
负责启用和禁用缓冲的指令是proxy_buffering。 默认情况下,它被设置为开启且缓冲已启用。
proxy_buffers
指令控制分配给请求的缓冲区的大小和数量。 来自代理服务器的响应的第一部分存储在单独的缓冲区中,其大小由proxy_buffer_size指令设置。 这部分通常包含一个比较小的响应头,并且可以比其余的响应的缓冲区小。
在以下示例中,缓冲区的默认数量增加,并且响应的第一部分的缓冲区的大小小于默认值。
location /some/path/ {
# 16个 4k大小的缓冲区
proxy_buffers 16 4k;
#header buffer
proxy_buffer_size 2k;
proxy_pass http://localhost:8000;
}
如果缓存被禁用,则在从代理服务器接收缓冲时,响应将同步发送到客户端。 对于需要尽快开始接收响应的快速交互式客户端,此行为可能是可取的。
要禁用特定位置的缓冲,请在location
块中将proxy_buffering
伪指令设置为off
,如下所示:
location /some/path/ {
proxy_buffering off;
proxy_pass http://localhost:8000;
}
在这种情况下,NGINX只使用由proxy_buffer_size
配置的缓冲区来存储响应的当前部分。
22.5. 选择传出IP地址
如果您的代理服务器有多个网络接口,有时您可能需要选择特定的源IP地址才能连接到代理服务器或上游。 如果NGINX后端的代理服务器只配置为接受来自特定IP网络或IP地址范围的连接,在这种情况下,这个配置选项就很有用。
指定proxy_bind指令和必要网络接口的IP地址:
location /app1/ {
proxy_bind 127.0.0.1;
proxy_pass http://example.com/app1/;
}
location /app2/ {
proxy_bind 127.0.0.2;
proxy_pass http://example.com/app2/;
}
IP地址也可以用变量指定。 例如,$server_addr变量传递接受请求的网络接口的IP地址:
location /app3/ {
proxy_bind $server_addr;
proxy_pass http://example.com/app3/;
}
23.Nginx压缩和解压
本节介绍如何配置响应的压缩或解压缩以及发送压缩文件。
在这篇文章中,涉及内容如下 -
- 压缩和解压缩介绍
- 启用压缩
- 启用解压缩
- 发送压缩文件
23.1. 压缩和解压缩介绍
相关文章:https://blog.csdn.net/baidu_35407267/article/details/77141871 如何通过GZIP来优化你的网站
压缩响应通常会显着减少传输数据的大小。 然而,由于压缩在运行时发生,它还可以增加相当大的处理开销,这会对性能产生负面影响 在向客户端发送响应之前,NGINX会执行压缩,但不会“压缩”已压缩的响应(例如,由代理的服务器)。
23.2. 启用压缩
要启用压缩,请使用包含gzip指令并指定on
值。
gzip on;
默认情况下,NGINX仅使用MIME类型text/html
压缩响应。要使用其他MIME类型压缩响应,请包含gzip_types
指令并列出其他类型。
gzip_types text/plain application/xml;
要指定要压缩的响应的最小长度,请使用gzip_min_length指令。 默认值为20
字节(可将此处调整为1000
):
gzip_min_length 1000;
默认情况下,NGINX不会压缩对代理请求的响应(来自代理服务器的请求)。 请求来自代理服务器的事实由请求中Via头字段的存在确定。 要配置这些响应的压缩,请使用gzip_proxied指令。
该指令具有多个参数,指定NGINX应压缩哪种代理请求。例如,仅对不会在代理服务器上缓存的请求压缩响应是合理的。 为此,gzip_proxied
指令具有指示NGINX在响应中检查Cache-Control
头字段的参数,如果值为no-cache
, no-store
或 private
,则压缩响应。 另外,您必须包括 Expires
参数以用来检查Expires
头域的值。 这些参数在以下示例中与auth
参数一起设置,该参数检查Authorization
头字段的存在(授权响应特定于最终用户,并且通常不被缓存):
gzip_proxied no-cache no-store private expired auth;
与大多数其他指令一样,配置压缩的指令可以包含在http
上下文中,也可以包含在 server
或 location
配置块中。
gzip
压缩的整体配置可能如下所示。
server {
gzip on;
gzip_types text/plain application/xml;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 1000;
...
}
23.3. 启用解压缩
某些客户端不支持使用gzip
编码方法的响应。 同时,可能需要存储压缩数据,或者即时压缩响应并将它们存储在缓存中。 为了成功地服务于不接受压缩数据的客户端,NGINX可以在将数据发送到后一种类型的客户端时即时解压缩数据。
要启用运行时解压缩,请使用gunzip
指令。
location /storage/ {
gunzip on;
...
}
gunzip
指令可以在与gzip
指令相同的上下文中指定:
server {
gzip on;
gzip_min_length 1000;
gunzip on;
...
}
请注意,此指令在单独的模块中定义,默认情况可能不包含在开源NGINX构建中。
23.4. 发送压缩文件
要将文件的压缩版本发送到客户端而不是常规文件,请在适当的上下文中将gzip_static
指令设置为on
。
location / {
gzip_static on;
}
在这种情况下,为了服务/path/to/file
的请求,NGINX尝试查找并发送文件/path/to/file.gz
。 如果文件不存在,或客户端不支持gzip
,则NGINX将发送未压缩版本的文件。
请注意,gzip_static
指令不启用即时压缩。它只是使用压缩工具预先压缩的文件。要在运行时即时压缩内容(而不仅仅是静态内容),请使用gzip
指令。
该指令在单独的模块中定义,默认情况下可能不包含在开源NGINX构建中。
24.Nginx内容缓存
本节介绍如何启用和配置从代理服务器接收的响应的缓存。主要涉及以下内容 -
- 缓存介绍
- 启用响应缓存
- 涉及缓存的NGINX进程
- 指定要缓存的请求
- 限制或绕过缓存
- 从缓存中清除内容
- 配置缓存清除
- 发送清除命令
- 限制访问清除命令
- 从缓存中完全删除文件
- 缓存清除配置示例
- 字节缓存
- 组合配置示例
24.1. 介绍
当启用缓存时,NGINX将响应保存在磁盘缓存中,并使用它们来响应客户端,而不必每次都为同一内容代理请求。
24.2. 启用响应缓存
要启用缓存,请在顶层的http
上下文中包含proxy_cache_path指令。 强制的第一个参数是缓存内容的本地文件系统路径,强制keys_zone
参数定义用于存储有关缓存项目的元数据的共享内存区域的名称和大小:
http {
...
proxy_cache_path /data/nginx/cache keys_zone=one:10m;
}
然后在要缓存服务器响应的上下文(协议类型,虚拟服务器或位置)中包含proxy_cache
指令,将由keys_zone
参数定义的区域名称指定为proxy_cache_path
指令(在本例中为一):
http {
...
proxy_cache_path /data/nginx/cache keys_zone=one:10m;
server {
proxy_cache one;
location / {
proxy_pass http://localhost:8000;
}
}
}
请注意,由keys_zone
参数定义的大小不会限制缓存的响应数据的总量。 缓存响应本身存储在文件系统上的特定文件中的元数据副本。 要限制缓存的响应数据量,请将max_size
参数包含到proxy_cache_path
指令中(但请注意,缓存数据的数量可能会临时超出此限制,如以下部分所述。)
24.3. 涉及缓存的NGINX进程
缓存中还有两个额外的NGINX进程:
- 缓存管理器周期性地被激活以检查缓存的状态。 如果缓存大小超过了由
max_cize_path
指令设置的max_size
参数,缓存管理器将删除最近访问的数据。如前所述,高速缓存管理器激活之间的缓存数据量可以临时超过限制。 - NGINX启动后,缓存加载程序只运行一次。 它将有关以前缓存的数据的元数据加载到共享内存区域。一次加载整个缓存可能会在启动后的最初几分钟内消耗足够的资源来减慢NGINX的性能。 为了避免这种情况,请通过将以下参数包含到
proxy_cache_path
伪指令来配置缓存的迭代加载:loader_threshold
- 迭代的持续时间,以毫秒为单位(默认为200
)loader_files
- 在一次迭代期间加载的最大项目数(默认为100
)loader_sleeps
- 迭代之间的延迟(以毫秒为单位)(默认为50
)
在以下示例中,迭代持续300
毫秒或直到加载了200
个项目:
proxy_cache_path /data/nginx/cache keys_zone=one:10m loader_threshold=300 loader_files=200;
24.4. 指定要缓存的请求
默认情况下,NGINX首次从代理服务器接收到这样的响应后,缓存对HTTP GET
和HEAD
方法的请求的所有响应。 作为请求的密钥(标识符),NGINX使用请求字符串。 如果请求具有与缓存响应相同的密钥,则NGINX将缓存的响应发送给客户端。 您可以在http
, server
, 或 location
上下文中包含各种指令,以控制哪些响应被缓存。
要更改在计算密钥时使用的请求字符,请包括proxy_cache_key
伪指令:
proxy_cache_key "$host$request_uri$cookie_user";
要定义在缓存响应之前必须进行具有相同密钥的请求的最小次数,请包括proxy_cache_min_uses指令:
proxy_cache_min_uses 5;
要使用除GET和HEAD之外的方法来缓存对请求的响应,请将它们与GET和HEAD一起列为proxy_cache_methods伪指令的参数:
proxy_cache_methods GET HEAD POST;
24.5. 限制或绕过缓存
默认情况下,响应将无限期地保留在缓存中。 只有缓存超过最大配置大小,然后按照最后一次请求的时间长度,它们才被删除。 您可以通过在http
, server
, 或 location
上下文中包含指令来设置缓存响应被认为有效的时间长度,甚至是否使用它们。
要限制缓存响应与特定状态代码被认为有效的时间,请包括proxy_cache_valid指令:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
在此示例中,使用代码200
或302
的响应有效时间为10
分钟,并且代码404
的响应有效1
分钟。 要定义具有所有状态码的响应的有效时间,请指定any
作为第一个参数:
proxy_cache_valid any 5m;
要定义NGINX不会向客户端发送缓存响应的条件,请包括proxy_cache_bypass
指令。 每个参数定义一个条件并由多个变量组成。 如果至少有一个参数不为空,并且不等于“0
”(零),则NGINX不会在缓存中查找响应,而是将请求立即转发到后端服务器。
proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
要定义NGINX根本不缓存响应的条件,请包括proxy_no_cache指令,以与proxy_cache_bypass
伪指令相同的方式定义参数。
proxy_no_cache $http_pragma $http_authorization;
24.6. 从缓存中清除内容
NGINX可以从缓存中删除过期的缓存文件。删除过期的缓存内容以防止同时提供旧版本和新版本的网页。 在接收到包含自定义HTTP头或“PURGE” HTTP方法的特殊“purge
”请求时,缓存被清除。
24.6.1 配置http块层级上缓存清除
我们设置一个配置来标识使用“PURGE” HTTP方法的请求并删除匹配的URL。
1.在http
块层级上,创建一个新变量,例如:$purge_method
,这将取决于$request_method
变量:
http {
...
map $request_method $purge_method {
PURGE 1;
default 0;
}
}
24.6.2 配置location块层级上缓存清除
在location
中配置高速缓存,包括指定缓存清除请求的条件的proxy_cache_purge指令。 在我们的例子中,它是在上一步配置的$purge_method
:
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://localhost:8002;
proxy_cache mycache;
proxy_cache_purge $purge_method;
}
}
24.6.3 发送清除命令
配置proxy_cache_purge
指令后,您需要发送一个特殊的缓存清除请求来清除缓存。 您可以使用一系列工具发出清除请求,例如curl
命令:
$ curl -X PURGE -D – "http://www.example.com/*"
HTTP/1.1 204 No Content
Server: nginx/1.5.7
Date: Sat, 01 Dec 2015 16:33:04 GMT
Connection: keep-alive
在该示例中,具有公共URL部分(由星号通配符指定)的资源将被删除。 但是,这些高速缓存条目将不会从缓存中完全删除:它们将保留在磁盘上,直到它们被删除为非活动状态(proxy_cache_path
的非活动参数),或由缓存清除程序进程处理,或客户端尝试访问它们 。
24.6.4 限制访问清除命令
建议您配置允许发送缓存清除请求的有限数量的IP地址:
geo $purge_allowed {
default 0; # deny from other
10.0.0.1 1; # allow from localhost
192.168.0.0/24 1; # allow from 10.0.0.0/24
}
map $request_method $purge_method {
PURGE $purge_allowed;
default 0;
}
在这个例子中,NGINX检查请求中是否使用“PURGE
”方法,如果是,分析客户端IP地址。 如果IP地址被列入白名单,那么$purge_method
设置为$purge_allowed:“1”
允许清除,“0
”表示禁止清除。
24.6.5 从缓存中完全删除文件
要完全删除与星号相匹配的缓存文件,您将需要激活一个特殊的缓存清除程序,该过程将永久地遍历所有缓存条目,并删除与通配符相匹配的条目。 在http
块级别上,将purger
参数添加到proxy_cache_path
指令中:
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m purger=on;
24.6.6 缓存清除配置示例
http {
...
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m purger=on;
map $request_method $purge_method {
PURGE 1;
default 0;
}
server {
listen 80;
server_name www.example.com;
location / {
proxy_pass http://localhost:8002;
proxy_cache mycache;
proxy_cache_purge $purge_method;
}
}
geo $purge_allowed {
default 0;
10.0.0.1 1;
192.168.0.0/24 1;
}
map $request_method $purge_method {
PURGE $purge_allowed;
default 0;
}
}
24.7. 字节缓存
有时,初始缓存填充操作可能需要一些时间,特别是对于大文件。 当第一个请求开始下载视频文件的一部分时,下一个请求将不得不等待整个文件被下载并放入高速缓存。
NGINX使缓存这样的范围请求成为可能,并逐渐用缓存片模块填充高速缓存。 该文件分为较小的“切片”。 每个范围请求选择将覆盖所请求范围的特定切片,并且如果此范围仍未缓存,请将其放入缓存中。 对这些切片的所有其他请求将从缓存中获取响应。
要启用字节范围缓存:
-
确保您的NGINX是使用slice模块编译的。
-
使用slice指令指定切片的大小:
location / { slice 1m; }
slice
的大小应适当调整,使切片快速下载。 在处理请求时,太小的大小可能会导致内存使用量过多和大量打开的文件描述符,太大的值可能会导致延迟。 -
将
$slice_range
变量包含到缓存键中:proxy_cache_key $uri$is_args$args$slice_range;
-
启用使用206状态代码缓存响应:
proxy_cache_valid 200 206 1h;
-
通过在
Range
头字段中传递$slice_range
变量来将传递范围请求设置为代理服务器:proxy_set_header Range $slice_range;
字节范围缓存示例:
location / {
slice 1m;
proxy_cache cache;
proxy_cache_key $uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
proxy_cache_valid 200 206 1h;
proxy_pass http://localhost:8000;
}
请注意,如果切片(slice
)缓存打开,则不应更改初始文件。
24.8. 组合配置示例
以下示例配置组合了上述某些缓存选项。
http {
...
proxy_cache_path /data/nginx/cache keys_zone=one:10m loader_threshold=300
loader_files=200 max_size=200m;
server {
listen 8080;
proxy_cache one;
location / {
proxy_pass http://backend1;
}
location /some/path {
proxy_pass http://backend2;
proxy_cache_valid any 1m;
proxy_cache_min_uses 3;
proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
}
}
}
在这个例子中,两个位置使用相同的缓存,但是以不同的方式。
由于backend1
服务器的响应很少更改,因此不包括缓存控制指令。 首次请求响应缓存,并无限期保持有效。
相比之下,对backend2
服务的请求的响应频繁变化,因此它们被认为只有1
分钟有效,并且在相同请求3
次之前不被缓存。 此外,如果请求符合proxy_cache_bypass
指令定义的条件,则NGINX会立即将请求传递给backend2
,而不在缓存中查找。
25.Nginx配置日志
本节介绍如何在NGINX中配置日志记录错误和处理的请求。在本文章中将涉及以下内容 -
- 设置错误日志
- 设置访问日志
- 启用条件日志记录
- 日志记录到Syslog
25.1. 设置错误日志
NGINX将遇到的不同严重性级别问题的信息写入错误日志。 error_log
指令将日志记录设置为特定文件,stderr
或syslog
,并指定要记录的消息的最低级别。 默认情况下,错误日志位于{NGING_INSTALL_PATH}/logs/error.log
(绝对路径取决于操作系统和安装),并记录来自所指定的所有严重级别的消息。
以下配置将错误消息的最小严重性级别更改为从错误记录到警告:
error_log logs/error.log warn;
## 或者可写为: error_log /var/logs/nginx/error.log warn;
在这种情况下,将记录 warn
, error crit
, alert
和 emerg
级别的消息。
错误日志的默认设置全局工作。 要覆盖它,将error_log
指令放在 main
(顶级)配置上下文中。main
上下文中的设置始终由其他配置级别继承。 还可以在 http
, stream
, server
和 location
级别指定error_log
指令,并覆盖从较高级别继承的设置。 如果发生错误,则该消息只写入一个错误日志,最接近发生错误的级别的错误日志。 但是,如果在同一级别指定了多个error_log
伪指令,则会将消息写入所有指定的日志。
注意:在开源NGINX版本1.5.2中添加了在同一配置级别指定多个
error_log
伪指令的功能。
25.2. 设置访问日志
在处理请求之后,NGINX在访问日志中写入有关客户端请求的信息。 默认情况下,访问日志位于{NGING_INSTALL_PATH}logs/access.log
中,{NGING_INSTALL_PATH}
为安装nginx的目录,信息以预定义的组合格式写入日志。要覆盖这个默认设置,请使用log_format指令更改记录消息的格式,以及access_log指令,以指定日志的位置及其格式。 日志格式使用变量定义。
以下示例定义扩展预定义组合格式的日志格式,其值指示响应gzip
的压缩比。 然后将格式应用于启用压缩的虚拟服务器。
http {
log_format compression '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
server {
gzip on;
access_log /spool/logs/nginx-access.log compression;
...
}
}
以下是一些如何读取生成时间值的规则:
- 当通过多个服务器处理请求时,变量包含由逗号分隔的多个值。
- 当从一个上游组到另一个上游组有内部重定向时,这些值以分号分隔。
- 当请求无法到达上游服务器或无法接收到完整报头时,变量包含“0”(零)。
- 在连接到上游或从缓存中获取回复时出现内部错误的情况下,该变量包含“
-
”(连字符)。
可以通过启用缓冲区的日志消息和名称包含变量的常用日志文件的描述符缓存来优化日志记录。 要启用缓冲,请使用access_log指令的缓冲区参数来指定缓冲区的大小。 当下一个日志消息不适合缓冲区以及其他情况时,缓冲的消息将被写入日志文件。
要启用日志文件描述符的缓存,请使用open_log_file_cache指令。
与error_log
指令类似,在特定配置级别定义的access_log
伪指令将覆盖以前级别的设置。 当请求的处理完成时,消息将被写入到当前级别上配置的日志中,或者从先前的级别继承。 如果一个级别定义了多个访问日志,则会将消息写入所有的访问日志。
25.3. 启用条件日志记录
条件记录允许从访问日志中排除琐碎或不重要的日志条目。在NGINX中,条件日志记录由access_log
伪指令的if
参数启用。
此示例不包括使用HTTP状态代码2xx
(成功)和3xx
(重定向)的请求:
map $status $loggable {
~^[23] 0;
default 1;
}
access_log /path/to/access.log combined if=$loggable;
25.4. 日志记录到Syslog
syslog
实用程序是计算机消息记录的标准,并允许从单个syslog
服务器上的不同设备收集日志消息。 在NGINX中,对syslog
的日志记录使用error_log
和access_log
伪指令中的syslog:
前缀进行配置。
Syslog消息可以发送到服务器=可以是域名,IP地址或UNIX域的套接字路径。 可以使用端口指定域名或IP地址来覆盖默认端口514
. 可以在unix:prefix
之后指定UNIX域套接字路径:
error_log server=unix:/var/log/nginx.sock debug;
access_log syslog:server=[2001:db8::1]:1234,facility=local7,tag=nginx,severity=info;
在该示例中,NGINX错误日志消息将在调试日志记录级别写入UNIX域套接字,并将访问日志写入具有IPv6地址和端口1234
的syslog服务器。
facility =
参数指定正在记录消息的程序类型。 默认值为local7
。 其他可能的值是:auth
,authpriv
,daemon
,cron
,ftp
,lpr
,kern
,mail
,news
,syslog
,user
,uucp
,local0
… local7
。
tag =
参数将自定义标签应用于syslog
消息(在我们的示例中为nginx)。
severity =
参数设置访问日志的syslog消息的严重性级别。 严重性越来越高的可能值为:debug
,info
,notice
,warn
,error(default)
,crit
,alert
和emerg
。 消息记录在指定的级别和更严重的级别。 在我们的示例中,严重性级别错误还使得可以 crit
, alert
和 emerg
级别。
26.Nginx主要应用场景(必读)
本文只针对Nginx在不加载第三方模块的情况能处理哪些事情,由于第三方模块太多所以也介绍不完,当然本文本身也可能介绍的不完整,这里是根据个人使用过和了解到过总结出来的。所以还请见谅,同时欢迎留言交流。
26.1Nginx能做什么?
- 反向代理
- 负载均衡
- HTTP服务器(包含动静分离)
- 正向代理
以上就是我了解到的Nginx在不依赖第三方模块能处理的事情,下面详细说明每种功能怎么做
26.2. 反向代理
反向代理应该是Nginx做的最多的一件事了,什么是反向代理呢,以下是百度百科的说法:反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已。
下面贴上一段简单的实现反向代理的代码 -
server {
listen 80;
server_name localhost;
client_max_body_size 1024M;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host:$server_port;
}
}
保存配置文件后启动Nginx,这样当我们访问localhost的时候,就相当于访问 localhost:8080 了。
26.3. 负载均衡
负载均衡也是Nginx常用的一个功能,负载均衡其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。简单而言就是当有2台或以上服务器时,根据规则随机的将请求分发到指定的服务器上处理,负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。而Nginx目前支持自带3种负载均衡策略,还有2种常用的第三方策略。
1、RR(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down
掉,能自动剔除。
upstream test {
server localhost:8080;
server localhost:8081;
}
server {
listen 81;
server_name localhost;
client_max_body_size 1024M;
location / {
proxy_pass http://test;
proxy_set_header Host $host:$server_port;
}
}
负载均衡的核心代码为 -
upstream test {
server localhost:8080;
server localhost:8081;
}
这里配置了2台服务器,当然实际上是一台,只是端口不一样而已,而8081的服务器是不存在的,也就是说访问不到,但是我们访问 http://localhost 的时候,也不会有问题,会默认跳转到 http://localhost:8080 具体是因为Nginx会自动判断服务器的状态,如果服务器处于不能访问(服务器挂了),就不会跳转到这台服务器,所以也避免了一台服务器挂了影响使用的情况,由于Nginx默认是RR策略,所以我们不需要其他更多的设置。
2、权重
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。 例如
upstream test {
server localhost:8080 weight=9;
server localhost:8081 weight=1;
}
那么10
次一般只会有1
次会访问到8081
,而有9
次会访问到8080
-
3、ip_hash
上面的2
种方式都有一个问题,那就是下一个请求来的时候请求可能分发到另外一个服务器,当我们的程序不是无状态的时候(采用了session保存数据),这时候就有一个很大的很问题了,比如把登录信息保存到了session中,那么跳转到另外一台服务器的时候就需要重新登录了,所以很多时候我们需要一个客户只访问一个服务器,那么就需要用iphash了,iphash的每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
upstream test {
ip_hash;
server localhost:8080;
server localhost:8081;
}
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
upstream backend {
fair;
server localhost:8080;
server localhost:8081;
}
5、url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。 在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
upstream backend {
hash $request_uri;
hash_method crc32;
server localhost:8080;
server localhost:8081;
}
以上5种负载均衡各自适用不同情况下使用,所以可以根据实际情况选择使用哪种策略模式,不过fair和url_hash需要安装第三方模块才能使用,由于本文主要介绍Nginx能做的事情,所以Nginx安装第三方模块不会再本文介绍
26.3. HTTP服务器
Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,同时现在也很流行动静分离,就可以通过Nginx来实现,首先看看Nginx做静态资源服务器
server {
listen 80;
server_name localhost;
client_max_body_size 1024M;
location / {
root E:/wwwroot;
index index.html;
}
}
这样如果访问 http://localhost 就会默认访问到E
盘wwwroot
目录下面的index.html
,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署。
26.4. 动静分离
动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。
upstream test{
server localhost:8080;
server localhost:8081;
}
server {
listen 80;
server_name localhost;
location / {
root e:/wwwroot;
index index.html;
}
# 所有静态请求都由nginx处理,存放目录为html
location ~ .(gif|jpg|jpeg|png|bmp|swf|css|js)$ {
root e:/wwwroot;
}
# 所有动态请求都转发给tomcat处理
location ~ .(jsp|do)$ {
proxy_pass http://test;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root e:/wwwroot;
}
}
这样我们就可以吧HTML以及图片和css以及js放到wwwroot目录下,而tomcat只负责处理jsp和请求,例如当我们后缀为gif的时候,Nginx默认会从wwwroot获取到当前请求的动态图文件返回,当然这里的静态文件跟Nginx是同一台服务器,我们也可以在另外一台服务器,然后通过反向代理和负载均衡配置过去就好了,只要搞清楚了最基本的流程,很多配置就很简单了,另外localtion后面其实是一个正则表达式,所以非常灵活
26.5. 正向代理
正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。当你需要把你的服务器作为代理服务器的时候,可以用Nginx来实现正向代理,但是目前Nginx有一个问题,那么就是不支持HTTPS,虽然我百度到过配置HTTPS的正向代理,但是到最后发现还是代理不了,当然可能是我配置的不对,所以也希望有知道正确方法的同志们留言说明一下。
resolver 114.114.114.114 8.8.8.8;
server {
resolver_timeout 5s;
listen 81;
access_log e:/wwwrootproxy.access.log;
error_log e:/wwwrootproxy.error.log;
location / {
proxy_pass http://$host$request_uri;
}
}
resolver是配置正向代理的DNS服务器,listen 是正向代理的端口,配置好了就可以在ie上面或者其他代理插件上面使用服务器ip+端口号进行代理了。
Nginx是支持热启动的,也就是说当我们修改配置文件后,不用关闭Nginx,就可以实现让配置生效,当然我并不知道多少人知道这个,反正我一开始并不知道,导致经常杀死了Nginx线程再来启动。。。Nginx从新读取配置的命令是 -
nginx -s reload
windows下面就是
nginx.exe -s reload
27.Nginx+PHP7源码安装配置
https://www.yiibai.com/nginx/nginx-php7-source-config.html
https://www.yiibai.com/nginx/compression-and-decompression.html#article-start
nginx.conf 配置文件详解
参考文档:
Taobao Nginx开发从入门到精通http://tengine.taobao.org/book/index.html
https://github.com/taobao/nginx-bookNginx 之二: nginx.conf 配置及基本优化 https://www.cnblogs.com/zhang-shijie/p/5428640.html
Nginx的超时timeout配置详解 https://www.jb51.net/article/131868.htm
nginx doc http://nginx.org/en/docs/
Nginx 核心模块 http://nginx.org/en/docs/http/ngx_http_core_module.html#location
指令文档列表 http://nginx.org/en/docs/ngx_core_module.html
变量文档列表 http://nginx.org/en/docs/varindex.html
nginx中文文档:http://www.nginx.cn/doc/index.html
nginx服务器主要通过nginx.conf进行配置,此文档用于记录配置详细说明。
很多配置主要是适用于linux上的nginx。
目录列表
[TOC]
说明
nginx.conf
中 注释标记是#
(井号)- 每一条指令都要以分号(;)结尾,参数通过空格分隔
- 配置文件指令分为简单指令(e.g. worker_processes)和块指令(e.g. events)
- 块指令通过
{}
来包含简单指令,如果一个块能包含另一个块,则这个块(block)叫做context
, (e.g. events, http, server, and location). - 对于有些指令,如
root
,一般配置在location
块中,但也可以配置在server
块中,这样,当location
中没有配置root
指令,就会使用在server
块中的root
指令的值。相当于是一个继承覆盖关系,子级有数据用子级的,没有就使用父级的。
配置文件中值可以含有单位,如keepalive_timeout 60s 50s;
,参考如下所示:
k,K | 千字节 |
---|---|
m,M | 兆字节 |
例如, "8k", "1m" 代表字节数计量.
时间符号缩写
ms | 毫秒 |
---|---|
s | 秒 |
m | 分钟 |
h | 小时 |
d | 日 |
w | 周 |
M | 一个月, 30天 |
y | 年, 365 天 |
例如, "1h 30m", "1y 6M". 代表 "1小时 30分", "1年零6个月".
配置文件基本格式如下
#global
worker_processes 1 ;
events{
worker_connections 1024;
}
http{
include mime.types;
root html;
server{
listen 8051 default;
location /{
root html;
index index.html;
}
}
}
示例
虚拟主机标准配置(简化) - A Default Catchall Virtual Host
http {
server {
listen 80 default;
server_name _ *;
access_log logs/default.access.log main;
location / {
index index.html;
root /var/www/default/htdocs;
}
}
}
两个虚拟主机(纯静态-html 支持) - Two Virtual Hosts, Serving Static Files
http {
server {
listen 80;
server_name www.domain1.com;
access_log logs/domain1.access.log main;
location / {
index index.html;
root /var/www/domain1.com/htdocs;
}
}
server {
listen 80;
server_name www.domain2.com;
access_log logs/domain2.access.log main;
location / {
index index.html;
root /var/www/domain2.com/htdocs;
}
}
}
在父文件夹中建立子文件夹以指向子域名 - Wildcard Subdomains in a Parent Folder
这是一个添加子域名(或是当DNS已指向服务器时添加一个新域名)的简单方法。需要注意的是,我已经将FCGI配置进该文件了。如果你只想使服务器为静态文件服务,可以直接将FCGI配置信息注释掉,然后将默认主页文件变成index.html。
这个简单的方法比起为每一个域名建立一个 vhost.conf 配置文件来讲,只需要在现有的配置文件中增加如下内容:
This is just a really easy way to keep adding new subdomains, or to add new domains automatically when DNS records are pointed at the server. Note that I have included FCGI here as well. If you want to just serve static files, strip out the FCGI config and change the default document to index.html. Rather than creating a new vhost.conf file for every domain, just create one of these:
server {
# Replace this port with the right one for your requirements
# 根据你的需求改变此端口
listen 80; #could also be 1.2.3.4:80 也可以是1.2.3.4:80的形式
# Multiple hostnames seperated by spaces. Replace these as well.
# 多个主机名可以用空格隔开,当然这个信息也是需要按照你的需求而改变的。
server_name star.yourdomain.com *.yourdomain.com www.*.yourdomain.com;
#Alternately: _ *
#或者可以使用:_ * (具体内容参见本维基其他页面)
root /PATH/TO/WEBROOT/$host;
error_page 404 http://yourdomain.com/errors/404.html;
access_log logs/star.yourdomain.com.access.log;
location / {
root /PATH/TO/WEBROOT/$host/;
index index.php;
}
# serve static files directly
# 直接支持静态文件 (从配置上看来不是直接支持啊)
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires 30d;
}
location ~ .php$ {
# By all means use a different server for the fcgi processes if you need to
# 如果需要,你可以为不同的FCGI进程设置不同的服务信息
fastcgi_pass 127.0.0.1:YOURFCGIPORTHERE;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /PATH/TO/WEBROOT/$host/$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_intercept_errors on;
}
location ~ /\.ht {
deny all;
}
}
官方完整示例
这是来自 Nginx官方网站 的一个例子。
user www www;
worker_processes 2;
pid /var/run/nginx.pid;
#[ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx.error_log info;
events {
worker_connections 2000;
# use [ kqueue | epoll | /dev/poll | select | poll ];
use kqueue;
}
http {
include conf/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
log_format download '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_range" "$sent_http_content_range"';
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;
output_buffers 1 32k;
postpone_output 1460;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
send_lowat 12000;
keepalive_timeout 75 20;
#lingering_time 30;
#lingering_timeout 10;
#reset_timedout_connection on;
server {
listen one.example.com;
server_name one.example.com www.one.example.com;
access_log /var/log/nginx.access_log main;
location / {
proxy_pass http://127.0.0.1/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
client_body_temp_path /var/nginx/client_body_temp;
proxy_connect_timeout 70;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_send_lowat 12000;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_temp_path /var/nginx/proxy_temp;
charset koi8-r;
}
error_page 404 /404.html;
location = /404.html {
root /spool/www;
}
location /old_stuff/ {
rewrite ^/old_stuff/(.*)$ /new_stuff/$1 permanent;
}
location /download/ {
valid_referers none blocked server_names *.example.com;
if ($invalid_referer) {
#rewrite ^/ http://www.example.com/;
return 403;
}
#rewrite_log on;
# rewrite /download/*/mp3/*.any_ext to /download/*/mp3/*.mp3
rewrite ^/(download/.*)/mp3/(.*)\..*$
/$1/mp3/$2.mp3 break;
root /spool/www;
#autoindex on;
access_log /var/log/nginx-download.access_log download;
}
location ~* \.(jpg|jpeg|gif)$ {
root /spool/www;
access_log off;
expires 30d;
}
}
}
配置详解
global/user(linux)
运行nginx服务器的用户,默认用户是nginx,可不设置
user nginx
global/worker_processes
可以指定启动的固定nginx进程数,或使用auto
,auto
是启动与当前CPU 线程相同的进程数,如CPU是四核八线程的就启动八个进程的Nginx工作进程。
worker_processes 4;
worker_processes auto;
global/worker_cpu_affinity
cpu亲和力配置,让不同的进程使用不同的cpu。默认Nginx是不进行cpu绑定的,绑定并不能是当前nginx进程独占以一核心CPU,但是可以保证此进程不会运行在其他核心上,这就极大减少了nginx 工作进程在不同cpu上的跳转,减少了CPU对进程的资源分配与回收,因此可以有效的提升nginx服务器的性能,配置如下:
四个线程CPU的配置
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;
八个线程CPU的配置
worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
确认CPU的核心数量(linux)
grep process /proc/cpuinfo | wc -l
global/worker_rlimit_nofile
配置nginx工作进程最大打开文件数(连接),可设置为系统优化后的ulimit -HSn
的结果
worker_rlimit_nofile 51200;
global/pid
nginx进程pid存放位置,每次启动nginx pid的值不一样
pid /application/nginx/nginx.pid;
global/error_log
设置错误日志存放文件位置和错误级别
error_log 指令的日志级别配置分为错误日志级别和调试日志级别,错误日志只能设置一个级别,而且错误日志必须书写在调试日志级别的前面,另外调试日志可以设置多个级别,其他配置方法可能无法满足需求。
错误日志级别: debug | info | notice | warn | error | crit|alert|emerg
调试日志级别:debug_core | debug_alloc | debug_mutex | debug_event | debug_http | debug_mail | debug_mysql
#指定错误日志路径
error_log logs/error.log;
error_log logs/debug.log debug;
error_log logs/info.log info ;
error_log logs/notice.log notice ;
error_log logs/warn.log warn ;
error_log logs/error.log error ;
error_log logs/crit.log crit ;
error_log logs/alert.log alert ;
error_log logs/emerg.log emerg ;
error_log logs/debug.log debug|debug_core ;
global/include
file是要导入的文件,支持相对路径,一般在html目录里面导入一个conf文件,并配置不同主机名的页面,编辑nginx.conf主配置文件:
include file;
如下所示
include /usr/local/nginx/conf.d/cms-site.conf;
在/usr/local/nginx/conf.d/
创建一个cms-site.conf,内容如下:
server {
listen 8090;
server_name cms.example.con;
location / {
root html;
index index1.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
global/events(scope)
events设置块,主要影响nginx服务器与用户的网络连接,比如是否允许同时接受多个网络连接,使用哪种事件驱动模型处理请求。
每个工作进程可以同时支持的最大连接数,是否开启对多工作进程下的网络连接进行序列化等。
events
{
use epoll;
worker_connections 1024;
accept_mutex on;
}
global/events/use
- epoll,是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能。
- epoll是库是Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和select和poll有很大的区别,epoll是poll的升级版,但是与poll的效率有很大的区别
- epoll的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮训检查这个表,以判断事件是否发生
- epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时epoll库的IO效率不随描述符数目增加而线性下降,因为它只会对内核上报的“活跃”的描述符进行操作。
- select,是在linux和windows平台都基本支持的 事件驱动模型库,并且在接口的定义也基本相同,只是部分参数的含义略有差异,最大并发限制1024,只最早期的事件驱动模型。
- poll,在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select库。
- rtsig,不是一个常用事件驱动,最大队列1024,不是很常用
- kqueue,用于支持BSD系列平台的高校事件驱动模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版本,NetBSD级以上版本及Mac OS X 平台上,该模型也是poll库的变种,因此和epoll没有本质上的区别,都是通过避免轮训操作提供效率。
- /dev/poll,用于支持unix衍生平台的高效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发Solaris系列平台的时候提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员将要见识的文件描述符加入这个设备,然后通过ioctl()调用来获取事件通知,因此运行在以上系列平台的时候请使用/dev/poll事件驱动机制。
- eventport,该方案也是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库看防止内核崩溃等情况的发生。
#使用epoll事件驱动,因为epoll的性能相比其他事件驱动要好很多
use epoll;
use kqueue;
use /dev/poll;
use select;
use poll;
use rtsig;
use eventport;
global/events/worker_connections
配置单个工作进程的最大连接数,通过worker_connections number;进行设置,numebr为整数,number的值不能大于操作系统能打开的最大的文件句柄数,使用ulimit -n可以查看当前操作系统支持的最大文件句柄数,默认为为1024。
worker_connections 1024;
global/events/accept_mutex
网络连接的优化,用于防止在同一个时刻只有一个请求的情况下,出现多个睡眠进程会被唤醒但只能有一个进程可获得请求的尴尬,如果不优化,在多进程的nginx会影响以部分性能。
优化同一时刻只有一个请求而避免多个睡眠进程被唤醒的设置,on为防止被同时唤醒,默认为off,因此nginx刚安装完以后要进行适当的优化。
accept_mutex on;
accept_mutex off;
global/events/multi_accept
相关链接:https://blog.csdn.net/zhxuewu/article/details/77935628
Nginx服务器的每个工作进程可以同时接受多个新的网络连接,但是需要在配置文件中配置,此指令默认为关闭,即默认为一个工作进程只能一次接受一个新的网络连接,打开后几个同时接受多个,配置语法如下:
#打开同时接受多个新网络连接请求的功能
multi_accept on;
multi_accept off;
global/http(scope)
http块是Nginx服务器配置中的重要部分,缓存、代理和日志格式定义等绝大多数功能和第三方模块都可以在这设置。
http块可以包含多个server块,而一个server块中又可以包含多个location块。
server块可以配置文件引入MIME-Type定义、日志自定义、是否启用sendfile、连接超时时间和单个链接的请求上限等。
http
{
include mime.types;
default_type application/octet-stream; #默认文件类型
#limit模块,可防范一定量的DDOS攻击
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
#第三方模块lua防火墙
lua_need_request_body on;
#lua_shared_dict limit 50m;
lua_package_path "/application/nginx/conf/waf/?.lua";
init_by_lua_file "/application/nginx/conf/waf/init.lua";
access_by_lua_file "/application/nginx/conf/waf/access.lua";
#设定请求缓存
server_names_hash_bucket_size 128;
client_header_buffer_size 512k;
large_client_header_buffers 4 512k;
client_max_body_size 100m;
#隐藏响应header和错误通知中的版本号
server_tokens off;
#开启高效传输模式
sendfile on;
#激活tcp_nopush参数可以允许把httpresponse header和文件的开始放在一个文件里发布,
#积极的作用是减少网络报文段的数量
tcp_nopush on;
#激活tcp_nodelay,内核会等待将更多的字节组成一个数据包,从而提高I/O性能
tcp_nodelay on;
#FastCGI相关参数:为了改善网站性能:减少资源占用,提高访问速度
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 128k;
#连接超时时间,单位是秒
keepalive_timeout 60;
#开启gzip压缩功能
gzip on;
#设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取。
#默认值是0,表示不管页面多大都进行压缩。建议设置成大于1K。如果小于1K可能会越压越大。
gzip_min_length 1k;
#压缩缓冲区大小。表示申请4个单位为16K的内存作为压缩结果流缓存,默认值是申请与原始数
#据大小相同的内存空间来存储gzip压缩结果。
gzip_buffers 4 16k;
#压缩版本(默认1.1,前端为squid2.5时使用1.0)用于设置识别HTTP协议版本,默认是1.1,
#目前大部分浏览器已经支持GZIP解压,使用默认即可。
gzip_http_version 1.0;
#压缩比率。用来指定GZIP压缩比,1压缩比最小,处理速度最快;9压缩比最大,传输速度快,
#但处理最慢,也比较消耗cpu资源。
gzip_comp_level 9;
#用来指定压缩的类型,“text/html”类型总是会被压缩
gzip_types text/plain application/x-javascript text/css application/xml;
#vary header支持。该选项可以让前端的缓存服务器缓存经过GZIP压缩的页面,例如用
#Squid缓存经过Nginx压缩的数据。
gzip_vary off;
#开启ssi支持,默认是off
ssi on;
ssi_silent_errors on;
#设置日志模式
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_for';
}
global/http/include mime.types
引入文件扩展名与类型映射表
在浏览器当中可以显示的内容有HTML/GIF/XML/Flash等内容,浏览器为取得这些资源需要使用MIME Type,即MIME是网络资源的媒体类型,Nginx作为Web服务器必须要能够识别全都请求的资源类型,在nginx.conf文件中引用了一个第三方文件,使用include导入:
include mime.types;
global/http/default_type
默认文件类型
default_type application/octet-stream;
global/http/server_tokens
当前使用的nginx可能会有未知的漏洞,如果被黑客使用将会造成无法估量的损失,但是我们可以将nginx的版本隐藏。
server_tokens on;
server_tokens off;
global/http/sendfile
是否调用 sendfile 函数(zero copy -->零copy方式)来输出文件,普通应用打开,可以大幅提升nginx的读文件性能,如果服务器是提供下载的就需要关闭。
后端程序负责把源文件打包加密生成目标文件,然后程序读取目标文件返回给浏览器;这种做法有个致命的缺陷就是占用大量后端程序资源,如果遇到一些访客下载速度巨慢,就会造成大量资源被长期占用得不到释放(如后端程序占用的CPU/内存/进程等),很快后端程序就会因为没有资源可用而无法正常提供服务。通常表现就是 nginx报502错误,而sendfile打开后配合location可以实现有nginx检测文件使用存在,如果存在就有nginx直接提供静态文件的浏览服务,因此可以提升服务器性能.
sendfile on;
sendfile off;
global/http/log_format
格式中定义要保存的具体日志内容:
如定义一个格式叫做main
:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
定义一个格式叫做download
:
log_format download '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_range" "$sent_http_content_range"';
将日志定义为json格式:
在使用日志分析工具如ELK对访问日志做统计的时候,就需要将日志格式定义为json格式,以便于取相应字段的key做统计,完整的定义如下:
log_format logstash_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"url":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"agent":"$http_user_agent",'
'"status":"$status"}';
server{
access_log /var/log/nginx/samsung1.access.log logstash_json;
}
global/http/keepalive_timeout
同 global/http/server/location/keepalive_timeout
https://blog.csdn.net/dream_flying_bj/article/details/54709549
global/http/limit模块(limit_req_zone|limit_conn_zone)
详情查看
https://www.cnblogs.com/wjoyxt/p/6128183.html
https://blog.csdn.net/keketrtr/article/details/75315330
可防范一定量的DDOS攻击
用来存储session会话的状态,如下是为session分配一个名为one的10M的内存存储区,限制了每秒只接受一个ip的一次请求 1r/s
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=addr:10m;
global/http/upstream
反向代理负载均衡设定部分upstream表示负载服务器池,定义名字为backend_server的服务器池
设置由 fail_timeout 定义的时间段内连接该主机的失败次数,以此来断定 fail_timeout 定义的时间段内该主机是否可用。默认情况下这个数值设置为 1。零值的话禁用这个数量的尝试。
设置在指定时间内连接到主机的失败次数,超过该次数该主机被认为不可用。
这里是在30s内尝试2次失败即认为主机不可用!
upstream backend_server {
server 10.254.244.20:81 weight=1 max_fails=2 fail_timeout=30s;
server 10.254.242.40:81 weight=1 max_fails=2 fail_timeout=30s;
server 10.254.245.19:81 weight=1 max_fails=2 fail_timeout=30s;
server 10.254.243.39:81 weight=1 max_fails=2 fail_timeout=30s;
}
global/http/server(scope)
global/http/server/gzip
参考 https://blog.csdn.net/zhuyiquan/article/details/52709864
开启/关闭Gzip
gzip on;
gzip off;
global/http/server/gzip_min_length
启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
global/http/server/gzip_buffers
设置用于处理请求压缩的缓冲区数量和大小。比如32 4K表示按照内存页(one memory page)大小以4K为单位(即一个系统中内存页为4K),申请32倍的内存空间。建议此项不设置,使用默认值。
gzip_buffers 32 4k|16 8k;
global/http/server/gzip_http_version
设置gzip压缩针对的HTTP协议版本,用了反向代理的话,末端通信是HTTP/1.0,默认是HTTP/1.1。
如果我们使用了proxy_pass进行反向代理,那么nginx和后端的upstream server之间默认是用HTTP/1.0协议通信的。如果我们的Cache Server也是nginx,而前端的nginx没有开启gzip。同时,我们后端的nginx上没有设置gzip_http_version为1.0,那么Cache的url将不会进行gzip压缩。
gzip_http_version 1.1;
global/http/server/gzip_comp_level
zip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间。
- 随着压缩级别的升高,压缩比有所提高,但到了级别6后,很难再提高;
- 随着压缩级别的升高,处理时间明显变慢;
- gzip很消耗cpu的性能,高并发情况下cpu达到100%
因此,建议:
一方面,不是压缩级别越高越好,其实gzi_comp_level 1的压缩能力已经够用了,后面级别越高,压缩的比例其实增长不大,反而很吃处理性能。
另一方面,压缩一定要和静态资源缓存相结合,缓存压缩后的版本,否则每次都压缩高负载下服务器肯定吃不住。
gzip_comp_level 1;
global/http/server/gzip_types
进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
global/http/server/gzip_vary
是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
gzip_vary off;
global/http/server/gzip_disable
禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";
global/http/server/access_log
访问日志是记录客户端即用户的具体请求内容信息,全局配置模块中的error_log是记录nginx服务器运行时的日志保存路径和记录日志的level,因此有着本质的区别,而且Nginx的错误日志一般只有一个,但是访问日志可以在不同server中定义多个,定义一个日志需要使用access_log指定日志的保存路径,使用http 块 中定义的log_format指定日志的格式。
使用main
格式( global/http/log_format)存储访问日志到access-main.log
access_log logs/access-main.log main;
global/http/server/listen
使用命令listen,可以配置监听IP+端口,端口或监听unix socket:
#监听本机的IPV4和IPV6的8090端口,等于listen *:8090
listen 8090;
listen *:8090
#监听指定地址的8090端口
listen 192.168.0.1:8090;
#监听unix socket
listen Unix:/www/file
global/http/server/server_name
当前server的名称,当访问此名称的时候nginx会调用当前 server_name 内部的配置进程匹配。
基于域名和IP的虚拟主机
server_name localhost;
#多个域名用空格间隔即可
server_name localhost www.a.com;
#IP是本机的网卡IP地址
server_name 192.168.0.2;
global/http/server/error_page
出现错误码时跳转到的错误页面的文件位置
error_page 500 502 503 504 /50x.html;
#location处理对应的不同错误码的页面定义到/50x.html,这个跟对应其server中定义的目录下。
location = /50x.html {
root html; #定义默认页面所在的目录
}
global/http/server/client_header_timeout
客户端向服务端发送一个完整的 request header 的超时时间。如果客户端在指定时间内没有发送一个完整的 request header,Nginx 返回 HTTP 408(Request Timed Out)。
用于指定来自客户端请求头的headerbuffer大小,对于大多数请求,1kb的缓冲区大小已经足够,如果自定义了消息头部或有更大的cookie,可以增加缓冲区大小。
client_header_timeout 10s;
global/http/server/tcp_nopush
官方:
tcp_nopush
Syntax: tcp_nopush on | off
Default: off
Context: http
server
location
Reference: tcp_nopush
This directive permits or forbids the use of thesocket options TCP_NOPUSH on FreeBSD or TCP_CORK on Linux. This option is onlyavailable when using sendfile.
Setting this option causes nginx to attempt to sendit’s HTTP response headers in one packet on Linux and FreeBSD 4.x
You can read more about the TCP_NOPUSH and TCP_CORKsocket options here.
linux 下是tcp_cork,上面的意思就是说,当使用sendfile函数时,tcp_nopush才起作用,它和指令tcp_nodelay是互斥的。tcp_cork是linux下tcp/ip传输的一个标准了,这个标准的大概的意思是,一般情况下,在tcp交互的过程中,当应用程序接收到数据包后马上传送出去,不等待,而tcp_cork选项是数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞,已经是默认了。
也就是说tcp_nopush = on 会设置调用tcp_cork方法,这个也是默认的,结果就是数据包不会马上传送出去,等到数据包最大时,一次性的传输出去,这样有助于解决网络堵塞。
以快递投递举例说明一下(以下是我的理解,也许是不正确的),当快递东西时,快递员收到一个包裹,马上投递,这样保证了即时性,但是会耗费大量的人力物力,在网络上表现就是会引起网络堵塞,而当快递收到一个包裹,把包裹放到集散地,等一定数量后统一投递,这样就是tcp_cork的选项干的事情,这样的话,会最大化的利用网络资源,虽然有一点点延迟。
对于nginx配置文件中的tcp_nopush,默认就是tcp_nopush,不需要特别指定,这个选项对于www,ftp等大文件很有帮助.
global/http/server/tcp_nodelay
TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。 John Nagle是Nagle算法的发明人,后者就是用他的名字来命名的,他在1984年首次用这种方法来尝试解决福特汽车公司的网络拥塞问题(欲了解详情请参看IETF RFC 896)。他解决的问题就是所谓的silly window syndrome,中文称“愚蠢窗口症候群”,具体含义是,因为普遍终端应用程序每产生一次击键操作就会发送一个包,而典型情况下一个包会拥有一个字节的数据载荷以及40个字节长的包头,于是产生4000%的过载,很轻易地就能令网络发生拥塞,。 Nagle化后来成了一种标准并且立即在因特网上得以实现。它现在已经成为缺省配置了,但在我们看来,有些场合下把这一选项关掉也是合乎需要的。
现在让我们假设某个应用程序发出了一个请求,希望发送小块数据。我们可以选择立即发送数据或者等待产生更多的数据然后再一次发送两种策略。如果我们马上发送数据,那么交互性的以及客户/服务器型的应用程序将极大地受益。如果请求立即发出那么响应时间也会快一些。以上操作可以通过设置套接字的TCP_NODELAY = on 选项来完成,这样就禁用了Nagle 算法。
另外一种情况则需要我们等到数据量达到最大时才通过网络一次发送全部数据,这种数据传输方式有益于大量数据的通信性能,典型的应用就是文件服务器。应用 Nagle算法在这种情况下就会产生问题。但是,如果你正在发送大量数据,你可以设置TCP_CORK选项禁用Nagle化,其方式正好同 TCP_NODELAY相反(TCP_CORK和 TCP_NODELAY是互相排斥的)。
global/http/server/location(scope)
location其实是server的一个指令,为nginx服务器提供比较多而且灵活的指令,都是在location中提现的,主要是基于nginx接受到的请求字符串,对用户请求的UIL进行匹配,并对特定的指令进行处理,包括地址重定向、数据缓存和应答控制等功能都是在这部分实现,另外很多第三方模块的配置也是在location模块中配置。
在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最高的一个uri,uri是用户请求的字符串,即域名后面的web文件路径,然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理此请求。
location 正则匹配的语法:
= #用于标准uri前,需要请求字串与uri完全匹配,如果匹配成功就停止向下匹配并立即处理请求。
~ #区分大小写
~* #不区分大写
!~ #区分大小写不匹配
!~* #不区分大小写不匹配
^ #匹配以什么开头
$ #匹配以什么结尾
\ #转义字符。可以转. * ?等
* #代表任意长度的任意字符
-f和!-f #用来判断是否存在文件
-d和!-d #用来判断是否存在目录
-e和!-e #用来判断是否存在文件或目录
-x和!-x #用来判断文件是否可执行
常见http状态码:
200 #请求成功,即服务器返回成功
301 #永久重定向
302 #临时重定向
403 #禁止访问,一般是服务器权限拒绝
400 #错误请求,请求中有语法问题,或不能满足请求。
403 #服务器权限问题导致无法显示
404 #服务器找不到用户请求的页面
500 #服务器内部错误,大部分是服务器的设置或内部程序出现问题
501 #没有将正在访问的网站设置为浏览器所请求的内容
502 #网关问题,是代理服务器请求后端服务器时,后端服务器不可用或没有完成 相应网关服务器,这通常是反向代理服务器下面的节点出问题导致的。
503 #服务当前不可用,可能是服务器超载或停机导致的,或者是反向代理服务器后面没有可以提供服务的节点。
504 #网关超时,一般是网关代理服务器请求后端服务器时,后端服务器没有在指定的时间内完成处理请求,多数是服务器过载导致没有在特定的时间内返回数据给前端代理服务器。
505 #该网站不支持浏览器用于请求网页的HTTP协议版本(最为常见的是HTTP/1.1)
global/http/server/location/root
用于简化访问资源的url,默认是相对路径,可以使用绝对路径配置。
比如一个icon文件夹的路径是html/content/image/icon
,使用默认匹配,访问的时候路径为localhost/content/image/icon
(nginx默认以html为根目录),
想要简化访问url为 localhost/icon
,则可以如下配置,因此root的作用就是简化location的路径,访问的虽然是/icon
,实际上文件查找是在html/content/image/
+/icon
里面找文件,因此/icon
目录一定存在,否则应该使用alias
;
指定文件路径结果是:root路径+location路径
location /icon {
root html/content/image/;
}
global/http/server/location/alias
也是用于定位文件位置,不过这个就像路由,访问的url和实际目录并不相同。
按照上面的例子,比如访问的仍然是/icon
,实际上查找的文件路径是html/content/image/qq-icon
。
指定文件路径结果是:使用alias路径替换location路径
location /icon {
alias html/content/image/qq-icon;
}
global/http/server/location/index
默认页面的名称,优先级从左往右递减。
index index.html index.htm index.php;
global/http/server/location/sendfile_max_chunk
nginx工作进程每次调用sendfile()传输的数据最大不能超出这个值,默认值为0表示无限制,可以设置在http/server/location模块中。
sendfile_max_chunk 512k;
global/http/server/location/keepalive_timeout
HTTP 是一种无状态协议,客户端向服务器发送一个 TCP 请求,服务端响应完毕后断开连接。
如果客户端向服务器发送多个请求,每个请求都要建立各自独立的连接以传输数据。
HTTP 有一个 KeepAlive 模式,它告诉 webserver 在处理完一个请求后保持这个 TCP 连接的打开状态。若接收到来自客户端的其它请求,服务端会利用这个未被关闭的连接,而不需要再建立一个连接。
KeepAlive 在一段时间内保持打开状态,它们会在这段时间内占用资源。占用过多就会影响性能。
Nginx 使用 keepalive_timeout 来指定 KeepAlive 的超时时间(timeout)。指定每个 TCP 连接最多可以保持多长时间。Nginx 的默认值是 75 秒,有些浏览器最多只保持 60 秒,所以可以设定为 60 秒。若将它设置为 0,就禁止了 keepalive 连接。
用户和服务器建立连接后客户端分配keep-alive链接超时时间,服务器将在这个超时时间过后关闭链接,我们将它设置低些可以让ngnix持续工作的时间更长,1.8.1默认为65秒,一般不超过120秒。
keepalive_timeout 65;
设置Nginx服务器与客户端保持连接的时间是60秒,到60秒后服务器与客户端断开连接,50s是使用Keep-Alive消息头与部分浏览器如 chrome等的连接事件,到50秒后浏览器主动与服务器断开连接。
设置后会在发送给客户端应答报文头部中显示的超时时间设置为50s:如不设置客户端将不显示超时时间
keepalive_timeout 60 50;
keepalive_timeout 60s 50s;
浏览器收到的服务器返回的报文将如下显示:
Connection: keep-alive
Keep-Alive: timeout=50
如果设置为0表示关闭会话保持功能
keepalive_timeout 0;
浏览器收到的服务器返回的报文将如下显示:
Connection:close
global/http/server/location/client_body_timeout
指定客户端与服务端建立连接后发送 request body 的超时时间。如果客户端在指定时间内没有发送任何内容,Nginx 返回 HTTP 408(Request Timed Out)。
client_body_timeout 20s;
global/http/server/location/send_timeout
https://www.cnblogs.com/wajika/p/6573014.html
Http核心模块指令,指定了发送给客户端应答后的超时时间,Timeout是指没有进入完整established状态,只完成了两次握手,如果超过这个时间客户端没有任何响应,nginx将关闭与客户端的连接。
send_timeout 10s;
nginx优化
sysctl.conf 针对IPv4内核的7个参数的配置优化:
net.core.netdev_max_backlog
每个网络接口的处理速率比内核处理包的速度快的时候,允许发送队列的最大数目。
sysctl -a | grep max_backlog
net.core.netdev_max_backlog = 1000 这里默认是1000,可以设置的大一些,比如:
net.core.netdev_max_backlog = 102400
net.core.somaxconn
用于调节系统同时发起的TCP连接数,默认值一般为128,在客户端存在高并发请求的时候,128就变得比较小了,可能会导致链接超时或者重传问题。
net.core.somaxconn = 128 #默认为128,高并发的情况时候要设置大一些,比如:
net.core.somaxconn = 102400
net.ipv4.tcp_max_orphans
设置系统中做多允许多少TCP套接字不被关联到任何一个用户文件句柄上,如果超出这个值,没有与用户文件句柄关联的TCP套接字将立即被复位,同时给出警告信息,这个值是简单防止DDOS(Denial of service)的攻击,在内存比较充足的时候可以设置大一些:
net.ipv4.tcp_max_orphans = 32768 #默认为32768,可以改该打一些:
net.ipv4.tcp_max_orphans = 102400
net.ipv4.tcp_max_syn_backlog
用于记录尚未收到客户度确认消息的连接请求的最大值,一般要设置大一些:
net.ipv4.tcp_max_syn_backlog = 256 #默认为256,设置大一些如下:
net.ipv4.tcp_max_syn_backlog = 102400
net.ipv4.tcp_timestamps
用于设置时间戳,可以避免序列号的卷绕,有时候会出现数据包用之前的序列号的情况,此值默认为1表示不允许序列号的数据包,对于Nginx服务器来说,要改为0禁用对于TCP时间戳的支持,这样TCP协议会让内核接受这种数据包,从而避免网络异常,如下:
net.ipv4.tcp_timestamps = 1 #默认为1,改为0,如下:
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries
用于设置内核放弃TCP连接之前向客户端发生SYN+ACK包的数量,网络连接建立需要三次握手,客户端首先向服务器发生一个连接请求,服务器收到后由内核回复一个SYN+ACK的报文,这个值不能设置过多,会影响服务器的性能,还会引起syn攻击:
net.ipv4.tcp_synack_retries = 5 #默认为5,可以改为1避免syn攻击
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries
与上一个功能类似,设置为1即可:
net.ipv4.tcp_syn_retries = 5 #默认为5,可以改为1
net.ipv4.tcp_syn_retries = 1
nginx.conf配置文件中针对CPU的2个优化参数
woker_precess #设置Nginx 启动多少个工作进程的数量
woker_cpu_affinit #固定Nginx 工作进程所运行的CPU核心
nginx.conf配置文件中与网络相关的4个指令
设置Nginx服务器与客户端保持连接的时间是60秒,到60秒后服务器与客户端断开连接,50s是使用Keep-Alive消息头与部分浏览器如 chrome等的连接事件,到50秒后浏览器主动与服务器断开连接。
keepalived_timeout 60 50;
Http核心模块指令,指定了发送给客户端应答后的超时时间,Timeout是指没有进入完整established状态,只完成了两次握手,如果超过这个时间客户端没有任何响应,nginx将关闭与客户端的连接。
sendtime_out 10s
用于指定来自客户端请求头的headerbuffer大小,对于大多数请求,1kb的缓冲区大小已经足够,如果自定义了消息头部或有更大的cookie,可以增加缓冲区大小。
client_header_timeout 4k
设置是否允许,Nginx在已经得到一个新连接的通知时,接收尽可能更多的连接。
multi_accept on;
nginx.conf配置文件中与驱动模型相关的8个指令
use;
woker_process;
woker_connections;
woker_rlimit_sigpending;
#用于设置Nginx 在/dev/poll 模型下Nginx服务器可以与内核之间传递事件的数量,前一个设置传递给内核的事件数量,后一个设置从内核读取的事件数量,默认为512。
devpoll_changes 和 devpoll_events
#设置在kqueue模型下Nginx服务器可以与内核之间传递事件的数量,前一个设置传递给内核的事件数量,后一个设置从内核读取的事件数量,默认为512。
kqueue_changes 和 kqueue_events
epoll_events
rtsig_signo
rtsig_overflow
apache vs nginx
- nginx相对于apache的优点
- 轻量级,同样起web 服务,比apache占用更少的内存及资源
- 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能
- 高度模块化的设计,编写模块相对简单
- 社区活跃,各种高性能模块出品迅速啊
- apache 相对于nginx 的优点
- rewrite ,比nginx 的rewrite 强大
- 动态页面
- 模块超多,基本想到的都可以找到
- 少bug ,nginx 的bug 相对较多
- 超稳定
存在就是理由,一般来说,需要性能的web 服务,用nginx 。如果不需要性能只求稳定,那就apache 吧。
后者的各种功能模块实现得比前者好,例如ssl 的模块就比前者好,可配置项多。这里要注意一点,epoll(freebsd 上是 kqueue )网络 IO 模型是nginx 处理性能高的根本理由,但并不是所有的情况下都是epoll 大获全胜的,如果本身提供静态服务的就只有寥寥几个文 件,apache 的select 模型或许比epoll 更高性能。
当然,这只是根据网络IO 模型的原理作的一个假设,真正的应用还是需要实测了再说 的。
作为 Web 服务器,相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点 使 Nginx 尤其受到虚拟主机提供商的欢迎。
在高连接并发的情况下,Nginx是Apache服务器不错的替代品。Nginx在美国是做虚拟主机生意的老板们经常选择的软件平台之一. 能够支持高达 50,000 个并发连接数的响应, 感谢Nginx为我们选择了 epoll and kqueue 作为开发模型.
- Nginx 配置简洁, Apache 复杂 。
- Nginx 静态处理性能比 Apache 高 3倍以上
- Apache 对 PHP 支持比较简单,Nginx 需要配合其他后端用
- Apache 的组件比 Nginx 多
- 现在 Nginx 才是 Web 服务器的首选
最核心的区别在于apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程
nginx处理静态文件好,耗费内存少.但无疑apache仍然是目前的主流,有很多丰富的特性.所以还需要搭配着来.当然如果能确定nginx就适合需求,那么使用nginx会是更经济的方式. apache有先天不支持多核心处理负载鸡肋的缺点,建议使用nginx做前端,后端用apache。大型网站建议用nginx自代的集群功能
从个人过往的使用情况来看,nginx的负载能力比apache高很多。最新的服务器也改用nginx了。而且nginx改完配置能-t
测试一下配置有没 有问题,apache重启的时候发现配置出错了,会很崩溃,改的时候都会非常小心翼翼。现在看有好多集群站,前端nginx抗并发,后端apache集群, 配合的也不错。
nginx处理动态请求是鸡肋,一般动态请求要apache去做,nginx只适合静态和反向。
从我个人的经验来看,nginx是很不错的前端服务器,负载性能很好,在老奔上开nginx,用webbench模拟10000个静态文件请求毫不吃力。apache对php等语言的支持很好,此外apache有强大的支持网路,发展时间相对nginx更久。
Nginx优于apache的主要两点:
- Nginx本身就是一个反向代理服务器
- Nginx支持7层负载均衡;其他的当然,Nginx可能会比 apache支持更高的并发,但是根据NetCraft的统计,2011年4月的统计数据,Apache依然占有62.71%,而Nginx是 7.35%,因此总得来说,Aapche依然是大部分公司的首先,因为其成熟的技术和开发社区已经也是非常不错的性能。
你对web server的需求决定你的选择。大 部分情况下nginx都优于Aapche,比如说静态文件处理、PHP-CGI的支持、反向代理功能、前端Cache、维持连接等等。在 Apache+PHP(prefork)模式下,如果PHP处理慢或者前端压力很大的情况下,很容易出现Apache进程数飙升,从而拒绝服务的现象。
可以看一下nginx lua模块:https://www.nginx.com/resources/wiki/modules/lua/ , https://github.com/openresty/lua-nginx-module#name , 比nginx多的模块,可直接用lua实现apache是最流行的,why?大多数人懒得更新到nginx或者学新事物。
对于nginx,我喜欢它配置文件写的很简洁,正则配置让很多事情变得简单运行效率高,占用资源少,代理功能强大,很适合做前端响应服务器 。
Apache在处理动态有优势,Nginx并发性比较好,CPU内存占用低,如果rewrite频繁,那还是Apache吧。
nginx QA
1.linux 中 nginx的默认日志目录在哪里?
nginx访问日志的默认路径在/var/log/nginx
。
2.如何在存在nginx代理的情况下尽可能获取到用户的真实IP?
参考链接:https://www.cnblogs.com/nx520zj/p/6031337.html
nginx反向代理配置时,一般会添加下面的配置:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
其中第一行关于host的配置,是关于域名传递的配置,余下跟IP相关。
需要注意的是并不能完全的到真实的IP地址。因为IP地址是可以伪造的。所以大家可以通过这种方式取得。但是一定要做一些特殊的判断及其处理,防止插入到数据库中,引起异常现象。
下面是在 asp.net core 中的实现
/// <summary>
/// 获取客户端ip地址
/// </summary>
/// <param name="result"></param>
private string GetClientIp(Microsoft.AspNetCore.Http.HttpRequest request)
{
//避免nginx代理后导致ip地址是nginx代理服务器的ip
string ip = request.Headers["x-forwarded-for"];
if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
{
ip = request.Headers["Proxy-Client-IP"];
}
if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
{
ip = request.Headers["X-Real-IP"];
}
if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
{
ip = request.Headers["WL-Proxy-Client-IP"];
}
if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
{
ip = request.Host.Host;
}
if (ip == null || ip.Length == 0 || string.Equals("unknown", ip, StringComparison.OrdinalIgnoreCase))
{
ip = request.HttpContext.Connection.RemoteIpAddress.ToString();
}
//可能存在如下格式:X-Forwarded-For: client, proxy1, proxy2
if (ip.Contains(", "))
{
//如果存在多个反向代理,获得的IP是一个用逗号分隔的IP集合,取第一个
//X-Forwarded-For: client 第一个
string[] ipaddrs = ip.Split(new string[1] { ", " }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < ipaddrs.Length; i++)
{
if (ipaddrs[i] != "")
{
if (!IsInnerIP(ipaddrs[i]))//判断是否为内网IP
{
System.Net.IPAddress realip;
if (System.Net.IPAddress.TryParse(ipaddrs[i], out realip) && ipaddrs[i].Split('.').Length == 4)
{//合法IP
return ipaddrs[i];
}
else
{//非法IP
//IP地址不符合规范
}
}
}
}
ip = ipaddrs[0];//默认取第一个ip地址
}
return ip;
}
/// <summary>
/// 判断IP地址是否为内网IP地址
/// </summary>
/// <param name="ipAddress">IP地址字符串</param>
/// <returns></returns>
private bool IsInnerIP(String ipAddress)
{
bool isInnerIp = false;
ulong ipNum = ParseIpToUlong(ipAddress);
/**
私有IP:A类 10.0.0.0-10.255.255.255
B类 172.16.0.0-172.31.255.255
C类 192.168.0.0-192.168.255.255
当然,还有127这个网段是环回地址
**/
ulong aBegin = ParseIpToUlong("10.0.0.0");
ulong aEnd = ParseIpToUlong("10.255.255.255");
ulong bBegin = ParseIpToUlong("172.16.0.0");
ulong bEnd = ParseIpToUlong("172.31.255.255");
ulong cBegin = ParseIpToUlong("192.168.0.0");
ulong cEnd = ParseIpToUlong("192.168.255.255");
isInnerIp = IsInIpRange(ipNum, aBegin, aEnd) || IsInIpRange(ipNum, bBegin, bEnd) ||
IsInIpRange(ipNum, cBegin, cEnd) || ipAddress.StartsWith("127");
return isInnerIp;
}
/// <summary>
/// 把IP地址转换为Long型数字
/// </summary>
/// <param name="ipAddress">IP地址字符串</param>
/// <returns></returns>
private ulong ParseIpToUlong(string ipAddress)
{
byte[] bytes = System.Net.IPAddress.Parse(ipAddress).GetAddressBytes();
ulong ret = 0;
foreach (byte b in bytes)
{
ret <<= 8;
ret |= b;
}
return ret;
//同等实现
//var arr = ipAddress.Split('.').Select(int.Parse).ToList();
//return (ulong)(arr[0] * Math.Pow(256, 3) + arr[1] * Math.Pow(256, 2) + arr[2] * Math.Pow(256, 1) + arr[3]);
}
/// <summary>
/// 判断ip地址转换为long型后是否在定义的ip范围内
/// </summary>
/// <param name="testIp">测试ip</param>
/// <param name="beginIp">起始ip</param>
/// <param name="endIp">结束ip</param>
/// <returns></returns>
private bool IsInIpRange(ulong testIp, ulong beginIp, ulong endIp)
{
return (testIp >= beginIp) && (testIp <= endIp);
}
3.nginx配置项目到另一个项目的子目录?
location /e{
proxy_pass http://edoc2/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
#$http_host:$server_port;#这个server_port不能随便加
client_max_body_size 0;
proxy_http_version 1.1;
proxy_request_buffering off;
index index.html index.htm;
allow all;
}
4.nginx如何配置目录浏览?
在location server 或 http段中加入autoindex on;
这个参数
autoindex_exact_size off
; 默认为on,显示出文件的确切大小,单位是bytes。 改为off后,显示出文件的大概大小,单位是kB或者MB或者GB
autoindex_localtime on
; 默认为off,显示的文件时间为GMT时间。
注意:改为on后,显示的文件时间为文件的服务器时间
如果目录中有中文文件名,可能某些浏览器会显示成乱码,需要设置一下字符编码:charset utf-8;
location / {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
charset utf-8;
}
5.某些东东不工作 (URL重写, 代理, 路径, ...)
例如: 如URL重写(rewrite)不工作了或者是unix的路径(/$PATH)的问题云云...
请仔细阅读 [NginxDebugging] 并且 逐行 查看错误日志。
如果你没找到错误 打起精神 试着到IRC或邮件列表里说明一下你碰到的问题。
6.有没有其它类似的Web服务器
关于各自的优缺点请使用自己喜欢的搜索引挚查找 ;-)
7.对于chroot的支持是否在计划之中?
有人知道吗?
8.在什么情况下使用Nginx比使用squid要好? 反之亦然。
大体上来说nginx主要用于反向加速代理而不是像squid那样做为常规代理服务器。Nginx的最大优势在于高负载情况下内存和CPU的低消耗。 我不认为squid能给你带来比nginx更好的性能。
9.怎么让Nginx成为以postfix做为后端的SMTP代理?
有人知道不?
10.Nginx使用什么算法来实现负载均衡? 它能实现基于连接数的负载均衡吗?
目前Nginx使用简单的轮巡算法,所以无法做基本链接计数的负载均衡。 这个可能会在将来的版本中有所改变。
11.我能关闭从代理服务器到后端服务器的缓存吗或者使用上传进度特性?
基于 太多人询问下面的问题:
- 我能为了得到上传进度而关闭代理的缓存吗
- 使用nginx我怎么才能给用户显示上传进度
- ...
到目前为止 (2007-Apr-26) 还没有办法关闭到后端服务器的缓存.
12.window下nginx的proxy_pass指向localhost访问时非常慢
https://blog.csdn.net/gnail_oug/article/details/70141010
https://blog.csdn.net/CodeFarmer_/article/details/86481744
https://www.213.name/archives/1521
把localhost替换为127.0.0.1重启nginx即可
不过为什么会出现这个问题还是不清楚,没有去深究localhsot
和127.0.0.1
。
13.Nginx之——web网站图片显示过慢 超大附件不完全下载的解决方法
https://blog.csdn.net/l1028386804/article/details/50549921
location /mypm {
root /home/mypmcc/mypm20100914;
index index.jhtml index.html login_page.jhtml;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080 ;
client_max_body_size 100m;
client_body_buffer_size 128k;
proxy_connect_timeout 600;#nginx跟后端服务器连接超时时间(代理连接超时)
proxy_read_timeout 600; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_send_timeout 6000;#后端服务器数据回传时间(代理发送超时)
proxy_buffer_size 32k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 64k;#proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_busy_buffers_size 128k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 512k;#设定缓存文件夹大小,大于这个值,将从upstream服务器传
}
问题就出在proxy_temp_file_write_size上,当你的文件超过该参数设置的大小时,nginx会先将文件写入临时目录(缺省为nginx安装目下/proxy_temp目录),或直接更改proxy_temp_file_write_size的值。
缺省nginx是以nobody身份启动的,用ls -al 命令查看proxy_temp目录 nobody是proxy_temp目录的所有者,怪了那为什么没权限呢,接下来我查看proxy_temp的父目录既nginx安装目录。发现 nobody竞然没权限,怪不得会出上面的问题。IT网,http://www.it.net.cn
然后设置任何人都可以写 proxy_temp目录,重启 nginx 即可解决。
14.Nginx location 的匹配优先级怎么算?
15.Nginx 反向代理到二级子目录怎么配置?
server{
listen 7500 default;
server_name 127.0.0.1;
location / {
proxy_pass http://site1;
}
location /site1 {
#注意要加斜杠,不然会路径拼接
proxy_pass http://127.0.0.1:7110/;
}
location /site1s1/ {
proxy_pass http://127.0.0.1:7111/;
}
location /site1s2/ {
proxy_pass http://127.0.0.1:7112/;
}
}
注意proxy_pass http://127.0.0.1:7110/;
后面的斜杠,如果没有斜杠,则会访问 http://127.0.0.1:7110/site1
。
发表评论