基础

I/O 模型

I/O 概述

  • I/O 就是把数据从内核空间中的内存数据 复制到 用户空间进程的内存当中

I/O 分类

Linux 中的 I/O

  • 磁盘 I/O
    • 磁盘 I/O 是进程向内核发起的系统调用;
    • 假设请求磁盘上的某个资源,比如说 html 文件或者图片:
      • 内核会通过相应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存
  • 网络 I/O
    • 一切皆文件,本质就是对 socket 文件的读写
  • 总结:
    • 无论是磁盘I/O还是网络I/O,每次I/O都要经由两个阶段:
      1. 先将数据加载至内核内存空间(缓冲区),时间较长
      2. 然后将数据从内核缓冲区复制到用户空间进程的内存,时间较短

同步与异步

同步与异步 关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知

同步 synchronous;被调用者并不提供事件的处理结果相关的通知信息,需要被调用者主动询问事件是否处理完成

异步 asynchronous;被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态

阻塞与非阻塞

阻塞与非阻塞 关注调用者在等待结果返回之前所处的状态

阻塞 blocking;指IO操作需要彻底完成后才返回结果到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情

非阻塞 nonblocking;指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情

小结

**假设用水壶烧水这件事举例:**启动水壶后;

  • 需要定期关注水是否烧开(同步),期间不能做其他事情(阻塞),这就是同步/阻塞。

  • 需要定期关注水是否烧开(同步),期间可以去做别的事情(非阻塞),这就是同步/非阻塞。

  • 水烧开后水壶会发出水烧开的信号来提醒我(异步),期间不能做其他事情(阻塞),这就是异步/阻塞。

  • 水烧开后水壶会发出水烧开的信号来提醒我(异步),期间可以去做别的事情(非阻塞),这就是异步/非阻塞。

Nginx 概述

  • nginx是一个性能优异的web服务器应用,并且还能提供强大的反向代理功能

为什么这么快

  • epoll 模型
  • 支持sendfile零复制技术
    • 即将数据从磁盘中读出后进入内核空间后直接发送给soket缓存区,从而省略了user缓存这一步

特性

  • 模块化设计、较好的扩展性
  • 高可靠性
  • 支持热部署:不停机更新配置文件、升级版本、更换日志文件等
  • 低内存消耗:10000个kepp-alive连接模式下的非活动连接,消耗内存仅2.5M
  • event-driven、aio、mmap、sendfile

处理机制

  • 一个master进程带领多个worker进程进行数据处理
  • master进程只负责将客户端请求调度到worker
  • 真正进行数据处理的是worker进程

Apache VS Nginx

Nginx:

  • 使用 epoll 模型

  • IO 多路复用,Epoll(freebsd 上是 kqueue)

  • 高性能

  • 高并发

  • 占用系统资源少

  • C10K? 不存在

Apache:

  • 使用 select 模型

  • 阻塞 + 多进程 / 多线程

  • 更稳定,Bug 少

  • 模块更丰富

  • C10K? 存在

Nginx 安装

yum安装

#centos自带安装
yum -y install nginx

#官方自带源安装
#https://nginx.org/en/linux_packages.html#RHEL-CentOS
#配置官方的yum源文件,然后再安装

编译安装

下载源码:https://nginx.org/en/download.html

#下载源码包
[root@centos8 ~]# cd /usr/local/src/
[root@centos8 src]# wget https://nginx.org/download/nginx-1.18.0.tar.gz

#创建nginx账号
[root@centos8 ~]#useradd -r -s /sbin/nologin nginx

#安装相关依赖包
#centos
yum -y install make gcc pcre-devel openssl-devel zlib-devel
#ubuntu
apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev 


#指定编译安装选项(根据生产需要指定)
[root@centos8 src]# tar xf nginx-1.18.0.tar.gz 
[root@centos8 src]# cd nginx-1.18.0/
[root@centos8 nginx-1.18.0]# ./configure \
--prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module


#开始编译安装
[root@centos8 nginx-1.20.1]#make -j 2 && make install

#修改权限
[root@centos8 nginx-1.20.1]#chown -R nginx.nginx /apps/nginx

#将可执行文件创建软连接
[root@centos8 nginx-1.20.1]#ln -s /apps/nginx/sbin/nginx /usr/sbin/

编译安装后实现开机自动启动

#创建目录
[root@centos8 ~]#mkdir /apps/nginx/run

#修改权限
[root@centos8 nginx-1.20.1]#chown -R nginx.nginx /apps/nginx

#修改配置文件
[root@centos8 ~]#vim /apps/nginx/conf/nginx.conf
pid        /apps/nginx/run/nginx.pid;

#创建service文件
[root@centos ~]#vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/apps/nginx/run/nginx.pid
ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /apps/nginx/run/nginx.pid)"
ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /apps/nginx/run/nginx.pid)"

[Install]
WantedBy=multi-user.target


#更新service文件并实现开机启动
[root@centos8 ~]# systemctl daemon-reload 
[root@centos8 ~]# systemctl enable --now nginx.service 

Nginx 命令

  • **注意:**systemctl也可以实现服务的启动、停止、和重新加载、但是不要和nginx自带的启动停止等工具混用,否则会出现错误
#启动服务
[root@centos8 apps]#nginx
[root@centos8 apps]#ss -ntl
State     Recv-Q    Send-Q     Local Address:Port     Peer Address:Port                  
LISTEN    0         128           0.0.0.0:80              0.0.0.0:*            
       
#停止服务
nginx -s stop

#重新加载配置文件
nginx -s reload

#检查配置文件语法
nginx -t

#显示版本
nginx -v

#显示编译选项
nginx -V

Nginx 配置文件

Nginx 配置文件参考文档:

配置文件自定生成(仅作参考):

配置文件格式

  • directive value [value2 …];
  • 必须以分号结尾
  • 支持使用配置变量:
    • 内建变量:由Nginx模块引入,可直接使用
    • 自定义变量:由用户使用set命令定义,格式:set variable_name value;
    • 引用变量:$variable_name

配置文件结构

main # 主配置段,即全局配置段,对http,mail都有效

events { # 定义 Nginx 如何处理连接的事件,如连接数限制、超时等
...
}

http { # 记录各 server 的公共配置,例如:HTTP 服务器或反向代理服务器的配置,包括 HTTP 请求的处理、代理设置、缓存设置、日志记录等。
...
  server { # 每个server用于定义一个虚拟主机,用于匹配到来的请求并确定如何处理该请求。第一个server为默认虚拟服务器。
  ...
    location / { # 定义某个 URI(或者 URI 的一部分)的配置,用于匹配到来的请求并确定如何处理该请求。一个 server 中可以有多个 location
    ...
    }
  }
}

mail { # mail 协议相关配置段,默认配置文件不包括此配置段
...
}

stream { # 定义基于TCP、UDP、UNIX等协议的后端代理配置,默认配置文件不包括此配置段
...
}