nginx 高性能,可靠,开源的http中间件,代理服务。
Nginx高性能的原因:底层采用IO多路复用技术,poll(系统调用select 不够高效)。这样可以使得网络IO流量,这种频繁并发的环境,得到能高效的处理。
传统服务器软件:
Nginx软件:静态文件不经过用户态缓冲区,直接在内核区传递,最后通过网卡IO出去。
Nginx安装与基本使用:
1. 去到官网,按照提示新建.repo文件,yum下载即可,然后再输入nginx -V,出现版本号和一堆参数,则成功
2. 目录讲解:
PS:nginx启动的时候回去读取/etc/nginx/nginx.conf(如果有变更),没有变更的话,读的就是最后那个默认配置
PS:php 就需要加载 fastcgi 这种配置文件
PS:这三类文件比较少用
PS:http协议报文里面有说明文件类型比如:jpg ,png等,这个配置文件里面就有建立这种对应关系,如果遇到未知拓展名,就可以在这个配置文件添加。
PS:nginx会安装模块到以上目录中
PS:nginx命令就是用来启动nginx服务的,启动,关闭等。 debug可以用来进行nginx调试分析。
PS:帮助文档
PS:nginx缓存的一个目录
nginx编译参数:
yum 下载的时候,这些都已经搞定了(源码安装就要去加这些参数),所以yum还是贼方便
图一
图二
PS: 图一和图二暂不关心
nginx主配置文件说明:
主要配置文件是/etc/nginx/nginx.conf, 在/etc/nginx下还有一个也是重要配置文件,有个目录/etc/nginx/conf.d,这个目录下有个default.conf,是默认读取的配置文件。
PS:/etc/nginx/nginx.conf中的include语句会把/etc/nginx/conf.d/下的所有后缀名为.conf的配置文件都都进来。
因此,/etc/nginx/conf.d/可配置别的模块,只要后缀名为.conf就会被主配置读到。
/etc/nginx/conf.d/default.conf配置文件:
1.listen字段:监听端口
2.server_name:虚拟主机名称,localhost是默认,可以改成其它名称,相当于一种类似域名的访问形式
3.location / :里面的两个字段,默认的访问根目录以及默认访问的文件,linux配置http服务,设置好chroot,是很重要的,因为网络安全问题很严重,一个不小心会有入侵的风险。
当资源找不到或者服务出错时,统统归为404,那么状态码的配置就在上图。
观察http请求信息:
日志:
error.log : 是记录nginx处理http请求出现错误的状态,以及nginx本身服务错误的状态
access.log:记录http访问的状态,能够方便从中分析
配置access日志(语法格式):
这个配置只能配在http下(只属于http模块的范围),access_log是将nginx里面的变量写入到自身中。
nginx中的error_log配置:
错误日志文件所在目录,以及warn是错误等级,完全可以按照要求来调整error的级别输出。
error.log内容:
access_log的配置:
注意,log_format的配置那行的main和access_log这行的main是对应的。main就是一个名字而已,参考access_log语法格式可知。带美元符号的都是nginx的变量,通过一定的格式/符号连接。
意思是,后面那串字符串(含格式组织形式)全部由main统一代替,即main就是后面那一串东东的标记,当我以main的形式打入access日志的时候,信息就像那串东西格式那样显示。
access_log的文件内容:
nginx变量(记录在日志中):
1.http请求变量:
(1) 属于request头的变量格式: http_请求报文头部中的字段
(2) 属于reponse头的变量格式:send_http_响应报文头部中的字段
拿request报文头部为例子:
http_作为固定前缀,然后可以使用浏览器 f12 找到对应的字段,将字段全部改为小写,中间有 "-" 转为下划线 “_”,然后前面加上美元符即可。
如果是响应头,则用send_http_作为前缀,然后可以去匹配头中的任意字段。
PS:在/etc/nginx/nginx.conf 加上变量的时候, 字符串之间要记得空格。
(3)arg_参数名 是get请求时带上的参数名
利用nginx命令检查语法是否正确:
nginx reload配置 (当然也可以用systemctl reload):
2.内置变量:可以去nginx官网查看所有变量
$remote_addr:客户端地址
$remote_user: http客户端请求nginx,认证的用户名 如果没有启动nginx认证模块的话,这个是不会记录的。
$time_local :nginx服务器上的时间
$request: 表示request的请求行
$status: response返回的状态
$body_bytes_sent: response的数据包大小(字节数)
$http_referer:判断来源,可用于防盗链等场景
$http_user_agent: 浏览器(代理)信息
$binary_remote_addr与$remote_addr一样表示客户端地址,但$binary_remote_addr要比$remote_addr少10个字节
3.自定义变量:待定
nginx -V 显示出来的:
这些带前缀 ---with的就是一些nginx的模块:
这个模块主要用于nginx处理http连接的一些状态,用于监控nginx当前的信息。这个模块的配置写在“默认配置”下面,并且规定写在server的location字段选项下(也可以直接配置在server层级下,语法上是没问题的)。如图:在default.conf下的写入
输入对应路径后,看到如下信息:
Active connections: 1 //nginx当前活跃的连接数
server accepts handled requests //三个数值都是总值
200 200 296
//第一个数是nginx能够处理的接收的握手的总数
//第二个数是nginx能够处理的连接总数
//正常情况第一个和第二个总值要相等,这样就表示不会出
现丢失。
//第三个是总的请求数
Reading: 0 Writing: 1 Waiting: 0 //nginx当前状态,第一个是读状态,
第二个是nginx写的状 态,
第三个是客户端与nginx建立连接后,没有数据传输
的一个空闲等待状态
场景:推送不同主页给不同用户
这个模块也是配置在 default.conf 的location字段下:
这样当访问的时候就会随机的推出主页。当然一旦把某些页面设置成隐藏类型的文件,这些页面就不会被推送了。
这个模块用于,nginx response客户端http内容后,对html的内容进行替换。
sub_filter +要替换的内容 要替换成的内容,如果加在http层级下,可以对多个server进行内容替换。
TIPS:这个模块可以在http层级 , server层级(即两个配置文件)或者在location字段下设置。
如果开启设置,就会使得nginx服务端在客户端进行请求时,对服务端的内容进行校验,看看内容有没有发生变化/更新,这个信息一般以时间的形式记录在http头信息里面:last-Modified 字段,判断有没有更新,如果有更新就返回给用户最新的内容,如果没有,就不需要再返回html的内容代码,节省消耗,主要用于缓存。
这个设置的作用是,匹配html的内容,如果设置为开启,则匹配html中的 指定的第一个字符串,如果是设置为off,就会把所有指定的字符串都匹配。
这两种方式设置都可以达到请求限制的目的,但原理不太一样:
现在的时代,tcp长连接的存在,使得tcp连接可以被复用,也就是在一条连接的基础上,进行多次http报文交换。
第一个连接限制设置会与第二个连接限制设置有关联,第一个连接限制设置中,key是代表使用哪些nginx变量来做限制的对象,比如限制IP,那么就用nginx中的$remote_addr 变量来作为key。
第一个连接限制设置:需要在内存里面开辟一块空间用于保存限制连接的状态,所以zone=name,就相当给这个空间一块名字,然后要用的时候,由第二个设置来调用,不难发现第二个设置的语法中就有zone,对应的就是第一个设置。size,就是这块空间的大小。
第二个连接限制设置:这个设置就两个参数,zone是对应第一个设置,而number表示,同一时间的连接并发数,比如设置为1,则同一时间只能进行1条连接,可按要求设置。
语法跟连接限制设置差不多。第一个设置还多了一个rate,是请求速率的设置,以秒为单位限制多少个请求,即 单位为 r/s。
TIPS:apache下的ab压力测试工具,ab -n [请求数] -c [请求并发数] URL
第二个设置的额外两个参数: burst参数是限制客户端访问的作用,比如burst=3,意思是遗留三个请求到下一秒再执行,即这三个请求是延迟响应。 如果burst=3 ,再加上一个nodelay,意思就是除了这三个延迟响应,剩余的请求不延迟直接返回。如果,当请求数非常多,压力已经非常大,那么这样设置的话,就相当于多出来的请求直接不对客户端响应,客户端看到的将是503状态码(宕机)。
这个模块的语法:
allow address:允许的ip地址
~ CIDR:允许的网段
~ unix:是允许的socket流
~ all:所有都允许
deny 就是拒绝的意思,别的跟allow含义一样。
TIPS:limit_except这个字段的作用域是location,所以http_access_module模块一般可配置在server的location层级下
访问控制在不同的级别下设置,影响的范围是不一样的,比如在location下面设置,只会对location所在的范围产生限制。
上图中:~ 是一个模式匹配符号,后面接正则表达式:匹配以 /admin.html开头的页面。上图的限制是:除了222.128.189.17这个IP不能访问,其它IP都可以访问。访问出现403状态,则表明访问限制成功。
TIPS:allow ,deny一般都可成对使用
访问控制模块的精度是不高的,因为出现了代理,这时候nginx依靠remote_addr变量来识别进行限制的话,就会限制了代理而没有限制到真正的源IP。
解决方案一:
http_x_forwarded_for是常用的http头字段。上图可见:http_x_forwarded_for是会记录所有的IP,这时候提高了精度。
http_x_forwarded_for内容:
访问控制精度不高的基本解决方案:
登陆权限控制模块:
模块第一部分语法:默认是关闭的,开启的话再后面加上一串字符串,用来做网站密码验证的提示语,也相当于开启了验证。
第二部分:该部分只有一个参数,file参数,要写出绝对路径文件名,然后该文件是存放登录验证的用户名和密码。该密码文件格式去nginx官网找。密码加密方式,一个工具 htpasswd。
使用htpasswd来生成密码信息,首先要安装httpd-tools,在httpd-tools中包含了htpasswd命令。需要依赖一个工具,先检查一下系统是否已经安装此工具。
如果没有安装此工具,那么可以yum命令安装
yum install -y httpd-tools
先使用htpasswd来生成密码文件:
配置例子:
效果图:
常常用于动静分离等场景。
CDN内容分发网络,常常用于请求分发静态资源(因为静态资源的传输延迟是最小的),nginx就在这个网络架构中扮演着分发的角色,每个地区的后台都存下一份,那么访问的时候,由于有临近节点就要快的多。
静态资源配置:
这个设置跟linux IO结构有关(直接在内核启动网络IO),前面提过。
这个tcp_nopush模块就相当于利用了tcp协议的缓冲区,控制当缓冲到一定程度,一次性发送数据包,避免效率低下的单个发送。适用于大文件传输的场景。但前提是sendfile要打开
这个设置适用于,实时性较高的场景。不延迟的直接推送。前提是keep-alive的长连接状态下。
静态资源进行压缩后,能减少网络资源消耗,能提高传输速度。特别是比较大的文件,压缩后更加有利于网络传输。
这个设置是压缩比,要根据场景考录,因为压缩算法的执行要消耗服务端的性能,等级越高,压缩的越小,性能会下降的多。
(http协议上的)压缩主要用的是gzip的格式,版本主要是1.0/1.1.
gzip_static_module模块是预先去对应的目录里找.gzip类型的压缩文件,找到的话直接返回给客户端,gunzip压缩模块比较少用,这个模块只是为了解决少量不支持gzip压缩格式的浏览器,但这种情况很少。
这个设置方法是匹配根目录下的所有图片,然后将其压缩。gzip_types 指定的压缩对象的类型
这个设置方法是匹配根目录下的所有文本,然后将其压缩。
预读功能:gzip_static设置,它与gzip压缩是不一样的,来看效果图:
当服务器没有开启这个设置时,而目录下又有对应的gzip文件,那么显然这个图片是无法显示的。
当设置成启动时:
同样上图的网址,将会启动浏览器下载。这就是预读。
PS:预读的设置,你的目录首先要存在gzip后缀的文件。
缓存:
第二次缓存:
客户端会校验缓存的时间,如果过期,则请求服务器,服务器上的文件没有更新,那么客户端继续使用原来的缓存,如果客户端缓存没过期,也是继续使用。
缓存校验机制原理:
http1.1版本是cache-control字段,该字段记录着一个缓存周期,超过该时间,客户端就会认为缓存过期,既而发起服务端请求。
经过确认cache-control字段后,发起校验,起作用的是Etag , last-modified这两个字段
如果,服务端没有资源的更新,那么状态码就是304(而不应该是200)直接跳回客户端,如果发生更新,状态码才是200.
nginx静态资源过期设置:
该配置是给客户端的response头里面添加缓存字段。expires+时间,这个时间和cache-control的max-age是一致的。
有些浏览器会自动加入缓存字段,但它的max-age一般都是<=0,表明每次都向服务端(利用Etag等字段)校验缓存信息。
例子:
跨站访问设置:
浏览器默认是拒绝跨域访问的,但是如果识别到这个 Access-Control-Allow-Originhttp头字段的话,就会允许跨站访问。
例子:
add_header name(头部中的字段) value(允许跨域的域名站点)
nginx配置防盗链(防止资源盗用):
例子:
valid_referers(表示允许哪些请求访问资源) none(表示允许没有带referer信息的请求过来) blocked(表示允许referer信息不是标准http协议请求过来的 ) 域名(表示只允许当前设定域名访问资源)
valid_referers这个设定其实是在设定$invalid_referer这个变量信息,不满足访问条件的都会使得$invalid_referer值为1,
因此想要盗用资源时返回的就是403.
valid_referers这个设定还支持访问的正则匹配:
代理服务:
反向代理服务对象是服务端,客户端根本不需要知道具体哪一台服务端地址,完全交给代理来访问。
而正向代理,则填上对应的代理服务器地址 ,比如翻墙这种行为,填上对应的VPN就可以访问外网。
例子:
上图的例子,是通过访问本地80的方式再反向代理访问到本地的8080。proxy_pass +url (这个URL就是要代理实际访问的服务器地址,可以是私有IP)。
正向代理:
此处设置了只允许 116.62.103.228 IP来访问(访问限制),如果不使用这个IP是没办法访问到的。那么如果将这个116.62.103.228 设置成了正向代理,就可以了。
TIPS:正向代理或者反向代理的设置语法都一样。
接上话题,去到116.62.103.228 这台代理主机:
注意看,这台代理主机的server_name写的是要实际访问的主机的域名,proxy_pass 后面跟的URL也是实际访问的地址。这样,访问这台代理主机,就可以访问到实际提供服务的主机。
配置switchysharp代理插件来进行测试:
类似操纵TCP缓冲区那样,一次性尽可能收集完请求才进行网络IO,降低网络IO的频次,是驻留内存的,但也要控制缓冲区大小,否则内存不够而进入到swap交换区的话,磁盘读写可是很慢的,性能会下降。
这个配置较常用,因为由于代理的存在,导致访问控制中使用remote_addr精度不高,可以设置一个字段在http头部里面,让这个字段带着代理地址信息给后端读到:
proxy_set_header 字段名 值可以是 代理IP地址变量
该模块设置TCP连接超时时间。
例子:
nginx就是典型的SLB
四层负载均衡是在TCP上实现数据包的转发,速度快性能高,逻辑控制也少。而7层负载均衡主要体现在对http协议报文的操作,逻辑控制就比较多了,安全应用策略控制,重定向,http头改写等。nginx主要就是7层负载均衡。
负载均衡原理上也用到代理。
这个设置,只能在http层级下。
例子:
这里以同一台服务器的三个端口作为三个不同服务,然后在另外一台服务器配置负载均衡代理到该服务器不同端口上。
配置负载均衡:
设置代理:
PS:图二,location中的代理地址,要对应写上upstream后面的那个参数(虚拟服务)名称,如图标记处。
语法:upstream + 自定义负载均衡名称(也叫虚拟服务名称){
该括号内写上一组均摊压力的服务器地址 (域名或者IP地址) ;
}
该实例效果是实现了一个简单的轮询。
upstream还支持unixsocket方式 ,每个节点后面还有一些小参数,比如:后面的backup 表示的是一个备份节点,weight是表示的该节点的权重。
别的节点参数:
例子:
一旦设置了backup,该节点只会在其它节点不可用的情况下才启动。
demo:
同一个URL会定位到同一个主机上(一旦分配好了以后),不会再轮询。
例子:
平常的业务场景不会那么简单,一般可能涉及到很多私密信息存储,所以就会使用一些诸如判断指令+正则提取,然后进行hash定位。
缓存服务:之所以使用缓存,就是要减少服务端压力,因为访问服务端是中心化的,而客户端是分散的,如果客户端可以不用请求服务端就可以获取数据那么,这样服务端的压力就会得到减小。
缓存类型:
这种类型就是常见的使用nosql数据库(如redis)进行独特的存储,这种存储是内存级的,可以常驻内存,提高IO速度来提升访问性能。
这种缓存是放在代理上的(或者是放在中间件上),从服务端获取到的,代理留一份再返回给客户端。
这类型就是客户端缓存,客户端在数据有效期间就可以直接在本地直接读取数据。
代理缓存流程:
使用大小proxy_cache之前还要使用proxy_cache_path 来定义好一个目录(完整的路径),这个目录是用来放缓存文件的。
配置好这个路径后才进行cache配置:
这个设置中的 zone 参数对应 proxy_cache_path 设置中的 keys_zone。
对缓存文件的过期时间的设置,设置中的code参数对应http协议的状态码。
这个设置可以用来设置cookie,http头信息等多维度缓存,而不仅仅局限域名,url等。
例子:
定义缓存文件目录:
proxy_cache_path后面的参数讲解(图中可明显看到参数是以空格隔开的,下面以序号来阐述):
1.定义缓存文件所在目录
2.不能所有缓存都堆在一个cache大目录下,按照2级(也就是1比2)目录来分层。
3.为缓存文件(缓存文件用来存下缓存标识key,10M大小的文件能存8万个key,够用)申请一片空间以及定义这片空间的名字,图中imooc_cache就是name,‘:’后面是空间大小的值。
4.定义这个缓存目录最大值,一旦目录满了,nginx就会触发淘汰规则,将不常使用的缓存淘汰。
5.定义不活跃的缓存文件清理时间,表示这个时间内,这个缓存文件不常被访问,,则会被清理掉。
6.最后一个参数最好关闭,有性能损耗。
定义好缓存文件目录后,接下来到了定义nginx代理缓存以及其参数:
例子参数讲解(参数顺序对应序号):
1.第一个参数对应定义缓存文件目录中的那个key_zone,不多说
2.第二个之前提过了,对应虚拟服务名称
3.对于200,304状态码的头信息设置过期时间。
4.除了200,304之外的头信息,设置别的过期时间
5.设置缓存维度。即要实施缓存的部分
6.设置一个http头信息,Nginx-Cache头信息,能够在客户端看出,缓存是否命中。
7.对于50X系列的HTTP状态码,或者错误,或者超时,或者不可用的http头部,这个设置能让代理跳过该台服务器去访问别的节点。
例子:
缓存分片请求,针对大型文件:
rewrite语法之return指令:
code参数:
error_page指令:
code参数也是HTTP状态码,它能够在用户找不到资源的时候以一些友好的错误资源来呈现给用户,提醒该资源不存在
return指令和error_page指令关系:
最终结果,return会覆盖掉error_page.
rewrite指令能够重写用户传过来的URL:
该指令的三个参数:
例子:
if指令: