最近花了一些时间来总结nginx常用的技能知识点,通过一些常用的实际案例来将nginx的众多小知识点串联起来。
首先是进入nginx目录进行脚本启动,准备初始化环境:
[root@idea-centos nginx]# cd ./sbin/ [root@idea-centos sbin]# ll total 3528 -rwxr-xr-x. 1 root root 3611160 Dec 26 16:43 nginx [root@idea-centos sbin]# ps -ef|grep nginx root 7270 7194 0 10:42 pts/1 00:00:00 grep --color=auto nginx [root@idea-centos sbin]# ./nginx [root@idea-centos sbin]# ps -ef|grep nginx root 7272 1 0 10:42 ? 00:00:00 nginx: master process ./nginx nobody 7273 7272 0 10:42 ? 00:00:00 nginx: master process ./nginx root 7275 7194 0 10:42 pts/1 00:00:00 grep --color=auto nginx 复制代码
启动成功之后,通过curl可以进行访问测试
首先通过 ip add来查看地址信息:
(本人使用的是虚拟机)
[root@idea-centos sbin]# ip add 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:ea:63:63 brd ff:ff:ff:ff:ff:ff inet 192.168.43.235/24 brd 192.168.43.255 scope global noprefixroute dynamic ens33 valid_lft 2922sec preferred_lft 2922sec inet6 2409:8955:3048:50d5:e7e8:636d:bdf1:7033/64 scope global noprefixroute dynamic valid_lft 2964sec preferred_lft 2964sec inet6 fe80::8a65:608b:505e:fe4/64 scope link noprefixroute valid_lft forever preferred_lft forever 复制代码
然后通过curl在本虚拟机上边进行测试:
[root@idea-centos sbin]# curl http://192.168.43.235/ <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> 复制代码
如果访问失败,请先查看防火墙是否开启,如果开启了,可以先进行关闭,方便展开后续的demo练习:
[root@idea-centos sbin]# firewall-cmd --state running [root@idea-centos sbin]# systemctl stop firewalld.service [root@idea-centos sbin]# firewall-cmd --state not running 复制代码
访问成功之后,会看到nginx的首页:
nginx常用的基础命令总结
#默认方式启动: ./sbin/nginx #指定配置文件启动 ./sbing/nginx -c /tmp/nginx.conf #指定nginx程序目录启动 ./sbin/nginx -p /usr/local/nginx/ #快速停止 ./sbin/nginx -s stop #优雅停止 (会等当前的请求先处理完再杀死) ./sbin/nginx -s quit # 热装载配置文件 ./sbin/nginx -s reload # 重新打开日志文件 ./sbin/nginx -s reopen # 检测配置是否正确 ./sbin/nginx -t 复制代码
启动nginx之后,可以通过日志来查看进程的相关信息
[root@idea-centos nginx]# ./sbin/nginx [root@idea-centos nginx]# ps -ef|grep nginx root 11059 1 0 16:34 ? 00:00:00 nginx: master process ./sbin/nginx nobody 11060 11059 0 16:34 ? 00:00:00 nginx: worker process root 11062 8193 0 16:34 pts/1 00:00:00 grep --color=auto nginx 复制代码
master process 主要是负责日志的更新,热装载 主进程
worker process 工作进程 处理客户端的连接,处理请求
nginx的日志
在nginx的log文件夹底下,我们在重新访问服务器之后,相应的access日志就会增加新的属性内容。
这里面的日志寻找,实际上是根据对象句柄来进行查找指定的文件。
关于nginx处理机制的理解
nginx里的高性能主要归咎于其相应特有的io多路复用。每当有请求发送过来的时候,请求的都会被放入到一个select队列里面,专门存储客户端的http链接信息,然后通过一个专门的选择器来处理轮询,监听客户端是否有发送请求的数据(一直轮询,直到有数据发送过来的时候才会发生堵塞),一旦当接收到发送的数据时,selector就会做出指定的处理。
当我们启动了nginx之后,会有两类型进程出现,分别是master进程和worker进程,而客户端发送的请求通常只是和master进程进行通信,master进程负责接收这些请求,然后分发给不同的worker进程进行处理。其实本质上,worker进程是从master进程这边fork出来的,在master的进程里面,需要先建立好被监听的socket之后,再fork出多个worker进程,多个worker进程(多核cpu环境下)会争抢accept_mutex互斥锁,抢锁成功的进程就会注册相应的事件对任务进行处理。这种独立进程处理事件的好处在于避免了原本的加锁开销,同时当进程中出现了bug异常的时候,不会影响其他的进程,降低了风险。
nginx处理高并发的方式又是如何的呢?当采用多个worker来处理请求的时候,每个worker里面都只有一个主线程,但是这样处理并发数非常有限,那当并发数量大的时候,是否又需要创建成千上万的线程来实现请求的处理呢?
nginx的设计高明之处就在于了这一点上了,它的机制有点类似于linux里面的epoll这样的系统调度。处理的响应线程(暂命名为A)只有一个,当请求过来的事件处理完毕的时候,会主动通知A , 不会对堵塞的请求等待操作。这样的设计避免了A主动去轮询和等待事件处理的所带来的事件消耗。
相比于传统的apache服务器,每一个连接,apache就会创建一个进程,每个进程内单线程,apache最多能创建256个进程。对于一个负载相对较高的网站来说,256的进程,也就是256个线程,因为线程处理请求时,是同步阻塞模式,接收请求之后,会一直等待该请求读取程序文件(IO)(同步),执行业务逻辑,返回客户端,所有操作完成之后才能处理下一个请求(阻塞)如果服务器已经达到256的极限,那么接下去的访问就需要排队这也就是为什么某些服务器负载不高的原因了。
小结
1.每个worker进程都是单线程的模式
2.每个io链接都是基于异步非堵塞的模型建立的。
3.worker进程的数目结合服务器的cpu数量来进行设置,可以达到调优的效果
nginx里面的基本组成模块
nginx在处理请求的时候,更多的是会把这些请求组成一条请求链,链上的各个模块都会进行不同功能的处理。例如说对于请求的解压和压缩处理,对于ssl的处理模块等。总的来说,nginx的基本模块我总结为了以下几项:
event module 事件处理机制模块,提供了各种事件的具体处理框架。nginx具体采用何种事件来处理,依赖于操作系统和编译设置项,例如ngx_event_core_module和ngx_epoll_module。
phase handler 主要负责处理客户端请求并产生待响应内容,ngx_http_static_module就是其中之一,该module主要是将nginx请求转往读取一些磁盘上边的数据,然后做出输出响应,例如说:uri 是以 / 结尾,则会交由 index 模块来链接上完整的路径名然后通过内部调用的方式来调用本模块。
output filter 该模块可以对响应的输出内容做出指定的修改,例如对页面的某些特定url进行替换操作。
upstream 这一模块相信大家都很熟悉,该模块主要是做反向代理的工作。
load-balancer 此模块主要是负责负载均衡功能,在集群中选择任意一台服务器作为请求的处理。
\
nginx的常用配置案例讲解
首先来查看一份最为基础的nginx基本配置:
events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; #标识使用零拷贝 keepalive_timeout 65; #标识采用长连接 server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } 复制代码
ps:这份配置里面分成了很多份配置块,每个配置块和大括号之间都需要有空格进行标明,否则会识别失效
\
配置location的重定向
例如说我们在/usr/local/www/文件夹底下创建了一份html页面,然后需要通过nginx来进行访问,nginx在匹配server的location路径的时候,会先按照全路径,再从左往右,再从右往左匹配的顺序。
server { listen 80; server_name www.idea.com *.idea.com idea.*; location / { root /usr/local/www/; } } 复制代码
注意,这里面的root配置是存在继承关系的,location里面的root会继承location外边的root信息。如果location里面有写root,就会按照location里面的root来判断。server外>server内>location内。
\
配置动静分离
所谓的动静分离实质上是指我们对于nginx配置里面的动态请求和静态文件都做了一定的分离。例如以下的配置信息:
server { listen 80; server_name www.idea.com *.idea.com idea.*; root /usr/local/www; #这里面添加映射static的记录 location /static { root /usr/local/static/; } location / { root /usr/local/www/; index idea.html; } } 复制代码
ps:这里面的配置内容,我引入了host文件的修改
192.168.43.235 www.idea.com 192.168.43.235 test.idea.com 192.168.43.235 idea.test 复制代码
图片的实际存储位置是: /usr/local/static/img/logo.jpg
按照上述的配置来讲,访问的方式是:
但是这种情况下,我们通过nginx来访问图片的方式是不会成功的,原因是这个地址会被nginx处理成为:
前往root地址+static的最终地址进行查询:
也就是: /usr/local/static/static
为了避免这种情况,通常会用别名alias来进行匹配,具体配置如下:
server { listen 80; server_name www.idea.com *.idea.com idea.*; root /usr/local/www; location /static { alias /usr/local/static/; } location / { root /usr/local/www/; index idea.html; } } 复制代码
这个时候,我们再去访问 www.idea.com/static/img/… 就会访问成功了。
同样对于别名我们可以进行更加复杂一些的逻辑操作案例:
假设我们需要访问static底下的文件内容,这个时候不需要携带相应的名称,直接通过访问
www.idea.com/static/css/… 就可以访问到 /usr/local/www/static/css/ 底下的内容了
那么,假如说有很多种类型的静态文件需要进行映射该如何配置呢?这个时候可以引入正则表达式的配置:
server { listen 80; server_name www.idea.com *.idea.com idea.*; root /usr/local/www; location /static { alias /usr/local/static/; } #这里的~是指忽略大小写 location ~* \.(gif|png|jpg|css|js) { root /usr/local/static/; } location / { root /usr/local/www/; index idea.html; } } 复制代码
加入了这段正则表达式的配置之后( ~* .(gif|png|css|js)$ ) 通过访问该路径:
www.idea.com/css/test.cs… 我们就可以访问到/usr/local/static/css/底下的文件内容了。
\