When you realize you want to spend the rest of your life with somebody,you want the rest of your life to start as soon as possible.<br/> 当你意识到想和某人共度余生时,便会恨不得下半场人生马上开始。——《当哈利遇到莎莉》1989
基本概述
或许当提前80端口和443端口的时候,我们就能想起对应的Http访问[基于HTTP协议]和Https访问[基于HTTP协议+SSL证书]。记忆中比较深刻的,就是开发微信小程序时,对应域名配置述求,必须是备案认证通过的Https的服务。因此,在配置之前,我们需要了解Nginx包含着那些模块以及配置规则,工作原理才能更好地使用Nginx以及认识Nginx。 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是Nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。 Nginx的模块从结构上分为核心模块、基础模块和第三方模块, HTTP模块、EVENT模块和MAIL模块等属于核心模块,HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块属于基本模块,而HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块属于第三方模块,用户根据自己的需要开发的模块都属于第三方模块。正是有了这么多模块的支撑,Nginx的功能才会如此强大。 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是Nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。
Nginx结构分析
以nginx-1.19.8版本为例:
Nginx的源码主要分布在src/目录下,而src/目录下主要包含三部分比较重要的模块:
core:基础核心库和框架
Nginx的核心源代码,包括常用数据结构的以及Nginx 内核实现的核心代码。
event:事件驱动模型
Nginx事件驱动模型,以及定时器的实现相关代码。
http:HTTP的模块
Nginx 实现http 服务器相关的代码。
mail:邮件服务模块
Nginx 实现邮件代理服务器相关的代码。
misc:整合模块
辅助代码,测试C++头 的兼容性,以及对Google_PerfTools 的支持。
os:系统模块
不同体系统结构所提供的系统函数的封装,提供对外统一的系统调用接口。
stream:流处理模块
Nginx(tcp/udp)反向代理及与上游通信的基础模块。
Nginx 事件驱动模型
Nginx提供支持的模型主要有Select库,Eventport库,Poll库,Epoll库,Kqueue库,Devpoll库以及Eventport库等。
- Select库:在linux和windows平台都基本支持的 事件驱动模型库,并且在接口的定义也基本相同,只是部分参数的含义略有差异,最大并发限制1024,只最早期的事件驱动模型。
- Poll库: 在Linux 的基本驱动模型,windows不支持此驱动模型,是select的升级版,取消了最大的并发限制,在编译nginx的时候可以使用--with-poll_module和--without-poll_module这两个指定是否编译select库。
- Epoll库:Nginx服务器支持的最高性能的事件驱动库之一,是公认的非常优秀的事件驱动模型,它和select和poll有很大的区别,epoll是poll的升级版,但是与poll的效率有很大的区别.epoll的处理方式是创建一个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮训检查这个表,以判断事件是否发生,epoll支持一个进程打开的最大事件描述符的上限是系统可以打开的文件的最大数,同时epoll库的IO效率不随描述符数目增加而线性下降,因为它只会对内核上报的“活跃”的描述符进行操作。
- Kqueue库:用于支持BSD系列平台的高校事件驱动模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版本,NetBSD级以上版本及Mac OS X 平台上,该模型也是poll库的变种,因此和epoll没有本质上的区别,都是通过避免轮训操作提供效率。
- Devpoll库:用于支持unix衍生平台的高效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发Solaris系列平台的时候提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员将要见识的文件描述符加入这个设备,然后通过ioctl()调用来获取事件通知,因此运行在以上系列平台的时候请使用/dev/poll事件驱动机制。
- Eventport库:是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库看防止内核崩溃等情况的发生。
Nginx工作原理
Nginx的模块从功能上分为三类,分别是:
- Handlers(处理器模块): 直接处理请求,并进行输出内容和修改headers信息等操作。handlers处理器模块一般只能有一个。
- Filters ->过滤器模块: 主要对其他处理器模块输出的内容进行修改操作,最后由Nginx输出。
- Proxies->代理类模块: Nginx的HTTP Upstream之类的模块,这些模块主要与后端一些服务比如fastcgi等操作交互,实现服务代理和负载均衡等功能。
在Nginx的模块下,一次常规的HTTP请求和响应的过程: 在工作方式上,Nginx分为单工作进程和多工作进程两种模式:
- 在单工作进程模式下,除主进程外,还有一个工作进程,工作进程是单线程的
- 在多工作进程模式下,每个工作进程包含多个线程 Nginx默认为单工作进程模式。Nginx的模块直接被编译进Nginx,因此属于静态编译方式。启动Nginx后,Nginx的模块被自动加载,不像在Apache一样,首先将模块编译为一个so文件,然后在配置文件中指定是否进行加载。在解析配置文件时,Nginx的每个模块都有可能去处理某个请求,但是同一个处理请求只能由一个模块来完成
Nginx的Http模块
Nginx常用的模块:
- ngx_http_access_module模块:只有allow[允许访问]和deny[拒绝访问]2个值,一般用于设置和控制IP的请求,类似于网络黑名单的功能。
location / { root html; index index.html index.htm; allow 127.0.0.1; ##允许127.0.0.1访问 deny 127.0.0.1; ##拒绝127.0.0.1访问 }
- ngx_http_auth_basic_module模块:实现基于用户的访问控制,使用basic机制进行用户认证
location / { root html; index index.html index.htm; auth_basic "Admin"; ##认证对话框的提示字符串显示的内容 auth_basic_user_file /etc/nginx/conf/htpasswd; ##存放认证用的用户名和文件,需要用htpasswd命令生成 }
对于htpasswd的应用需要安装httpd-tools:
yum install httpd-tools
使用命令生成:htpasswd -c /etc/nginx/conf/htpasswd nginx
[root@cotos-pivotal nginx]# htpasswd -c /etc/nginx/conf/htpasswd nginx New password: Re-type new password: Adding password for user nginx
- ngx_http_stub_status_module模块:用来查看http的状态信息的,使用方式直接在location里面加stub_status
location / { root html; index index.html index.htm; auth_basic "Admin"; ##认证对话框的提示字符串显示的内容 auth_basic_user_file /etc/nginx/conf/htpasswd; ##存放认证用的用户名和文件,需要用htpasswd命令生成 stub_status; }
状态参数解析:
Active connections: 活动状态的连接数;
accepts:已经接受的客户端请求的总数;
handled:已经处理完成的客户端请求的总数;
requests:客户端发来的总的请求数;
Reading:处于读取客户端请求报文首部的连接的连接数;
Writing:处于向客户端发送响应报文过程中的连接数;
Waiting:处于等待客户端发出请求的空闲连接数;
ngx_http_log_module模块:日志模块
ngx_http_gzip_module模块:压缩模块,有利于传输数据的大小减少,但是cpu使用会变高。因为要对传输的数据进行压缩
gzip on; gzip_comp_level 6; gzip_min_length 64; gzip_proxied any; gzip_types text/xml text/css application/javascript;
- ngx_http_ssl_module模块: 设置https连接的模块
server { listen 443 ssl; server_name www.ice.com; root /var/www/html; ssl on; ssl_certificate /usr/local/nginx/ssl/ssl.crt; ssl_certificate_key /usr/local/nginx/ssl/ssl.key; ssl_session_cache shared:sslcache:20m; location / { index index.html index.htm; } }
- ngx_http_rewrite_module模块:重写指令
rewrite regex replacement [flag]:将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为replacement指定的新的URI; 在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查,因此,隐含有循环机制;[flag]所表示的标志位用于控制此循环机制; 其中:
last:如果规则有很多条。这里重写完成一次之后就会重新开始匹配规则,直至最后一条。也就是说。如果规则写的不好很容易造成死循环,不停的重写规则。
break:重写完成之后不再从头再次匹配规则。直接跳出循环
redirect:重写完成后以临时重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;不能以http://或https://开头;
permanent:重写完成后以永久重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;
ngx_http_referer_module模块:防盗链 定义referer首部的合法可用值:
none:请求报文首部没有referer首部
blocked:请求报文的referer首部没有值
server_names:参数,其可以有值作为主机名或主机名模式
arbitrary_string:直接字符串,但可使用*作通配符
regular expression:被指定的正则表达式模式匹配到的字符串;要使用~打头
valid_referers none block server_names *.pivotal.com ; if($invalid_referer) {return 403; }
- ngx_http_headers_module模块 :向由代理服务器响应给客户端的响应报文添加自定义配置部
完整的 Nginx配置文件:
#Setting Nginx User Group user root; #Setting Nginx Processes worker_processes 1; #Setting Nginx Max Nofile worker_rlimit_nofile 51200; #Setting Nginx Events events { worker_connections 51200; } #Setting Nginx Http http { include mime.types; default_type application/octet-stream; #Setting Nginx FastCGI[避免504 502等] fastcgi_connect_timeout 600s; fastcgi_send_timeout 600s; fastcgi_read_timeout 600s; fastcgi_buffer_size 256k; fastcgi_buffers 16 256k; fastcgi_busy_buffers_size 512k; fastcgi_temp_file_write_size 512k; send_timeout 60000; client_header_buffer_size 64k; large_client_header_buffers 4 64k; sendfile on; tcp_nopush on; tcp_nodelay on; #keepalive_timeout 0; keepalive_timeout 120; #文件上传最大限制50M 默认是1m client_max_body_size 100m; #gzip on; #Setting Nginx Gzip gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on; #Setting Nginx Reverse Proxy [反向代理配置 负载均衡] #后台系统web层tomcat端口 monitor-8090 upstream monitor.com{ ip_hash; server localhost:8090 ; } #前台接口web层tomcat端口proscenium-8091 upstream proscenium.com{ ip_hash; server localhost:8091; } #移动接口web层tomcat端口mobile-8092 upstream mobile.com{ ip_hash; server localhost:8092; } #后台系统web层tomcat端口 schedule-8093 upstream schedule.com{ ip_hash; server localhost:8093; } server { listen 80; server_name localhost; #处理websocket请求 location /monitor { #请求转向定义的服务器列表 proxy_pass http://monitor.com/zhimeng; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 超时设置 默认300s proxy_read_timeout 300s; proxy_send_timeout 300s; } location /proscenium { #请求转向定义的服务器列表 proxy_pass http://proscenium.com; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 超时设置 默认300s proxy_read_timeout 300s; proxy_send_timeout 300s; } location /mobile { #请求转向定义的服务器列表 proxy_pass http://mobile.com; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 超时设置 默认300s proxy_read_timeout 300s; proxy_send_timeout 300s; } location /schedule { #请求转向定义的服务器列表 proxy_pass http://schedule.com/; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Headers X-Requested-With; add_header Access-Control-Allow-Methods GET,POST,OPTIONS; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 超时设置 默认300s proxy_read_timeout 300s; proxy_send_timeout 300s; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } location /staticFile { alias /root/repository/staticFile; autoindex on; autoindex_exact_size on; autoindex_localtime on; } } }