HTTP之Web服务器是如何进行工作的!
Web服务器是如何进行工作的
====================文章摘自《HTTP权威指南》======================
1、 建立连接—接收一个客户端的连接,或者如果不希望与这个客户端建立连接,就将其关闭;
2、 接收请求—从网络中读取一条HTTP请求报文;
3、 处理请求—对请求报文进行解释,并采取行动;
4、 访问资源—访问报文中指定的资源;
5、 构建响应—创建带有正确首部的HTTP响应报文;
6、 发送响应—将响应回送给客户端;
7、 记录事务处理过程—将与已经完成事务有关内容记录在一个日志文件中;
1、 接收客户端连接
(1)、
客户端请求一条到服务器的TCP连接时,Web服务器会建立连接,判断连接的另一端是哪个客户端,从TCP连接中将IP地址解析出来。一旦新连接建立起来并被接受,服务器就会将新连接添加到其现存的Web服务器连接列表中,做好监视连接上数据传输的准备。
Web服务器可以随时拒绝或立即关闭任意一条连接。有些Web服务器会因为客户端IP地址或主机名是未认证的,或者因为它是已知的恶意客户端而关闭连接。Web服务器也可以使用其他识别技术。
(2)、客户端主机名识别
可以用“反向DNS”对大部分Web服务器进行配置,以便将客户端IP地址转换成客户端主机名。Web服务器可以将客户端主机名用于详细的访问控制和日志记录。但要注意的事,主机名查找可能会花费很长的时间,这样会降低Web事务处理的速度。很多大容量Web服务器要么会禁止主机名解析,要么只允许对特定的内容进行解析。
(3)、通过ident确定客户端用户
有些Web服务器还支持IETFident的协议。服务器可以通过ident协议找到发起HTTP连接的用户名,这些信息对Web服务器的日志记录特别有用—流行的通用日志格式(Common Log Format)的第二个字段就包含了每条HTTP请求的ident用户名。
如果客户端支持ident协议,就在TCP端口113上监听ident请求。图5-4说明了ident协议是如何工作的。在图5-4a中,客户端打开了一条http连接。然后服务器打开自己到客户端ident服务器端口(113)的连接,发送一条简单的请求,询问与(由客户端和服务器端口号指定的)新连接相对应的用户名,并从客户端解析出包含用户名的响应。
2、 接收请求报文
连接上有请求报文达到时,web服务器会从网络连接中读取数据,并将请求报文中的内容解析出来(见图5-5)
解析请求报文时,web服务器会:
A、 解析请求行,查找请求方法、指定的资源标识符(URI)以及版本号,各项之间由一个空格分隔,并已一个回车换行(CRLF)序列作为行的结束;
B、 读取以CRLF截尾的报文首部;
C、 检测到以CRLF结尾的、标识首部结尾的空行(如果有的话);
D、 如果有的话(长度由content-Length首部指定),读取请求主题;
解析请求报文时,web服务器会不定期从网络上接收输入数据。网络连接可能随时都会出现延迟。Web服务器需要从网络中读取数据,将部分报文数据临时存储在内存中,直到收到足以解析的数据并理解其意义为止。
(1)、报文的内部表示法
有些web服务器还会用便于进行报文操作的内部数据结构来存储请求报文。比如,数据结构中可能包含有指向请求报文中各个片段的指针及其长度,这样就可以将这些首部放在一个快速查询表中,以便快速访问特定首部的具体值了。
(2)、连接的输入\输出处理结构
高性能的web服务器能够同时指出数千条连接。这些连接使得服务器可以与世界各地的客户端进行通信,每个客户端都想服务器打开了一条或多条连接。某些连接可能在向服务器快速的发送请求,而其他一些连接可能在慢慢发送,或不经常发送请求,还有一些可能是空闲的,安静的等待着将来可能出现的动作。
因为请求可能在任意时间到达,所以web服务器会不停的观察有无新的请求。不同的web服务器结果会以不同的方式为请求服务,见图5-7所示。
A、 单线程web服务器(5-7a)
单线程的web服务器一次只处理一个请求,直到其完成为止。一个事务处理结束后,采取处理下一条请求。这种结构易于实现,但在处理过程中,所有其他链接都会被忽略。这样会造成严重的性能问题,只适用于低负荷的服务器,以及type-o-serve这样的诊断工具。
B、 多进程及多线程web服务器(5-7b)
多进程和多线程服务器用多个进程或更高效的线程同时对请求进行处理。可以根据需要创建,或者预先创建一些线程/进程。有些服务器会为每条连接分配一个线程/进程,但当服务器同时处理成百上千甚至数以万计的连接时,需要的进程或线程的数量可能会消耗太多的内存和系统资源。因此很多多线程web服务器都会对线程/进程的最大数量进行限制。
C、 复用I/O的服务器
为了支持大量的连接,很多web服务器都采用的复用结构。在复用结构中,要同时监视所有连接上的活动。当连接的状态发生变化时(比如,有数据可用,或出现错误时),就对那条连接进行少量的处理;处理结束之后,将连接返回到开放连接列表中,等待下一次状态变化。只有在有事情可做时才会对连接进行处理;在空闲连接上等待的并不会绑定线程和进程。
D、 复用的多线程web服务器(5-7d)
有些系统会将多线程和复用功能结合在一起,以利用计算机平台上的多个CPU。多个线程(通常是一个物理处理器)中的每一个都在观察打开的连接(或打开的连接中的一个子集),并对每条连接执行少量的任务。
3、 处理请求
一旦web服务器收到了请求,就可以根据方法、资源、首部和可选的主体部分来对请求进行处理了。
有些方法(比如POST)要求请求报文中必须带有实体主体部分的数据。其他一些方法(OPTIONS)允许有请求的主体部分,也允许没有。少数方法(GET)禁止在请求报文中包含实体的主体数据。
4、 对资源的映射和访问
Web服务器是资源服务器。他们负责发送预先创建好的内容,比如HTML页面或者JPEG图片,以及运行在web服务器上的资源生成程序锁产生的动态内容。
在web服务器将内容传送给客户端之前,要将请求报文中的URI映射为web服务器上适当的内容或内容生成器,以识别出内容的源头。
(1)、docroot
Web服务器支持各种不同类型的资源映射,但最简单的资源映射形式就是请求URI作为名字来访问web服务器文件系统中的文件。通常web服务器的文件系统会有一个特殊的文件夹专门用于存放web内容。这个文件夹被称为文件根目录(document root或docroot)。 Web服务器从请求报文中获取URI,并将其附加在文档根目录的后面
在图5-8中,有一条对/specials/saw-blade.gif的请求达到。在这个例子中,web服务器的文档根目录为/usr/local/httpd/files.web服务器会返回文件/usr/local/httpd/files/specials/saw-blade.gif。
在配置文件httpd.conf中添加一个documentroot行就可以为Apache web服务器设置文档的根目录了。Documentroot /usr/local/httpd/files
服务器需要注意,不能让相对URL推到docroot之外,将文件系统的其余部分暴露出来。比如,大多数成熟的web服务器都不允许这样的URI看到joe五金商店文档根目录上一级的文件:http://www.joe-hardware.com/../
A、 虚拟托管的docroot
虚拟托管的web服务器会在同一台web服务器上提供多个web站点,每个站点在服务器上都会有自己独有的文档根目录。虚拟托管web服务器会根据URI或Host首部的IP地址或者主机名来识别要使用的正确文档根目录。通过这种方式,即使请求URI完成相同,托管在同一web服务器的两个web站点也可以拥有完全不同的内容了。
图5-9中的服务器托管了两个站点,www.joes-hardware.com和www.marys-antiques.com。服务器可以通过HTTP的host首部,或根据不同的IP地址来区分不同的web站点。
a、当请求A达到时,服务器或获取文件/docs/joe/index.html.
b、当请求B达到时,服务器会获取文件/docs/mary/index.html.
对大多数服务器来说,配置虚拟托管的文档根目录是很简单的。对常见的Apache web服务器来说,需要为每个虚拟的web站点配置一个Vitualhost块,而且每个虚拟服务器都要包含documentroot。
(2)、目录列表
Web服务器可以接收对目录URL的请求,其路径可以解析为一个目录,而不是文件。我们可以对大多数服务器进行配置,使其在客户端请求URL时采取不同的动作。
—返回一个错误
—不返回目录,返回一个特殊的默认的“索引文件”
—扫描目录,返回一个包含目录内容的HTML页面
大多数web服务器都会去查找目录中一个名为index.html或index.htm的文件来代表此目录。如果用户请求的是一个目录的URL,而且这个目录有一个名为index.html(index.htm)的文件,服务器就会返回那个文件的内容。
(3)、动态内容资源的映射
Web服务器还可以将URl映射为动态资源——也就是说,映射到按需动态生成内容的程序上去(图5-11)。实际上,有一个大类为应用程序服务器的web服务器会将web服务器连接到复杂的后端应用程序上去。Web服务器要能够分辨出资源什么时候是动态的,动态内容生成程序位于何处,以及如何运行那个程序。大多数web服务器都提供了一些基本的机制以识别和映射动态资源。
Apache服务器允许用户将URI路径名映射为可执行文件目录。服务器收到一条带有可执行路径组件的对URI的请求时,会试着去执行响应服务器目录中的程序。例如,下列Apache配置指令就表明所有路径以/cgi-bin/开头的URI都应该执行在目录/usr/local/etc/httpd/cgi-programs/中找到相应的文件。
ScriptAlias/cgi-bin/ /usr/local/etc/httpd/cgi-programs/
Apache还允许用户用一个特殊的扩展文件名来标识可执行文件。通过这种方式就可以将可执行脚本放置在任意目录中了。下面的Apache配置指令说明要执行所有以.cgi结尾的web资源:Addhandler cgi-script.cgi
5、 构建响应
一旦Web服务器识别出了资源,就执行请求方法中描述的动作,并返回响应报文。响应报文中包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主题。
(1)、响应实体
如果事务处理产生了响应实体,就将内容放在响应报文中回送过。如果有响应主体的话,响应报文中通常包括:
描述了响应主体MIME类型的content-type首部;
描述了响应主体长度的content-length首部;
实际报文的主体内容;
(2)、MIME类型
Web服务器要负责确定响应主体的MIME类型。有很多配置服务器的方法可以将MIME类型与资源关联起来。
A、 MIME类型
Web服务器可以用文件的扩展名来说明MIME类型。Web服务器会为每个资源扫描一个包含了所有扩展名的MIME类型文件,以确定其MIME类型。这种基于扩展名的类型相关是最常见的。
B、 魔法分类
Apache web服务器可以扫描每个资源的内容,将其与一个已知的模式表(被称为魔法文件)进行匹配,以决定每个文件的MIME类型。这样做可能比较慢,但很方便,尤其是文件没有标准的扩展名的时候。
C、 显示分类(Explicit typing)
可以对web服务器进行配置,使其不考虑文件的扩展名或内容,强制特定文件或目录内容拥有某个MIME类型。
D、 类型协商
有些web服务器经过配置,可以以多种文档格式来存储资源。在这种情况下,可以配置web服务器,使其可以通过与用户协商来决定使用哪种格式(及相关的MIME类型)“最好”。
(3)、重定向
Web服务器有时会返回重定向响应而不是成功的报文。Web服务器可以将浏览器重定向到其他地方来执行请求。重定向响应由返回码3XX说明。Location响应首部包含了内容的新地址或优选地址的URI。重定向可用于下列情况。
A、 永久删除的资源
资源可能已经被移动了新的位置,或者被重新命名,有了一个新的URL。Web服务器可以告诉客户端资源已经被重新命名了,这样客户端就可以在从新地址获取资源之前,更新书签之类的信息了。
B、 临时删除的资源
C、 URL增强
服务器通常用重定向来重写URL,往往用于嵌入上下文。当请求到达时,服务器会生成一个新的包含了嵌入式状态信息的URL,并将用户重定向到这个新的URL上去。客户度会跟随这个重定向信息,重新发起请求,但这次请求会包含完整的、经过状态增强的URL。这是在事务间维护状态的有效方式。
D、 负载均衡
E、 服务器关联
Web服务器上可能会有某些用户的本地信息;服务器可以将客户端重定向到包含了那个客户端信息的服务器上去。
F、 规范目录名称
客户端请求的URI是一个不带尾部斜杠的目录名时,大多数web服务器都会将客户端重定向到一个加了斜杠的URI上,这样相对连接就可以正常工作了。
6、 发送响应
Web服务器通过连接发送数据时也会面临与接收数据一样的问题。服务器可能有很多条到各个客户端的连接,有些是空闲的,有些在向服务器发送数据,还有一些在向客户端回送响应数据。
服务器要记录连接的状态,还要特别注意对持久连接的处理。对非持久连接而言,服务器应该在发送了整条报文之后,关闭自己这一段的连接。
对持久连接来说,连接仍可能保持打开状态吗,在这种情况下,服务器要特别小心,要正确的计算content-length首部,不然客户端就无法知道响应什么是时候结束了。
7、 记录日志
最后,当事务结束时,web服务器会在日志文件中添加一个条目,来描述已执行的事务。大多数web服务器都提供了集中日志配置格式。