nginx简介
- nginx是来自于俄罗斯的网站服务
- 功能十分丰富,可以作为
- http服务器
- 网络负载均衡
- 正向代理和反向代理
- nginx由一系列的模块组成
- 核心模块
- HTTP模块、EVENT模块和MAIL模块
- 基础模块
- HTTP Access模块、HTTP FastCGI模块、HTTP Proxy模块和HTTP Rewrite模块
- 第三方模块
- HTTP Upstream Request Hash模块、Notice模块和HTTP Access Key模块及用 户自己开发的模块
- 核心模块
nginx特点
- 支持高并发,内存消耗少
- 多种功能
- 网站web服务
- 网站负载均衡
- 正向代理反向代理
- 网站缓存
- 多系统多平台部署
- nginx实现网络通讯的时候使用的时异步网络IO模型epoll模型
nginx工作原理
- nginx由内核和一系列的模块组成,内核提供web服务的基本功能
- nginx内核的基本功能:
- 启用网络协议、创建运行环境、接收和分配客户端请求、处理模块之间的交互
- nginx从模型结构上分为核心模块、基础模块、第三方模块
nginx架构
-
nginx服务器使用master/worker多进程模式。
-
主程序Master process启动之后,通过一个for循环来接收和处理外部信号
-
主进程通过fork()函数产生子进程,每个子进程执行一个for循环来实现nginx服务器对事件的接收和处理
-
一般建议worker进程数与CPU内核树一样,这样一来不存在大量的子进程生成和挂历任务,避免了进程之间竞争CPU资源和进程切换的开销
-
nginx提供了CPU亲缘性绑定的选项,我们可以将某一进程绑定在某一个内核上,就不会带来进程切换导致的cache失效的问题
-
对于每个请求,有且仅有一个工作进程对其进行处理,每个worker进程都是从master进程fork()出来的,在master进程里面,要首先建立好listen和socket(listenfd之后)然后再fork出多个worker进程。所有worker进程在注册的时候
-
当一个worker进程在accept这个连接之后,就开始读取、解析、处理请求,产生数据之后,再返回给客户端,最后断开连接
-
一个请求,完全由worker进程来处理,而且只在一个worker进程中处理
-
每个工作进程使用异步非阻塞方式,可以处理读个客户端请求,当某个工作进程接收到客户端的请求之后,调用IO进行处理,如果不能立即得到结果,就去处理其他的事情(即非阻塞);而客户端在此期间也无需等待响应,可以去处理其他的事情(即为异步);当IO返回的时候,就会通知此工作进程;该进程得到通知,暂时挂起当前处理的事务去响应客户端请求。
-
管理员的作用:监控worker进程的运行状态,worker进程异常终止之后,重启worker进程
nginx进程直接按通信
nginx主进程与工作进程的通信
- nginx服务器启动过程中,通过配置文件决定启动工作进程的数量,然后建立一张全局的工作表存放当前未推出的所有工作进程,主进程生成工作进程之后会将新的工作进程加入到工作进程表厚葬,并建立一个单向管道将其产地给工作进程
- 该单向管道包含了主进程向工作进程发出得指令、工作进程ID、工作进程在工作进程表中得索引值和必要得文件描述符
- 工作进程只能监听主进程发来的内容,然后从中读取指令
- 主进程与外界的信号机制进行通信,当接收到需要处理的信号的时候,就通过管道向相关的工作进程发送正确的指令
- 每个进程都有能力捕获管道中的可读事件,当管道中有可读事件的时候,工作进程就会从管道中读取并解析指令,然后采取相应的执行动作,就完成了主进程与工作进程之间的交互
工作进程之间的通信
- 工作进程之间的通信交互与工作进程和主进程之间的交互的通信是一样的,只要工作进程之间可以取得彼此之间的信息,建立管道即可进行通信,
- 但是由于工作进程之间完全隔离,因此一个进程想要知道另外一个进程的状态信息只能通过主进程来设置
- 为实现工作进程之间的交互,主进程在生成工作进程之后,在工作进程表中进行遍历,将该新进程的ID以及针对该进程建立的管道句柄传递给工作进程中的其他进程,为工作进程之间的通信做准备
- 当工作进程1向工作进程2发送指令的时候,首先在主进程给他的其他工作进程工作信息中找到2的进程ID,然后将正确的指令写入指向进程2的管道,工作进程2捕获到管道中的事件之后,进行指令的解析并进行相关操作。完成工作进程之间的通信
- 工作进程之间的通信是双向的,建立的管道也是双向的
nginx事件驱动模型
在nginx的异步非阻塞机制中,工作进程在调用IO之后,就去处理其他的请求,当IO调用返回之后,会通知该工作进程。这样的机制使用nginx服务器的事件驱动模型来实现。
- nginx的事件驱动模型由事件收集器、事件发送器和事件处理器三部分基本单元组成。
- 事件收集器负责收集worker进程的各种IO请求
- 事件发送器负责将IO事件发送到事件处理器
- 事件发送器将每个请求放入一个待处理事件的列表,使用非阻塞IO方式调用“事件处理器”来处理请求,器处理方式称为多路IO复用方法,常见的包括select、poll、epoll模型
- 事件处理器负责各种事件的响应
web请求处理机制
- 多进程方式:服务器每接到一个客户端的请求就生成一个子进程,影响客户端。
- 有点,反应速度很快,子进程之间相互独立。安全
- 多线程方式:服务器,每收到一个客户端请求回派生出一个线程与客户端进行交互
- 有点:开销小。子线程之间共享内存空间,相对不安全
- nginx是多进程组织模型,而且是由一个master主进程和worker工作进程组成
linux IO模式以及select、poll、epoll、详解
1、概念说明
用户空间和内核空间
操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件的权限。
为了保证用户不可以直接操作内核,保护内核空间。操作系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间
进程切换
为了控制进程的和执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程,称为进程切换。任何进程都是在操作系统的支持下运行的,是与内核紧密相关的。
进程之间切换所经历的步骤
- 保存处理机上下文,包括程序计数器和其他寄存器。
- 更新PCB信息。(为了描述控制进程的运行,系统中存放进程的管理和控制信息的数据结构称为进程控制块,是操作系统中最重要的记录型数据结构,是进程管理和控制最重要的数据结构,每一个进程均有一个PCB,在进程创建的时候,建立PCB,伴随着进程运行的全过程明知道进程撤销而撤销)
- 把进程的PCB移入相应的队列,如就绪、在某事件阻塞等队列。
- 选择另一个进程执行,并更新其PCB。
- 更新内存管理的数据结构。
- 恢复处理机上下文。
是十分消耗资源的
文件描述符fd
文件描述符是计算机科学的术语,是一个用于表述指向文件的引用的抽象化的概念
在形式上是一个非负整数,是一个索引值
IO模式
对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作发生时,它会经历两个阶段:
- 等待数据准备 (Waiting for the data to be ready)
- 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
五种网络模式方案
- 阻塞 I/O(blocking IO)
- 非阻塞 I/O(nonblocking IO)
- I/O 多路复用( IO multiplexing)
- 信号驱动 I/O( signal driven IO)
- 异步 I/O(asynchronous IO)
- 阻塞IO
- 当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。所以,blocking IO的特点就是在IO执行的两个阶段都被block了。
- 非阻塞IO:
- 当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。从用户进程角度讲 ,它发起一个read操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦kernel中的数据准备好了,并且又再次收到了用户进程的system call,那么它马上就将数据拷贝到了用户内存,然后返回。
- 多路复用(select,poll,epoll)
多路复用(select,poll,epoll)
select,poll,epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。
三者之间的不同
- select
select:int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
当select函数返回后,可以 通过遍历fdset,来找到就绪的描述符。
缺点:中的fd_set有最大长度限制,为1024
- poll:不同与select使用三个位图来表示三个fdset的方式,poll使用一个 pollfd的指针实现。同时,pollfd并没有最大数量限制(但是数量过大后性能也是会下降)。 和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符。
- epoll:epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。
nginx
- nginx安装,需要首先下载对应的依赖包
yum install epel-release.noarch -y `` yum install nginx -y
- nginx目录结构
![image.png](https://img-blog.csdnimg.cn/img_convert/ff7b435078328c96356d3d8ba5ae9b94.png#averageHue=#f9f8f6&clientId=u5390555c-b3a0-4&errorMessage=unknown error&from=paste&height=466&id=u3e39a9aa&name=image.png&originHeight=582&originWidth=717&originalType=binary&ratio=1&rotation=0&showTitle=false&size=106846&status=error&style=none&taskId=udad1b1c1-e8af-4a0a-889c-82eded9e238&title=&width=573.6)
- nginx.conf配置文件
user www;#worker进程的管理用户
6 worker_processes auto;#自动调整cpu核数
7 error_log /var/log/nginx/error.log;#错误日志文件目录
8 pid /run/nginx.pid;#定义pid文件
9
10 # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
11 include /usr/share/nginx/modules/*.conf;
12
13 events {
14 worker_connections 1024;定义一个用户可以同时接收1024个请求
15 }
16
17 http {
18 log_format main '$remote_addr - $remote_user [$time_local] "$request" '
19 '$status $body_bytes_sent "$http_referer" '
20 '"$http_user_agent" "$http_x_forwarded_for"';#日志格式
21
22 access_log /var/log/nginx/access.log main;#日志文件路径
23
24 sendfile on;# 允许sendfile方式传输文件
25 tcp_nopush on;#有消息传来时不急着发送,而是等着数据包装满数据在进行发送和
26 tcp_nodelay on;#连接保持活动状态
27 keepalive_timeout 65;# 超时时间
28 types_hash_max_size 4096;;# 连接超时时间
29
30 include /etc/nginx/mime.types;# 文件扩展名与文件类型映射表
31 default_type application/octet-stream;#支持的文件类型
32
33 # Load modular configuration files from the /etc/nginx/conf.d directory.
34 # See http://nginx.org/en/docs/ngx_core_module.html#include
35 # for more information.
36 include /etc/nginx/conf.d/*.conf;
37
38 server {
39 listen 80;#监听端口
40 listen [::]:80;#监听ipv6端口
41 server_name _;
42 root /usr/share/nginx/html;指定网页根目录
43
44 # Load configuration files for the default server block.
45 include /etc/nginx/default.d/*.conf;#配置文件目录
46
47 error_page 404 /404.html;
48 location = /404.html {
49 }#网页内容匹配
50
51 error_page 500 502 503 504 /50x.html;
52 location = /50x.html {
53 }
54 }
- / 用来匹配index.html文件
- /document 用来匹配/document/index.html
~* \.(gif|jpg|jpeg)$
用来匹配 /images/1.jpg
案例一、网站的搭建
- 编写配置文件
[root@www conf.d]# vim /etc/nginx/conf.d/www.conf
server {
listen *:8080;#监听8080端口
server_name www.eagle.com;#指定域名
location / {
root /usr/share/nginx/html;网站根目录
index ealgeslab.html;#index文件
}
}
systemctl restart nginx
重启nginx服务vim /usr/share/nginx/html/eagelslab.html
编写网站内容systemctl stop firewalld
关闭防火墙+setenforce 0
关闭selinuxvim /etc/hosts
配置本地域名解析
nginx服务操作的两种方式
systemctl restart/reload/stop/enable/disable
nignx -t
检查nginx配置是否正确
nginx的相关模块
ngx_http_access_module
- 实现ip地址的访问控制,该种方式用于自上而下的匹配,一旦匹配成功则不再向下匹配
server {
deny 192.168.1.1;#拒绝IP地址访问
allow 192.168.1.0/24;允许网络地址访问
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}
ngx_http_auth_basic_module
- 实现网站访问的用户控制作用
location / {
auth_basic "closed site";
auth_basic_user_file conf/htpasswd;#允许访问的用户以及密码所在的目录
}
htpasswd -bc /etc/nginx/conf/htpasswd admin 123456 htpasswd工具是在下载httpd的时候所使用到的,所以在使用的时候要预先下载httpd或者直接下载该工具
ngx_http_stub_status_module
- 用于展示网站的访问状态信息
- 在访问的时候在域名后加
/basic_status
location = /basic_status {
stub_status;
}
nginx反向代理
- nginx反向代理的主要作用是为了提高网页的访问速度
- 用户每次直接访问的是代理服务器,一定程度上保护了后端的服务器
- 根据nginx反向代理的方式,也可以进行nginx负载均衡的配置,配置服务的负载均衡可以减小单个服务器的负载,可以提高服务系统的稳定性
- 代理可以分为正向和反向,正向代理和反向代理的概念是先对于客户端而言的,一般认为从客户端向服务端的方向为正向,从服务端到客户端的方向为反向,主要是通过代理请求是从客户端发起的还是从服务端发起的来区分,如果是客户端发起的代理请求则为正向代理,如果代理请求是服务端发起的则为反向代理。
- 正向代理一般用于配置梯子,用来访问外网的业务,原理是,中国大陆的防火墙会将国外的大部分网站的流量使用防火墙的方式进行拒绝,但是对于位于国外的一些防火墙的业务则不会进行阻挡,可以通过在国内访问位于国外的服务器的端口,将请求发送给相应的服务器,该服务器再访问外网,最后服务器将获得的数据返回给客户端
原理图:
- 反向代理:反向代理的代理请求是从服务端发起的,服务端向中间的代理服务器请求代理,代理服务器也有做缓存服务器的功能,可以配置nginx的proxy_cache选项进行缓存的配置,该种方式可以加速客户端对于服务端的访问速度
代理服务器的具体配置
- 通过模拟两台虚拟机的nginx服务器之间的缓存来演示,其中server1为代理服务器,server2为被缓存的后端的web服务器
- 拓扑图和上面的拓扑图基本一致
web服务器的nginx配置文件
[root@server2 ~]# cat /etc/nginx/conf.d/proxy.conf
server{
listen 80;
server_name 192.168.60.20;
location / {
root /code;
index index.html index.php;
}
}
代理服务器的配置文件
[root@server1 ~]# cat /etc/nginx/conf.d/proxy.conf
server {
listen 8080;
server_name proxy.test.com;
location / {
proxy_pass http://192.168.60.20:80;
include /etc/nginx/proxy_params;
}
}
代理配置参数文件
[root@server1 ~]# cat /etc/nginx/proxy_params
proxy_set_header HOST $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;