毕业前,毕设完成后,我闲极无聊接触了一下socket编程,用C++的Qt框架写了玩具一样的TCP和UDP通信客户端。跟直系学长电话聊天时被建议深挖一下socket,尝试走走后端或者架构师路线。问该怎么深挖,答研究源码,要学习socket相关知识,研究服务器源码是最合适不过的了。至于选择哪个服务器,经过考量调查,发现比起比较沉重庞大的apache,nginx更加小巧,也非常优秀。于是在开始正式吃源码之前,我先开始了一番自我科普工作。
1、进程模型
首先,默认的,与其他服务器一样,Unix下的nginx也以daemon(守护进程)的形式持续在后台运行。虽然nginx也可以以调试为目的关掉后台模式,使用前台模式,甚至可以通过配置取消master进程(后面会详细解释),使nginx以单进程的形式工作。但是这些与nginx引以为傲的架构关系不大,这里按下不表。尽管nginx也支持多线程方式,我们还是着重来了解下其默认的多进程方式。
nginx在启动后会创建一个master进程(主进程)和若干个worker进程(从进程)。master进程主要负责管理worker进程,具体来说就是接收来自管理员的信号并转发给对应worker进程;监控worker进程的工作状态,在worker进程异常终止时重新创建并启动worker进程。而worker进程负责处理基本的网络事件。worker进程之间优先级对等、相互独立,公平竞争来自客户端的请求,每个请求只由一个worker进程处理。nginx进程模型示意图如图1所示。
图1 nginx进程模型示意图
worker进程的数量可以进行设置,一般设置与CPU核数一致,这一原则与nginx的事件处理模型有关。后面会继续介绍nginx的事件处理模型。
2、信号与请求
nginx与外界互动无非通过两种接口界面:来自管理员的信号和来自客户端的请求。下面我们举例说明nginx是如何处理信号与请求的。
管理员要控制nginx需要与master进程通信,向master进程发送指令信号即可。比如,nginx在0.8版本之前使用kill -HUP [pid]命令来重启nginx。使用这个命令重启nginx将实现从容地重启过程,期间服务不中断。master进程在接到HUP指令后首先会重新加载配置文件,然后启动新的worker进程,向旧的worker进程发送停止信号。这时新的worker进程开始接收网络请求,旧的worker进程停止接收新的请求,等到处理完当前请求后,旧的worker进程就退出销毁了。在0.8版本以后,nginx引入了一系列命令行参数以方便管理服务器,比如./nginx -s reload和./nginx -s stop,分别用来重启和停止nginx。执行操作命令时,我们实际上启动了一个新的nginx进程,这个进程在解析命令中的参数后,自行向master进程发送相应的信号,达成与之前手动发送信号相同的效果。
3、请求与事件
服务器最常处理的就是80端口http协议的请求了, 以此为例说明一下nginx处理请求的过程。首先,每一个worker进程都是从master进程fork(分叉)而成的,master进程中先建立好需要监听的socket(套接字,即IP地址+端口号)和相应的listenfd(监听文件描述符或句柄)。我们知道socket通信中每个进程都要分配一个端口号,worker进程的socket分配工作就由master进程来完成。所有worker进程的listenfd在新的连接到来时变得可读,为保证只有一个worker进程处理连接,各worker进程在注册listenfd读事件前先要抢accept_mutex(接受连接互斥锁),一个worker进程抢注连接成功后,开始读取请求、解析请求、处理请求并反馈数据给客户端。
4、进程模型分析
nginx使用但不仅仅使用多进程请求处理模型(PPC),每个worker进程一次只处理一个请求,使得请求间资源独立不需要上锁,进程间互不影响能并行处理请求。一个请求处理失败导致一个worker进程异常退出,不会使服务中断,而是由master进程立刻重新启动一个新的worker进程,降低了服务器面临的整体风险,使服务更加稳定。但是相比多线程模型(TPC),系统开销略大,效率略低,这需要借助别的手段来改进。
5、nginx的高并发机制——异步非阻塞事件机制
IIS的事件处理机制是多线程,每个请求独占一个工作线程。由于多线程比较占用内存,线程间的上下文切换(反复的对寄存器组进行保护现场和恢复现场的操作)带来的CPU开销也很大,多线程机制的服务器在面临数千并发量时,会给系统造成很大的压力,高并发性能并不算理想,当然如果硬件足够出色,能够提供足够的系统资源,系统压力也就不再是问题了。
我们深入到系统层面讨论一下多进程与多线程,阻塞式机制与非阻塞式机制的区别。
熟悉操作系统的同学应该了解,多线程的出现是为了在资源充足的情况下更充分的调度使用CPU,尤其对提高多核CPU的利用率十分有益。但是线程是系统任务的最小单位,而进程却是系统分配资源的最小单位,这就意味着多线程将面临一个很大的问题:当线程数增多,资源需求变大,这些线程的母进程可能无法立即一口气申请到足够所有线程使用的资源,而当系统手里没有足够的资源满足一个进程时,它会选择让整个进程都等着。这时即使系统资源足够一部分线程正常工作,母进程也无法申请到这些资源,导致所有线程一起等待。直白的说,使用多线程,进程内的线程间可以灵活的进行调度(虽然增加了线程死锁的风险和线程切换的开销),但是却无法保证母进程在逐渐庞大沉重时还能够在系统中得到合理的调度。由此可见,多线程确实可以提高CPU利用率,但是并不是解决服务器高并发请求问题的理想解决方案,且不说在高并发状态下CPU的高利用率也无法维持。以上是IIS的多线程同步阻塞式事件机制。
nginx的多进程机制保证了每个请求独立申请系统资源,一旦满足条件,每一个请求都可以立即被处理,即异步非阻塞处理。但是创建进程需要的资源开销会比线程多一些,为了节约进程数,nginx使用了一些进程调度算法,使I/O事件处理不仅仅靠多进程机制,而是异步非阻塞的多进程机制。下面我们就来具体的引入nginx的异步非阻塞事件处理机制。
6、epoll
Linux下,言高并发的高性能网络必epoll,nginx也正是使用了epoll模型作为网络事件的处理机制。我们先看看epoll是怎么来的。
最早的调度方案是异步忙轮询方式,即持续的轮询I/O事件也就是遍历socket集合的访问状态,显然服务器空闲时这一方案造成了无谓的CPU开销。
后来,select和poll作为调度进程和提高CPU利用率的代理先后出现,字面上看,一个是“选择”,一个是“投票”,它们的本质相同,都是轮询socket集合并处理请求,与之前不同的地方在于,它们能够监视I/O事件,空闲时轮询线程将被阻塞,而一个或多个I/O事件到来时则被唤醒,摆脱了“忙轮询”的“忙”,成为异步轮询方式。select/poll模型轮询的是整个FD(文件描述符)集合即socket集合,网络事件处理效率随着并发请求数线性降低,所以使用一个宏来限制最大并发连接数。同时,select/poll模型的内核空间与用户空间通信方式为内存复制,带来较高的开销。以上缺点催生了新模型的产生。
epoll可以认为是event poll的简写,是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用I/O接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。首先,epoll没有最大并发连接数的限制,上限是可以打开的最大文件数,这与硬件内存大小有关,1GB的机器上大约是10w左右;然后是epoll最显著的优点,它只对“活跃”的socket进行操作,因为只有那些被内核I/O读写事件异步唤醒的socket才被放入ready队列,准备进入worker进程被处理,这在实际生产环境中节省了大量轮询开销,极大的提高了事件处理效率;最后,epoll使用共享内存(MMAP)的方式实现内核空间与用户空间的通信,省掉了内存复制的开销。额外的,nginx中使用epoll的ET(边缘触发)工作模式即快速工作模式。ET模式下,只支持非阻塞socket,FD就绪即由内核通过epoll发送通知,经过某些操作使FD不再是就绪状态时也会发送通知,但如果一直没有I/O操作导致FD变为未就绪状态将不再发送通知。总的来说,nginx在Linux下是基于事件,利用epoll处理网络事件的。
版权声明:本文为博主原创文章,未经博主允许不得转载。
以上就介绍了nginx核心架构概述,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

使用数据库存储会话的主要优势包括持久性、可扩展性和安全性。1.持久性:即使服务器重启,会话数据也能保持不变。2.可扩展性:适用于分布式系统,确保会话数据在多服务器间同步。3.安全性:数据库提供加密存储,保护敏感信息。

在PHP中实现自定义会话处理可以通过实现SessionHandlerInterface接口来完成。具体步骤包括:1)创建实现SessionHandlerInterface的类,如CustomSessionHandler;2)重写接口中的方法(如open,close,read,write,destroy,gc)来定义会话数据的生命周期和存储方式;3)在PHP脚本中注册自定义会话处理器并启动会话。这样可以将数据存储在MySQL、Redis等介质中,提升性能、安全性和可扩展性。

SessionID是网络应用程序中用来跟踪用户会话状态的机制。1.它是一个随机生成的字符串,用于在用户与服务器之间的多次交互中保持用户的身份信息。2.服务器生成并通过cookie或URL参数发送给客户端,帮助在用户的多次请求中识别和关联这些请求。3.生成通常使用随机算法保证唯一性和不可预测性。4.在实际开发中,可以使用内存数据库如Redis来存储session数据,提升性能和安全性。

在无状态环境如API中管理会话可以通过使用JWT或cookies来实现。1.JWT适合无状态和可扩展性,但大数据时体积大。2.Cookies更传统且易实现,但需谨慎配置以确保安全性。

要保护应用免受与会话相关的XSS攻击,需采取以下措施:1.设置HttpOnly和Secure标志保护会话cookie。2.对所有用户输入进行输出编码。3.实施内容安全策略(CSP)限制脚本来源。通过这些策略,可以有效防护会话相关的XSS攻击,确保用户数据安全。

优化PHP会话性能的方法包括:1.延迟会话启动,2.使用数据库存储会话,3.压缩会话数据,4.管理会话生命周期,5.实现会话共享。这些策略能显着提升应用在高并发环境下的效率。

thesession.gc_maxlifetimesettinginphpdeterminesthelifespanofsessiondata,setInSeconds.1)它'sconfiguredinphp.iniorviaini_set().2)abalanceIsiseededeedeedeedeedeedeedto to to avoidperformance andununununununexpectedLogOgouts.3)

在PHP中,可以使用session_name()函数配置会话名称。具体步骤如下:1.使用session_name()函数设置会话名称,例如session_name("my_session")。2.在设置会话名称后,调用session_start()启动会话。配置会话名称可以避免多应用间的会话数据冲突,并增强安全性,但需注意会话名称的唯一性、安全性、长度和设置时机。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

记事本++7.3.1
好用且免费的代码编辑器

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),