Nginx使用的详细解读(一)
- Nginx的一些有用的废话
- Nginx日志,HTTP请求
- Nginx基础官方模块
- Nginx 关联的模块
- Nginx 客户端状态模块 [http_stub_status_module](http://nginx.org/en/docs/http/ngx_http_stub_status_module.html)
- Nginx 随机主页模块 [http_random_index_module](http://nginx.org/en/docs/http/ngx_http_random_index_module.html)
- Nginx HTTP响应内容替换模块[http_sub_module](http://nginx.org/en/docs/http/ngx_http_sub_module.html)
- Nginx 请求限制模块
- Nginx 访问控制模块 [http_access_module](http://nginx.org/en/docs/http/ngx_http_access_module.html)
- Nginx 基于用户信任的访问控制 [http_auth_basic_module](http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html)
Nginx的一些有用的废话
Nginx的历史
Nginx是什么?
Nginx 是一个开源,高性能,可靠的http中间件代理服务。第一个公开版本0.1.0发布于2004年10月4日。那么问题来了,2014年之前用啥子了 ?
答曰:阿帕奇的Httpd、微软的IIS、和谷歌的GWS
使用Nginx原因
-
IO多路复用epoll
多个描述符的I/O操作能在一个线程内并发交替的顺序完成,叫I/O复用,这里的复用指的是同一个线程 -
轻量级
-
CPU亲和
为什么需要CPU亲和,Nginx有多个进程worker
什么是CPU亲和:把CPU核心和Nginx工作进程绑定方式,把每一个worker进程固定在一个CPU上执行,减少切换CPU的cache miss,获取更好的性能 -
sendfile工作机制
常规:In File->Server Kernel space->Server User space ->Server Kernel space-> Out File
linux 2.2 零拷贝文件拷贝只通过 : In File->Server Kernel space-> Out File
实现多路复用的方式
I/O多路复用的实现方式selecet、poll、epoll
-
select: FD没有就绪之前block阻塞,维护一个FD列表,就绪以后线性遍历文件描述符列表,等待对应的进行完成数据拷贝 ,select模式存在两个问题
1)能够监测的文件描述符数量存在限制1024
2)线性扫描效率低下 -
epoll模型:(Linux2.6版本以后),相对于select优势
1)每当FD就绪,采用系统回调函数将FD放入,效率更高
2)最大连接无限制
Nginx的安装
yum install nginx
多了不解释了 。。。。
还有几个常用的命令
service nginx start /// 启动
service nginx restart /// 重启
service nginx stop 停止服务
nginx -t -c /etc/nginx/conf.d/*.conf /// 检查配置文件是否有问题
nginx -s reload -c /etc/nginx/conf.d/*.conf /// 重载配置文件,不重启nginx重新加载配置文件
nginx -v /// 小v 查看版本
nginx -V /// 大V 参数版本参数 ,我没有写错,都是V
安装应该不存在什么问题,若真有问题,哈哈,我也不管,反正我的Nginx没有问题
Nginx的版本参数
安装完成以后执行
nginx -V
参数 | 作用 |
---|---|
–prefix=/usr/share/nginx –sbin-path=/usr/sbin/nginx | 配置Nginx命令目录 |
–modules-path=/usr/lib64/nginx/modules | 模块目录 |
–conf-path=/etc/nginx/nginx.conf | 配置文件目录 |
–error-log-path=/var/log/nginx/error.log –http-log-path=/var/log/nginx/access.log | 日志目录 |
–http-client-body-temp-path=/var/lib/nginx/tmp/client_body –http-proxy-temp-path=/var/lib/nginx/tmp/proxy –http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi –http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi –http-scgi-temp-path=/var/lib/nginx/tmp/scgi | temp 临时的目录 |
–pid-path=/var/run/nginx.pid | pid目录 |
–lock-path=/var/lock/subsys/nginx | |
–user=nginx --group=nginx | 设定 进程启动的 用户和用户组 |
–with-cc-opt=parameters | 设置额外的参数将被添加到CFLAGS变量 |
–with-id-opt=parameters | 设置附件的参数,如:连接数据库等 |
Nginx目录和配置文件总览、介绍
文件或目录 | 说明 | 描述 |
---|---|---|
/etc/logrotate.d/nginx /var/log/nginx/*log | 配置文件 | Nginx日志轮转,用于logrotate服务的日志切割 |
/etc/nginx /etc/nginx/nginx.conf /etc/nginx/conf.d /etc/nginx/conf.d/default.conf | 目录配置文件 | Nginx主配置文件 |
/etc/nginx/fastcgi_params /etc/nginx/uwsgi_params /etc/nginx/scgi_params | 配置文件 | cgi配置,fastcgi配置 |
/etc/nginx/koi-utf /etc/nginx/koi-win /etc/nginx/win-utf | 配置文件 | 编码转换映射转换文件 |
/etc/nginx/mime.types | 配置文件 | 设置http协议的Content-Type与扩展名对应关系 |
/usr/lib/systemd/system/nginx-debug.service(centos7.2 or later) /usrlib/systemd/system/nginx.service /etc/sysconfig/nginx /etc/sysconfig/nginx-debug | 配置文件 | 用于配置出系统守护进程管理器管理方式 |
/usr/lib64/nginx/modules /etc/nginx/modules | 目录 | Nginx模块目录 |
/usr/sbin/nginx /usr/sbin/nginx-debug | 命令 | Nginx服务的启动管理终端命令 |
/usr/share/doc/nginx-1.12.0 /usr/share/doc/nginx-1.12.0/COPYRIGHT /usr/share/man/man8/nginx.8.gz | 文件,目录 | Nginx的帮助手册 |
/var/cache/nginx | 目录 | Nginx的缓存目录 |
/var/log/nginx | 目录 | Nginx日志目录 |
Nginx日志,HTTP请求
Http请求
简单来说一个HTTP请求包含两个部分 request,response
request: 包括请求行,请求头部,请求数据
response: 状态行,消息报头,响应正文
用一个简单的命令来演示下
curl -v https://www.baidu.com
而Nginx的日志跟HTTP有很大的关系
Nginx 日志 ,内置变量
首先我们看下Nginx的主配置文件
cat /etc/nginx/nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
}
分别可以看到默认的日志位置
日志名称 | 标识 | 位置 |
---|---|---|
错误日志 | error_log | /var/log/nginx/error.log |
访问日志 | access_log | /var/log/nginx/access.log |
需要注意的是这段代码
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
这句话的意思就是格式化日志使用的 ,‘💲remote_addr’ 类似于这种以‘💲’ 开头的,都是系统内置的变量,当然变量也可以自定义
这里面要住的是两个参数
参数 | 含义 | 值的形式 |
---|---|---|
remote_addr | 访问者的IP或上级代理IP | 替换上层IP |
http_x_forwarded_for | 访问者IP ,代理1IP,代理2IP | 拼接上次IP |
太抽象了,伤害性不大,但侮辱性极强,来张图
下面我使用 rIP 代替: remote_addr
使用xIP代替:http_x_forwarded_for
当IP没有代理的时候remote_addr 跟 http_x_forwarded_for应该是一样的,而当经过代理了 , remote_addr 的IP就是上一级代理或主机的IP, http_x_forwarded_for则包含所有主机和代理的IP
类似的这些变量 http_x_forwarded_for, remote_addr 其实Nginx有很多内置变量
Nginx基础官方模块
Nginx 关联的模块
输入指令
nginx -V // 查看Nginx配置
--with-file-aio
--with-ipv6 --with-http_ssl_module
--with-http_v2_module
--with-http_realip_module
--with-http_addition_module
......
此处省略一万字。。。
这里是Nginx编译进去的模块了 ,当然Nginx有很多模块。。。
Nginx 客户端状态模块 http_stub_status_module
Syntax: stub_status;
Default: —
Context: server, location
这个模块是Nginx客户端状态
模块 | 作用 | 语法 | 默认值 | 上下文 |
---|---|---|---|---|
http_stub_status_module | 客户端状态 | stub_status | - | server, location |
说人话就是: 在 server, location 下(Context),配置一个stub_status的属性(Syntax),没有默认值(Default)
当然,这些配置文件并不是直接编辑 /etc/nginx/nginx.conf,这是个主配置文件,一般不在这里修改 ;我们修改的是 /etc/nginx/conf.d/*.conf 文件
include /etc/nginx/conf.d/*.conf;
我们打开Nginx的主配置文件,发现nginx.conf文件包含了所有conf.d目录下的所有*.conf 文件
注意:
若两个配置文件配置了相同的属性,Nginx不会报错,但会发出警告⚠️ ! nginx会安装文件读取属性判定,先读取的文件属性生效,后读取的属性无效
扯了这么多,我们看下刚刚的配置项
我在 /etc/nginx/conf.d/default.conf 下配置了一个
server {
#stub_status; 配置这里也可以
/** 省略部分代码 **/
location /mystatus{
stub_status; /// 没有默认值,只需要配置这个属性就行
}
}
访问看一下 。。。
http://ip_你的——IP/mystatus
分别分析下这几个参数干啥子的 …
名称 | 值 | 说明 |
---|---|---|
Active connections | 2 | 当前活跃连接数2个 |
accepts | 1249 | 总的 握手次数 |
handled | 1249 | 总的 连接数 |
requests | 1249 | 总的 请求数 |
Reading | 0 | IO 读个数 |
Writing | 1 | IO 读个数 |
Waiting | 1 | 没有读,也没有写开启 keepAlive |
Nginx 随机主页模块 http_random_index_module
首先说下这玩意是干什么的 。。。 这功能其实没什么卵用,大厂看不上,小厂可以通过JS等方式实现。 作用就是: 当你访问某个指定的网站的时候,每次给你反馈不同的内容。 但是不排除各种产品经理大开的脑洞,当网页为纯静态网页的时候,保不齐脸一黑。所以需要了解下,同样先介绍语法
Syntax: random_index on | off;
Default: random_index off;
Context: location
这个模块是Nginx客户端状态
模块 | 作用 | 语法 | 默认值 | 上下文 |
---|---|---|---|---|
http_random_index_module | 随机主页 | random_index | off | location |
也就是这哥们默认是没有配置的,而且只能位于location下
上代码 ,然后名词解释
server {
root /usr/share/nginx/html; // 配置目录的位置文件夹
location / {
random_index on;
# root /usr/share/nginx/html;
}
}
首页配置你的主页文件夹 /usr/share/nginx/html , root这个可以位于server 也可位于 location 中 ,在location 中加入 random_index on; 就表示开启此功能 ,当访问
https://你的主页
会随机的把 /usr/share/nginx/html 目录下的网页展现给你你, 但是主页以.开头的隐藏文件,不会被展示
Nginx HTTP响应内容替换模块http_sub_module
这玩意的作用就是:替换响应里面的指定字符串的内容。 举个简单例子,比如接口给你的响应用户名是张三({“name”:“张三”}), 可以通过添加这个模块替换成苍老师 {“name”:“仓老师”},设想一下最高权限控制了Nginx添加了这个模块,可以干啥子。。 额,满脑子邪恶😈 的想法,关键是这玩意的作用域还挺大 。。。。
{“name”:“张三”} = 响应字符替换 => {“name”:“仓老师”}
Syntax: sub_filter string replacement;
Default: —
Context: http, server, location
Syntax: sub_filter_once on | off;
Default: sub_filter_once on;
Context: http, server, location
模块 | 作用 | 语法 | 默认值 | 上下文 |
---|---|---|---|---|
http_sub_module | 响应内容字符替换 | sub_filter | off | http, server, location |
http_sub_module | 替换第一个 | sub_filter_once | on | http, server, location |
server {
# sub_filter 'nginx' 'tomcat'; // 也可配置这里
# sub_filter_once off; // 也可配置这里
/** 省略部分代码 **/
location / {
sub_filter 'nginx' 'tomcat'; // 把响应的内容里面的nginx 替换成 tomcat
sub_filter_once off; // off 关闭只替换第一个(也就是全文替换)
}
}
配置项可以看得出,默认只替换第一个 ,若要全文替换 ,需要加入配置 项
sub_filter_once off; // 替换全部,不写或者配置on只替换第一个
Nginx 请求限制模块
首先用一张抽象,装逼, 大多数人看不懂,而且很无聊的图来解释下HTTP连接 。 所有HTTP连接都是建立在TCP连接三次握手之上的(理论都懂,这个手怎么握这里不解释了 ,度娘上可以找一箩筐)
但是在不同版本的HTTP请求跟TCP直接有所不同
HTTP协议版本 | 连接关系 |
---|---|
HTTP1.0 | TCP不能复用 |
HTTP1.1 | 顺序性TCP复用 |
HTTP2.0 | 多路复用TCP复用 |
至于为啥从HTTP1.1就直接到了2.0 , 这个跟给娃子取名狗剩,二柱子没啥区别,这里不解释了
这两个模块应该是Nginx里面比较难理解的模块了 ,鉴于这两个模块复杂难理解,下面会把详细的Nginx 配置文件做详细的注释
连接频率限制 http_limit_conn_module
Syntax: limit_conn_zone key zone=name:size;
Default: —
Context: http
Syntax: limit_conn zone number;
Default: —
Context: http, server, location
下面是/ect/nginx/conf.d/default.conf文件的详细配置
#
# The default server
#
limit_conn_zone $binary_remote_addr zone=test_conn_zone:1m;
#
server {
root /usr/share/nginx/html;
location / {
limit_conn test_conn_zone 1;
}
}
上面代码表示的意思是
名称 | 意义 |
---|---|
limit_conn_zone | 在http模块 申明连接限制 |
$binary_remote_addr | 关键字 需要连接的名称,这里表示ip地址 可以是其他属性 |
zone=test_conn_zone | 给这个访问连接取一个别名 |
1m | 表示存储空间为1M ,多个的话空间都不一样,参数可调节 |
limit_conn test_conn_zone | 对指定名称的属性进行限制,这里限制的是test_conn_zone |
1 | 限制连接个数是1 个 |
请求频率限制 http_limit_req_module
Syntax: limit_req_zone key zone=name:size rate=rate [sync];
Default: —
Context: http
Syntax: limit_req zone=name [burst=number] [nodelay | delay=number];
Default: —
Context: http, server, location
下面是/ect/nginx/conf.d/default.conf文件的详细配置
#
# The default server
#
limit_req_zone $binary_remote_addr zone=my_req_zone:1m rate=1r/s;
## $binary_remote_addr 客户端IP,表示对`binary_remote_addr`进行限制,可以对其他关键字限制
## 定义zone的名称 my_req_zone ,:1m : 相当于取一个变量名称,后面使用 ,1m 表示存储空间为1M ,多个回话空间都不一样,参数可调节
## rate=1r/s; 速率
server {
root /usr/share/nginx/html;
location / {
limit_req zone=my_req_zone burst=3 nodelay ;
}
}
分别解释下上面的东西都是什么意思
limit_req_zone $binary_remote_addr zone=my_req_zone:1m rate=1r/s;
limit_req zone=my_req_zone burst=3 nodelay ;
名称 | 意义 |
---|---|
limit_req_zone | 在http模块 申明访问限制 |
$binary_remote_addr | 关键字 需要限制的名称,这里表示ip地址 可以是其他属性 |
zone=my_req_zone | 给这个访问限制取一个别名 |
1m | 表示存储空间为1M ,多个的话空间都不一样,参数可调节 |
limit_req zone=my_req_zone | 对指定名称的属性进行限制,这里限制的是my_req_zone |
burst=3 | 可选参数,客户端执行速度超过了 rate=1r/s(可设置)后,会保留3个(或更少)在下一秒执行,其他不保留直接nodelay 503 返回 |
nodelay | 可选参数, 没有延时 返回 |
可使用ab 命令进行测试
ab -n 2000(总数) -c (同时并发数) http://www.xxxxx.com
Nginx 访问控制模块 http_access_module
这个模块的作用是禁止或允许指定的访问
Syntax: allow address | CIDR | unix: | all;
Syntax: deny address | CIDR | unix: | all;
Default: —
Context: http, server, location, limit_except
解释之前,先说一个通配符 ,Nginx 很多通配符
// 匹配以 admin.html 开头的
location ~ ^/admin.html {
allow 111.222.333.444;
deny all;
}
比如我要限制IP为 111.22.33.44的IP访问,其他的IP可以访问,
先限制单个,后面允许所有 ;
location / {
deny 111.22.33.44;
allow all;
}
同样,比如我只允许 IP为 123.12.13.14的主机访问
先允许单个,后禁止所有
location / {
allow 123.12.13.14;
deny all;
}
这种限制有一定的局限性
若通过代理服务的话,就容易误伤或者误判断;这个就是访问控制的局限性,可以通过下面三种方案解决这个访问局限性
- 采用别的HTTP头信息控制访问,如:HTTP_X_FORWARD_FOR ,但是X_FORWARD_FOR 容易被修改
- 结合geo模块
- 通过HTTP自定义变量传递 ,定义一个自己的变量,一级一级的把变量传到下级
Nginx 基于用户信任的访问控制 http_auth_basic_module
什么叫做用户信任的访问控制
搞张图就可以了 。。。
就是这个 ,我们平时叫不出名的一种方式,需要用户认证
Syntax: auth_basic string | off;
Default: auth_basic off;
Context: http, server, location, limit_except
Syntax: auth_basic_user_file file;
Default: —
Context: http, server, location, limit_except
我们配置下,然后分别解释
location /mystatus{
auth_basic "YOU NEED INPUT PASSWORD";
auth_basic_user_file /etc/nginx/hb_auth_conf;
}
参数 | 说明 |
---|---|
auth_basic | 字符串标识信息 看的出这是一个无关紧要的东西 |
auth_basic_user_file | 存放认证的用户名和密码的文件 |
现在我们的问题转换为怎么生成认证文件
首先我们需要安装一个工具 httpd-tools
[root]# yum install httpd-tools
安装完成以后 我们生成 秘钥文件
[root]# htpasswd -c /etc/nginx/hb_auth_conf hebiao
输入两次密码确认后,会有一个文件生成
很显然这东西存在这局限性
- 用户信息依赖文件方式
- 操作者管理机械,效率低下
解决方案有两种
- Nginx结合Lua解决
- Nginx结合LDAP,利用nginx-auth-ladp模块解决