第16周-2022-03-28

1、對(duì)常用I/O模型進(jìn)行比較說(shuō)明

I/O模型概念:

  • 同步:synchronous,被調(diào)用者并不提供事件的處理結(jié)果相關(guān)的通知消息,需要調(diào)用者主動(dòng)詢問(wèn)事情是否處理完成。
  • 異步:asynchronous,被調(diào)用者通過(guò)狀態(tài)、通知或回調(diào)機(jī)制主動(dòng)通知調(diào)用者被調(diào)用者的運(yùn)行狀態(tài)。
  • 阻塞:blocking,指IO操作需要徹底完成后才返回到用戶空間,調(diào)用結(jié)果返回之前,調(diào)用者被掛起,干不了別的事情。
  • 非阻塞:nonblocking,指IO操作被調(diào)用后立即返回給用戶一個(gè)狀態(tài)值,而無(wú)需等到IO操作徹底完
    成,在最終的調(diào)用結(jié)果返回之前,調(diào)用者不會(huì)被掛起,可以去做別的事情。

I/O模型分為:
阻塞型、非阻塞型、復(fù)用型、信號(hào)驅(qū)動(dòng)型、異步

  • 阻塞型 I/O 模型(blocking IO)
    阻塞IO模型是最簡(jiǎn)單的I/O模型,用戶線程在內(nèi)核進(jìn)行IO操作時(shí)被阻塞。用戶線程通過(guò)系統(tǒng)調(diào)用read發(fā)起I/O讀操作,由用戶空間轉(zhuǎn)到內(nèi)核空間。
    內(nèi)核等到數(shù)據(jù)包到達(dá)后,然后將接收的數(shù)據(jù)拷貝到用戶空間,完成read操作用戶需要等待read將數(shù)據(jù)讀取到buffer后,才繼續(xù)處理接收的數(shù)據(jù)。
    整個(gè)I/O請(qǐng)求的過(guò)程中,用戶線程是被阻塞的,這導(dǎo)致用戶在發(fā)起IO請(qǐng)求時(shí),不能做任何事情,對(duì)CPU的資源利用率不夠
    優(yōu)點(diǎn):程序簡(jiǎn)單,在阻塞等待數(shù)據(jù)期間進(jìn)程/線程掛起,基本不會(huì)占用 CPU 資源
    缺點(diǎn):每個(gè)連接需要獨(dú)立的進(jìn)程/線程單獨(dú)處理,當(dāng)并發(fā)請(qǐng)求量大時(shí)為了維護(hù)程序,內(nèi)存、線程切換開銷較大,apache 的preforck使用的是這種模式。

  • 非阻塞型 I/O 模型 (nonblocking IO)
    用戶線程發(fā)起IO請(qǐng)求時(shí)立即返回。但并未讀取到任何數(shù)據(jù),用戶線程需要不斷地發(fā)起IO請(qǐng)求,直到數(shù)據(jù)到達(dá)后,才真正讀取到數(shù)據(jù),繼續(xù)執(zhí)行。
    即 “輪詢”機(jī)制存在兩個(gè)問(wèn)題:如果有大量文件描述符都要等,那么就得一個(gè)一個(gè)的read。這會(huì)帶來(lái)大量的Context Switch(read是系統(tǒng)調(diào)用,每調(diào)用一次就得在用戶態(tài)和核心態(tài)切換一次)。輪詢的時(shí)間不好把握。這里是要猜多久之后數(shù)據(jù)才能到。等待時(shí)間設(shè)的太長(zhǎng),程序響應(yīng)延遲就過(guò)大;設(shè)的太短,就會(huì)造成過(guò)于頻繁的重試,干耗CPU而已,是比較浪費(fèi)CPU的方式,一般很少直接使用這種模型,而是在其他IO模型中使用非阻塞IO這一特性。

  • 多路復(fù)用 I/O 型(I/O multiplexing)
    多路復(fù)用IO指一個(gè)線程可以同時(shí)(實(shí)際是交替實(shí)現(xiàn),即并發(fā)完成)監(jiān)控和處理多個(gè)文件描述符對(duì)應(yīng)各自的IO,即復(fù)用同一個(gè)線程一個(gè)線程之所以能
    實(shí)現(xiàn)同時(shí)處理多個(gè)IO,是因?yàn)檫@個(gè)線程調(diào)用了內(nèi)核中的SELECT,POLL或EPOLL等系統(tǒng)調(diào)用,從而實(shí)現(xiàn)多路復(fù)用IO。
    優(yōu)點(diǎn):可以基于一個(gè)阻塞對(duì)象,同時(shí)在多個(gè)描述符上等待就緒,而不是使用多個(gè)線程(每個(gè)文件描述符一個(gè)線程),這樣可以大大節(jié)省系統(tǒng)資源
    缺點(diǎn):當(dāng)連接數(shù)較少時(shí)效率相比多線程+阻塞 I/O 模型效率較低,可能延遲更大,因?yàn)閱蝹€(gè)連接處理需要 2 次系統(tǒng)調(diào)用,占用時(shí)間會(huì)有增加

  • 信號(hào)驅(qū)動(dòng)式 I/O 模型 (signal-driven IO)
    信號(hào)驅(qū)動(dòng)I/O的意思就是進(jìn)程現(xiàn)在不用傻等著,也不用去輪詢。而是讓內(nèi)核在數(shù)據(jù)就緒時(shí),發(fā)送信號(hào)通知進(jìn)程。調(diào)用的步驟是:通過(guò)系統(tǒng)調(diào)用sigaction ,并注冊(cè)一個(gè)信號(hào)處理的回調(diào)函數(shù),該調(diào)用會(huì)立即返回,然后主程序可以繼續(xù)向下執(zhí)行,當(dāng)有I/O操作準(zhǔn)備就緒,即內(nèi)核數(shù)據(jù)就緒時(shí),內(nèi)核會(huì)為該進(jìn)程產(chǎn)生一個(gè)SIGIO信號(hào),并回調(diào)注冊(cè)的信號(hào)回調(diào)函數(shù),這樣就可以在信號(hào)回調(diào)函數(shù)中系統(tǒng)調(diào)用recvfrom 獲取數(shù)據(jù),將用戶進(jìn)程所需要的數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間。
    此模型的優(yōu)勢(shì)在于等待數(shù)據(jù)報(bào)到達(dá)期間進(jìn)程不被阻塞。用戶主程序可以繼續(xù)執(zhí)行,只要等待來(lái)自信號(hào)處理函數(shù)的通知。在信號(hào)驅(qū)動(dòng)式 I/O 模型中,應(yīng)用程序使用套接口進(jìn)行信號(hào)驅(qū)動(dòng) I/O,并安裝一個(gè)信號(hào)處理函數(shù),進(jìn)程繼續(xù)運(yùn)行并不阻塞當(dāng)數(shù)據(jù)準(zhǔn)備好時(shí),進(jìn)程會(huì)收到一個(gè) SIGIO 信號(hào),可以在信號(hào)處理函數(shù)中調(diào)用 I/O 操作函數(shù)處理數(shù)據(jù)。
    優(yōu)點(diǎn):線程并沒(méi)有在等待數(shù)據(jù)時(shí)被阻塞,內(nèi)核直接返回調(diào)用接收信號(hào),不影響進(jìn)程繼續(xù)處理其他請(qǐng)求因此可以提高資源的利用率
    缺點(diǎn):信號(hào) I/O 在大量 IO 操作時(shí)可能會(huì)因?yàn)樾盘?hào)隊(duì)列溢出導(dǎo)致沒(méi)法通知

  • 異步 I/O 模型 (asynchronous IO)
    異步I/O 與 信號(hào)驅(qū)動(dòng)I/O最大區(qū)別在于,信號(hào)驅(qū)動(dòng)是內(nèi)核通知用戶進(jìn)程何時(shí)開始一個(gè)I/O操作,而異步I/O是由內(nèi)核通知用戶進(jìn)程I/O操作何時(shí)完成,兩者有本質(zhì)區(qū)別,相當(dāng)于不用去飯店場(chǎng)吃飯,直接點(diǎn)個(gè)外賣,把等待上菜的時(shí)間也給省了。相對(duì)于同步I/O,異步I/O不是順序執(zhí)行。用戶進(jìn)程進(jìn)行aio_read系統(tǒng)調(diào)用之后,無(wú)論內(nèi)核數(shù)據(jù)是否準(zhǔn)備好,都會(huì)直接返回給用戶進(jìn)程,然后用戶態(tài)進(jìn)程可以去做別的事情。等到socket數(shù)據(jù)準(zhǔn)備好了,內(nèi)核直接復(fù)制數(shù)據(jù)給進(jìn)程,然后從內(nèi)核向進(jìn)程發(fā)送通知。IO兩個(gè)階段,進(jìn)程都是非阻塞的。信號(hào)驅(qū)動(dòng)IO當(dāng)內(nèi)核通知觸發(fā)信號(hào)處理程序時(shí),信號(hào)處理程序還需要阻塞在從內(nèi)核空間緩沖區(qū)拷貝數(shù)據(jù)到用戶空間緩沖區(qū)這個(gè)階段,而異步IO直接是在第二個(gè)階段完成后,內(nèi)核直接通知用戶線程可以進(jìn)行后續(xù)操作了
    優(yōu)點(diǎn):異步 I/O 能夠充分利用 DMA 特性,讓 I/O 操作與計(jì)算重疊
    缺點(diǎn):要實(shí)現(xiàn)真正的異步 I/O,操作系統(tǒng)需要做大量的工作。目前 Windows 下通過(guò) IOCP 實(shí)現(xiàn)了真正的

五種IO對(duì)比:
這五種 I/O 模型中,越往后,阻塞越少,理論上效率也是最優(yōu)前四種屬于同步 I/O,因?yàn)槠渲姓嬲?I/O操作(recvfrom)將阻塞進(jìn)程/線程,只有異步 I/O 模型才與 POSIX 定義的異步 I/O 相匹配。

2、nginx中的模塊分類及常見核心模塊有哪些

nginx 有多種模塊

  • 核心模塊:是 Nginx 服務(wù)器正常運(yùn)行必不可少的模塊,提供錯(cuò)誤日志記錄 、配置文件解析 、事件驅(qū)動(dòng)機(jī)制 、進(jìn)程管理等核心功能
  • 標(biāo)準(zhǔn)HTTP模塊:提供 HTTP 協(xié)議解析相關(guān)的功能,比如: 端口配置 、 網(wǎng)頁(yè)編碼設(shè)置 、 HTTP響應(yīng)頭設(shè)置等等
  • 可選HTTP模塊:主要用于擴(kuò)展標(biāo)準(zhǔn)的 HTTP 功能,讓 Nginx 能處理一些特殊的服務(wù),比如: Flash 多媒體傳輸 、解析 GeoIP 請(qǐng)求、 網(wǎng)絡(luò)傳輸壓縮 、 安全協(xié)議 SSL 支持等
  • 郵件服務(wù)模塊:主要用于支持 Nginx 的 郵件服務(wù) ,包括對(duì) POP3 協(xié)議、 IMAP 協(xié)議和 SMTP協(xié)議的支持
  • Stream服務(wù)模塊: 實(shí)現(xiàn)反向代理功能,包括TCP協(xié)議代理
  • 第三方模塊:是為了擴(kuò)展 Nginx 服務(wù)器應(yīng)用,完成開發(fā)者自定義功能,比如: Json 支持、 Lua 支持等

nginx高度模塊化,但其模塊早期不支持DSO機(jī)制;1.9.11 版本支持動(dòng)態(tài)裝載和卸載

模塊分類:
核心模塊:core module
ngx_core,ngx_errlog,ngx_conf,ngx_events,ngx_event,ngx_epoll,ngx_regex
標(biāo)準(zhǔn)模塊:
HTTP 模塊: ngx_http_*
HTTP Core modules #默認(rèn)功能
HTTP Optional modules #需編譯時(shí)指定
Mail 模塊: ngx_mail_*
Stream 模塊 ngx_stream_*
第三方模塊
Rds-json-nginx,Lua-nginx,Others

3、描述nginx中worker_processes、worker_cpu_affinity、worker_rlimit_nofile、worker_connections配置項(xiàng)的含義

  • worker_processes [number | atuo]; #啟動(dòng)Nginx工作進(jìn)程的數(shù)量,一般設(shè)為和CPU核心數(shù)相同
  • worker_cpu_affinity 00000001 00000010 00000100 00001000; #將Nginx工作進(jìn)程綁定到指定的CPU核心,默認(rèn)Nginx是不進(jìn)行進(jìn)程綁定的,綁定并不是意味著當(dāng)前nginx進(jìn)程獨(dú)占以一核心CPU,但是可以保證此進(jìn)程不會(huì)運(yùn)行在其他核心上,這就極大減少了nginx的工作進(jìn)程在不同的cpu核心上的來(lái)回跳轉(zhuǎn),減少了CPU對(duì)進(jìn)程的資源分配與回收以及內(nèi)存管理等,因此可以有效的提升nginx服務(wù)器的性能
  • worker_rlimit_nofile 65536; #所有worker進(jìn)程能打開的文件數(shù)量上限,包括:Nginx的所有連接(例如與代理服務(wù)器的連接等),而不僅僅是與客戶端的連接,另一個(gè)考慮因素是實(shí)際的并發(fā)連接數(shù)不能超過(guò)系統(tǒng)級(jí)別的最大打開文件數(shù)的限制.最好與ulimit -n 或者limits.conf的值保持一致
  • worker_connections 65536; #設(shè)置單個(gè)工作進(jìn)程的最大并發(fā)連接數(shù)

4、編譯安裝nginx,實(shí)現(xiàn)多域名 https

安裝nginx

#安裝依賴包
[root@centos7-01 ~]# yum -y install gcc pcre-devel openssl-devel zlib-devel

#創(chuàng)建nginx用戶
[root@centos7-01 ~]# useradd -s /sbin/nologin nginx

#下載安裝包并解壓
[root@centos7-01 ~]# wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@centos7-01 ~]# tar xf nginx-1.18.0.tar.gz

#編譯安裝
[root@centos7-01 ~]# cd nginx-1.18.0/
[root@centos7-01 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@centos7-01 nginx-1.18.0]# make && make install
[root@centos7-01 nginx-1.18.0]# chown -R nginx.nginx /apps/nginx

#創(chuàng)建 Nginx 自啟動(dòng)文件
[root@centos7-01 nginx-1.18.0]# 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/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target

#創(chuàng)建目錄
[root@centos7-01 nginx-1.18.0]# mkdir /apps/nginx/run/
[root@centos7-01 nginx-1.18.0]# chown -R nginx.nginx /apps/nginx/run

#修改配置文件,變更pid文件位置
[root@centos7-01 nginx-1.18.0]# sed -r -i 's/#pid.*/pid\ \/apps\/nginx\/run\/nginx.pid;/' /apps/nginx/conf/nginx.conf

#啟動(dòng)nginx服務(wù)
[root@centos7-01 nginx-1.18.0]# systemctl daemon-reload
[root@centos7-01 nginx-1.18.0]# systemctl enable --now nginx

配置多域名https

#創(chuàng)建子配置文件目錄并修改配置文件
[root@centos7-01 nginx-1.18.0]# mkdir /apps/nginx/conf/vhost
[root@centos7-01 nginx-1.18.0]# chown -R nginx.nginx /apps/nginx/conf/vhost
[root@centos7-01 nginx-1.18.0]# vi /apps/nginx/conf/nginx.conf
#在http語(yǔ)句塊最后加入該行
include       vhost/*.conf;

#創(chuàng)建網(wǎng)頁(yè)文件
[root@centos7-01 nginx-1.18.0]# mkdir -p /www/example{1,2}
[root@centos7-01 nginx-1.18.0]# echo "example1" > /www/example1/index.html
[root@centos7-01 nginx-1.18.0]# echo "example2" > /www/example2/index.html
[root@centos7-01 nginx-1.18.0]# tree /www/
/www/
├── example1
│   └── index.html
└── example2
    └── index.html

#制作自簽名ssl證書
[root@centos7-01 nginx-1.18.0]# mkdir /www/ssl
[root@centos7-01 nginx-1.18.0]# cd /www/ssl
[root@centos7-01 ssl]# vi make_cert.sh
#!/bin/bash
CA_SUBJECT="/O=example/CN=ca.example.org"
SUBJECT="/C=CN/ST=henan/L=zhengzhou/O=example/CN=test1.example.org"
SERIAL=34
EXPIRE=100
FILE=test1.example.org
openssl req -x509 -newkey rsa:2048 -subj $CA_SUBJECT -keyout ca.key -nodes -days $EXPIRE -out ca.crt
openssl req -newkey rsa:2048 -nodes -keyout ${FILE}.key -subj $SUBJECT -out ${FILE}.csr
openssl x509 -req -in ${FILE}.csr -CA ca.crt -CAkey ca.key -set_serial $SERIAL -days $EXPIRE -out ${FILE}.crt
chmod 600 ${FILE}.key ca.key

#使用以上腳本生成證書文件
[root@centos7-01 ssl]# bash make_cert.sh
[root@centos7-01 ssl]# cat test1.example.org.crt ca.crt > test1.example.org.pem
#使用上面同樣方法生成test2.example.org證書文件及私鑰
[root@centos7-01 ssl]# ls test*.example.org.{pem,key}
test1.example.org.key  test1.example.org.pem  test2.example.org.key  test2.example.org.pem

#創(chuàng)建子配置文件
[root@centos7-01 nginx-1.18.0]# vi /apps/nginx/conf/vhost/example1.conf
server {
  listen 80;
  listen 443 ssl;
  server_name test1.example.org;
  ssl_certificate /www/ssl/test1.example.org.pem;
  ssl_certificate_key /www/ssl/test1.example.org.key;
  ssl_session_cache shared:sslcache:20m;
  ssl_session_timeout 10m;
  
  location / {
    root /www/example1;
    if ( $scheme = http ) {
    rewrite ^/(.*)$ https://test1.example.org/$1 redirect;
    }
  }
}
[root@centos7-01 ssl]# vi /apps/nginx/conf/vhost/example2.conf
server {
  listen 80;
  listen 443 ssl;
  server_name test2.example.org;
  ssl_certificate /www/ssl/test2.example.org.pem;
  ssl_certificate_key /www/ssl/test2.example.org.key;
  ssl_session_cache shared:sslcache:20m;
  ssl_session_timeout 10m;
  
  location / {
    root /www/example2;
    if ( $scheme = http ) {
    rewrite ^/(.*)$ https://test2.example.org/$1 redirect;
    }
  }
}
[root@centos7-01 ssl]# systemctl reload nginx

配置windows hosts文件,進(jìn)行驗(yàn)證
192.168.184.101 test1.example.org test2.example.org



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容