企业高性能web服务器

Web服务基础介绍

.1 Apache prefork 模型

预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024

每个子进程有一个独立的线程响应用户请求

相对比较占用内存,但是比较稳定,可以设置最大和最小进程数

是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景

优点:稳定

缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景


2 Apache worker 模型

一种多进程和多线程混合的模型

有一个控制进程,启动多个子进程

每个子进程里面包含固定的线程

使用线程程来处理请求

当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求,

由于其使用了线程处理请求,因此可以承受更高的并发

优点:相比prefork 占用的内存较少,可以同时处理更多的请求

缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超

时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在

prefork模式下,同样会发生


3 Apache event模型

Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll)

每个进程响应多个请求,在现在版本里的已经是稳定可用的模式

它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题

(某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)

event MPM中,会有一个专门的线程来管理这些keepalive类型的线程

当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场

景下的请求处理能力

优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep

alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放

缺点:没有线程安全控制

Nginx-高性能的 Web 服务端

Nginx是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的,开发

工作最早从2002年开始,第一次公开发布时间是2004年10月4日,版本号是0.1.0

 2019年3月11日F5 与 NGINX达成协议,F5 将收购 NGINX 的所有已发行股票,总价值约为 6.7 亿美元。

6.7亿美金约合44.97亿人民币,nginx核心模块代码长度198430(包括空格、注释),所以一行代码约为

2.2万人民币

官网地址

www.nginx.org

 Nginx历经十几年的迭代更新(

https://nginx.org/en/CHANGES), 目前功能已经非常完善且运行稳

定,另外Nginx的版本分为开发版、稳定版和过期版,nginx以功能丰富著称,它即可以作为http服务

器,也可以作为反向代理服务器或者邮件服务器能够快速的响应静态网页的请求

支持FastCGI/SSL/Virtual Host/URL Rwrite /Gzip / HTTP Basic Auth/http或者TCP的负载均衡(1.9版本以

上且开启stream模块)等功能,并且支持第三方的功能扩展

基于Nginx的工作场景

下载安装nginx

环境

Wget

解压

编译

启动nginx

查看

Curl 172.25.254.100

关闭debug减小内存

重新编后make

然后

网页查看

平滑升级流程

将旧Nginx二进制文件换成新Nginx程序文件(注意先备份)

向master进程发送USR2信号master进程修改pid文件名加上后缀.oldbin,成为nginx.pid.oldbin master进程用新Nginx文件启动新master进程成为旧master的子进程,系统中将有新旧两个Nginx主进程共同提供Web服务,当前新的请求仍然由旧Nginx的worker进程进行处理,将新生成的master进程的PID存放至新生成的pid文件nginx.pid

向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止

向旧master进程发送QUIT信号,关闭老master,并删除Nginx.pid.oldbin文件

如果发现升级有问题,可以回滚∶向老master发送HUP,向新master发送QUIT

下载安装新版nginx

解压编译

只make 不install

查看两个版本

#把之前的旧版的nginx命令备份

#把新版本的nginx命令复制过去

#检测一下有没有问题

USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的 nginx #此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80 #此时Nginx开启一个新的master进程,这个master进程会生成新的worker进程,这就是升级后的Nginx进 程,此时老的进程不会自动退出,但是当接收到新的请求不作处理而是交给新的进程处理

回滚

kill -HUP   6422

kill -WINCH  到24

完成回滚

IO

非阻塞型 I/O 模型 (nonblocking IO

用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据 到达后,才真正读取到数据,继续执行。即 “轮询”机制存在两个问题:如果有大量文件描述符都要等, 那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户 态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长, 程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一 般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。 非阻塞:程序向内核发送请I/O求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结 果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核I/O是否完 成。 查看上图可知,在设置连接为非阻塞时,当应用进程系统调用 recvfrom 没有数据返回时,内核会立即返 回一个 EWOULDBLOCK 错误,而不会一直阻塞到数据准备好。如上图在第四次调用时有一个数据报准 备好了,所以这时数据会被复制到 应用进程缓冲区 ,于是 recvfrom 成功返回数据 当一个应用进程这样循环调用 recvfrom 时,称之为轮询 polling 。这么做往往会耗费大量CPU时间,实 际使用很少

多路复用 I/O 型(I/O multiplexing)

上面的模型中,每一个文件描述符对应的IO是由一个线程监控和处理

多路复用IO指一个线程可以同时(实际是交替实现,即并发完成)监控和处理多个文件描述符对应各自的IO,即复用同一个线程

一个线程之所以能实现同时处理多个IO,是因为这个线程调用了内核中的SELECT,POLL或EPOLL等系统调用,从而实现多路复用IO

Apache prefork是此模式的select,worker是poll模式。

实际意义

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,就通知该进程多个连接共用一个等待机制,本模型会阻塞进程,但是进程是阻塞在select或者poll这两个系统调用上,而不是阻塞在真正的IO操作上用户首先将需要进行IO操作添加到select中,同时等待select系统调用返回。当数据到达时,IO被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行从流程上来看,使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视IO,以及调用select函数的额外操作,效率更差。并且阻塞了两次,但是第一次阻塞在select上时,select可以监控多个IO上是否已有IO操作准备就绪,即可达到在同一个线程内同时处理多个IO请求的目的。而不像阻塞IO那种,一次只能监控一个IO虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只是注册自己需要的IO请求,然

后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率IO多路复用是最常使用的IO模型,但是其异步程度还不够“彻底”,因它使用了会阻塞线程的select系统调用。因此IO多路复用只能称为异步阻塞IO模型,而非真正的异步IO

优缺点

优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述符一个线程),这样可以大大节省系统资源

缺点:当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理需要 2 次系统调用,占用时间会有增加

 信号驱动式 I/O 模型 (signal-driven IO)

此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处理函数的通知。

在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞

当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此可以提高资源的利用率

缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知

异步阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程

请求后

进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程。

.异步IO模型

异步非阻塞

异步I/O 与 信号驱动I/O最大区别在于,信号驱动是内核通知用户进程何时开始一个I/O操作,而异步I/O是由内核通知用户进程I/O操作何时完成,两者有本质区别,相当于不用去饭店场吃饭,直接点个外卖,把等待上菜的时间也给省了相对于同步I/O,异步I/O不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。

信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续操作了

优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠

缺点:要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的异步 I/O,在 Linux 系统下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编程时以 IO 复用模型模式+多线程任务的架构基本可以满足需求

Linux提供了AIO库函数实现异步,但是用的很少。目前有很多开源的异步IO库,例如libevent、libev、libuv。

异步非阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核调用的

IO如果不能立即返回,内核会继续处理其他事物,直到IO完成后将结果通知给内核,内核在将IO完成的

结果返回给进程,期间进程可以接受新的请求,内核也可以处理新的事物,因此相互不影响,可以实现较大的同时并实现较高的IO复用,因此异步非阻塞使用最多的一种通信方式。

Nginx 介绍

Nginx官网: nginx news

nginx的其它的二次发行版:

Tengine:由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加

了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了

很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。从2011年12月开始,

Tengine成为一个开源项目官网:

http://tengine.taobao.org/

 OpenResty:基于 Nginx 与 Lua 语言的高性能 Web 平台, 章亦春团队开发,官网

OpenResty:基于 Nginx 与 Lua 语言的高性能 Web 平台, 章亦春团队开发,官网: http://openresty.org/cn/

Nginx 功能介绍

静态的web资源服务器html,图片,js,css,txt等静态资源

http/https协议的反向代理

结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求

tcp/udp协议的请求转发(反向代理)

imap4/pop3协议的反向代理

基础特性

模块化设计,较好的扩展性

高可靠性

支持热部署:不停机更新配置文件,升级版本,更换日志文件

低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存

event-driven,aio,mmap,sendfile

 Web 服务相关的功能

虚拟主机(server)

支持 keep-alive 和管道连接(利用一个连接做多次请求)

访问日志(支持基于日志缓冲提高其性能)

url rewirte

路径别名

基于IP及用户的访问控制

支持速率限制及并发数限制

重新配置和在线升级而无须中断客户的工作进程

Nginx 的进程结构

主进程(master process)的功能:

对外接口:接收外部的操作(信号)

对内转发:根据外部的操作的不同,通过信号管理 Worker

监控:监控 worker 进程的运行状态,worker 进程异常终止后,自动重启 worker 进程

读取Nginx 配置文件并验证其有效性和正确性

建立、绑定和关闭socket连接

按照配置生成、管理和结束工作进程

接受外界指令,比如重启、升级及退出服务器等指令

不中断服务,实现平滑升级,重启服务并应用新的配置

开启日志文件,获取文件描述符

不中断服务,实现平滑升级,升级失败进行回滚处理

编译和处理perl脚本

工作进程(worker process)的功能:

所有 Worker 进程都是平等的

实际处理:网络请求,由 Worker 进程处理

Worker进程数量:一般设置为核心数,充分利用CPU资源,同时避免进程数量过多,导致进程竞争

CPU资源,

增加上下文切换的损耗

接受处理客户的请求

将请求依次送入各个功能模块进行处理

I/O调用,获取响应数据

与后端服务器通信,接收后端服务器的处理结果

缓存数据,访问缓存索引,查询和调用缓存数据

发送请求结果,响应客户的请求

接收主程序指令,比如重启、升级和退出等   

Nginx 命令示例

验证版本及编译参数

]# vim /usr/local/nginx/conf/nginx.conf

 nginx: [emerg] "worker_processes" directive is duplicate in

/usr/local/nginx/conf/nginx.conf:3

nginx -g "daemon off;

Nginx 启动文件

全局配置

#修改pam限制

[root@Nginx ~]# sudo -u nginx ulimit -n

新建一个 PC web 站点

root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location

 root示例

location 的详细使用

在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;

ngnix会根据用户请求的URI来检查定义的所有location,按一定的优先级找出一个最佳匹配,而后应用其配置在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最高的一个uri

 uri是用户请求的字符串,即域名后面的web文件路径

然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索,并使用此location处理此请求。

=  后只能是文件

#语法规则:

location [ = | ~ | ~* | ^~ ] uri { ... }

 =          #用于标准uri前,需要请求字串与uri精确匹配,大小敏感,如果匹配成功就停止向下匹配并立即处理此请求   

^~     #用于标准uri前,表示包含正则表达式,并且匹配以指定的正则表达式开头 #对uri的最左边部分做匹配检查,不区分字符大小写    

~            #用于标准uri前, 表示包含正则表达式,并区分大小写

~*           #用于标准uri前, 表示包含正则表达式,并不区分大小写

不带符号      #匹配起始于此uri的所有uri

\              #用于标准uri前,表示包含正则表达式并且转义字符。可以将 . * ?等转义为普通符号。

#匹配优先级从高到低:

=, ^~, ~/~*, 不带符号

Nginx 账户认证功能

自定义错误日志

长连接配置

keepalive_timeout timeout [header_timeout];     #设定保持连接超时时长,0表示禁止长连接,

默认为75s

                                                #通常配置在http字段作为站点全局配置

keepalive_requests 数字;                      #在一次长连接上所允许请求的资源的最大数量

                                                #默认为100次,建议适当调大,比如:500

Vim  /usr/local/nginx/conf/nginx.conf

检测文件是否存在

作为下载服务器配置

Nginx高级配置

状态页

Nginx 压缩功能

查看

Nginx的变量使用

nginx的变量可以在配置文件中引用,作为功能判断或者日志等场景使用

变量可以分为内置变量和自定义变量

内置变量是由nginx模块自带,通过变量可以获取到众多的与客户端访问相关的值。

内置变量

Alphabetical index of variables

$remote_addr;

 #存放了客户端的地址,注意是客户端的公网IP

$args;

#变量中存放了URL中的所有参数

#例如:https://search.jd.com/Search?keyword=手机&enc=utf-8

 #返回结果为: keyword=手机&enc=utf-8

$is_args #如果有参数为? 否则为空

$document_root; #保存了针对当前资源的请求的系统根目录,例如:/webdata/nginx/timinglee.org/lee

$document_uri; #保存了当前请求中不包含参数的URI,注意是不包含请求的指令 #比如:http://lee.timinglee.org/var?\id=11111会被定义为/var #返回结果为:/var

$host; #存放了请求的host名称

limit_rate 10240; echo $limit_rate; #如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0

$remote_port;

 #客户端请求Nginx服务器时随机打开的端口,这是每个客户端自己的端口

$remote_user;

 #已经经过Auth Basic Module验证的用户名

$request_body_file;

 #做反向代理时发给后端服务器的本地资源的名称

$request_method;

#请求资源的方式,GET/PUT/DELETE等

$request_filename; #当前请求的资源文件的磁盘路径,由root或alias指令与URI请求生成的文件绝对路径, #如:webdata/nginx/timinglee.org/lee/var/index.html

$request_uri; #包含请求参数的原始URI,不包含主机名,相当于:$document_uri?$args, #例如:/main/index.do?id=20190221&partner=search

$scheme; #请求的协议,例如:http,https,ftp等

$server_protocol; #保存了客户端请求资源使用的协议的版本,例如:HTTP/1.0,HTTP/1.1,HTTP/2.0等

$server_addr; #保存了服务器的IP地址

$server_name; #虚拟主机的主机名

$server_port; #虚拟主机的端口号

$http_user_agent; #客户端浏览器的详细信息

$http_cookie; #客户端的所有cookie信息

$cookie_ #name为任意请求报文首部字部cookie的key名

$http_ #name为任意请求报文首部字段,表示记录请求报文的首部字段,ame的对应的首部字段名需要为小写,如果有 横线需要替换为下划线

示例

自定义变量

nginx的网页从写功能

Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求

此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库

rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用功能

比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问

另外还可以在一定程度上提高网站的安全性

ngx_http_rewrite_module 模块指令

官方文档: Module ngx_http_rewrite_module

If set break return rewrite

重定向  rewirte flag

介绍

利用nginx的rewrite的指令,可以实现url的重新跳转,rewrite有四种不同的flag,分别是redirect(临时重定向302)、permanent(永久重定向301)、break和last。其中前两种是跳转型的flag,后两种是代理型

跳转型指由客户端浏览器重新对新地址进行请求

代理型是在WEB服务器内部实现跳转

redirect;

 #临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端

#由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302

 permanent;

 #重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端

#由客户端重新发起请求,状态码:301

 break;

 #重写完成后,停止对当前URL在当前location中后续的其它重写操作

#而后直接跳转至重写规则配置块之后的其它配置,结束循环,建议在location中使用

#适用于一个URL一次重写

last;

 #重写完成后,停止对当前URI在当前location中后续的其它重写操作,

#而后对新的URL启动新一轮重写检查,不建议在location中使用

#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户

示例

If

Break

Return

rewirte  临时和永久

Nginx  https

全站加密

盗链

网页

#盗链网页

<html>

  <head>

    <meta http-equiv=Content-Type content="text/html;charset=utf-8">

    <title>盗链</title>

</head>

  <body>

    <img src="http://www.timinglee.org/images/lee.png" >

    <h1 style="color:red">欢迎大家</h1>

    <p><a href=http://www.timinglee.org>狂</a>出门见喜</p>

  </body>

</html>

缓存

反向代理

在两台客户机中

在nginx中

Proxy_pass 只能写一个不能同时用

负载均衡

实现 FastCGI

CGI的由来: 最早的Web服务器只能简单地响应浏览器发来的HTTP请求,并将存储在服务器上的HTML文件返回给浏 览器,也就是静态html文件,但是后期随着网站功能增多网站开发也越来越复杂,以至于出现动态技 术,比如像php(1995年)、java(1995)、python(1991)语言开发的网站,但是nginx/apache服务器并不 能直接运行 php、java这样的文件,apache实现的方式是打补丁,但是nginx缺通过与第三方基于协议实 现,即通过某种特定协议将客户端请求转发给第三方服务处理,第三方服务器会新建新的进程处理用户 的请求,处理完成后返回数据给Nginx并回收进程,最后nginx在返回给客户端,那这个约定就是通用网 关接口(common gateway interface,简称CGI),CGI(协议) 是web服务器和外部应用程序之间的接口 标准,是cgi程序和web服务器之间传递信息的标准化接口。

为什么会有FastCGI?

 CGI协议虽然解决了语言解析器和 Web Server 之间通讯的问题,但是它的效率很低,因为 Web Server 每收到一个请求都会创建一个CGI进程,PHP解析器都会解析php.ini文件,初始化环境,请求结束的时候 再关闭进程,对于每一个创建的CGI进程都会执行这些操作,所以效率很低,而FastCGI是用来提高CGI性 能的,FastCGI每次处理完请求之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请 求。这样的话每个请求都不用再重新创建一个进程了,大大提升了处理效率。

什么是PHP-FPM?

 PHP-FPM(FastCGI Process Manager:

 FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。

 进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server 的请求

 worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理

FastCGI配置

然后编译安装

Make

Php 相关配置优化‘

生成主配置文件

生成启动文件

Vim / usr/local/nginx/conf.d/vhosts.conf

安装memcache模块

解压 

make

复制测试文件到nginx发布目录中

配置php加载模块

配置php加载memcache模块

部署memcached

php高速缓存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值