HTTP,即:HyperText Transfer Protocol的简称,超文本传输协议。1960年美国人泰德·尼尔森构思了一种通过计算机处理文本信息的方法,并称之为超文本(Hypertext),这成为了HTTP标准架构的发展根基。1990年,为了方便分布于世界各地的高能物理学家之间的协作,欧洲粒子物理研究所(European Organization for Nuclear Research,简称CERN)的计算机科学家蒂姆·伯纳斯·李以及与之一同工作的罗伯特·卡里奥,提出了一个基于"超文本"的分布式信息系统——一种将存储于计算机上的相关的信息碎片链接起来的方法。在他们的设想中,通过将网络地址隐藏在屏幕上突出显示的内容背后,从而将多台计算机之间信息被链接在一起。于是,他们就选用了"World-Wide Web"的名字,简称"www"。他们同时也开发了万维网客户端和服务器端,还定义了URL(统一资源定位符)、HTML(超文件标记语言)等。后来泰德·尼尔森组织协调万维网协会(World Wide Web Consortium),并和互联网工程工作小组(Internet Engineering Task Force共同合作研究,最终发布了一系列的RFC,其中著名RFC1945中定义了HTTP/1.0;RFC2616定义了HTTP/1.1以及RFC7540定义的HTTP/2.0。
下面简单来说说HTTP的版本:
HTTP真正公开使用的是其HTTP/0.9版本,其中只提供了一种"GET"方法,并且没有在通讯中指定版本号,且不支持请求头。由于该版本不支持POST方法,所以客户端无法向服务器传递太多信息。
HTTP/1.0
这是第一个在通讯中指定版本号的 HTTP 协议版本,并首次引入了缓存的概念。而且定义了GET、POST、HEAD、PUT、DELETE、TRACE、OPTIONS等多种方法,而且引入了MEMI,使得通过HTTP提供多媒体资源分发成为现实。
HTTP/1.1
当前最常见和常用的版本。默认采用长连接,GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH、MOVE、COPY、LINK、UNLINK、WRAPPED等14种方法,并且还额外提供了Extension-mothed,以期在不改动协议的前提下,可增加另外的方法。更为合理和强大的缓存处理机制、带宽优化及网络连接的使用、错误通知的管理、消息在网络中的发送、互联网地址的维护、安全性及完整性等诸多方面均较HTTP/1.0版本有明显提升。
下面是HTTP/1.1所支持的方法及其相应的功能解释:
GET 请求指定的页面信息,并返回资源主体;
HEAD 类似于GET请求,只不过返回的响应中没有具体的内容,用于获取HTTP首部;
POST 向指定服务器提交表单数据进行处理请求。请求报文主体种包含了要传递的
数据信息内容。POST请求可能会导致新的资源的建立和/或已有资源的修改。
PUT 从客户端向服务器上传可取代指定的文档的内容的数据资源。
DELETE 请求服务器删除指定的资源。
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS 允许客户端查看服务器的性能。
TRACE 回显服务器收到的请求,主要用于测试或诊断。
PATCH 资源主体中包含一个表,表中说明与该URI所表示的原内容的区别。
MOVE 请求服务器将指定的页面移至另一个网络地址。
COPY 请求服务器将指定的页面拷贝至另一个网络地址。
LINK 请求服务器建立链接关系。
UNLINK 断开链接关系。
WRAPPED 允许客户端发送经过封装的请求。
Extension-mothed 在不改动协议的前提下,可增加另外的方法。
HTTP/2.0即超文本传输协议2.0版本,是下一代HTTP协议。是由互联网工程任务组的Hypertext Transfer Protocol Bis工作小组进行开发。是自1999年http1.1发布后的首个更新。HTTP/2.0在2013年8月进行首次合作共事性测试。在开放互联网上HTTP/2.0将只用于https://网址,而http://网址将继续使用HTTP/1,目的是在开放互联网上增加使用加密技术,以提供强有力的保护去遏制主动攻击。
HTTP的采用了最为通用的C/S架构模式,并且采用Request/Response的工作方式实施客户端和服务端的通信,即:一次完整的HTTP事务,必须包含一次Request和一次Response。
HTTP是应用层协议,在传输层依靠TCP来承载和封装/解封装HTTP报文。对于HTTP服务器来说,默认采用TCP的80端口作为有效的套接字组合而进行监听。
一旦有客户端的请求发送到服务器,那么服务器完成一次完整的http请求的处理过程大致可以分为以下几个阶段:
1.建立或处理连接(可能还包含所需的身份验证阶段)
2.接收请求
3.处理请求
4.访问资源
5.构建响应报文
6.发送响应报文
7.记录日志
任何一次完整的http事务,都必须在客户端和服务端的配合下才能顺利完成。对于客户端来说,他们希望每次向服务器发出的请求都能在也应该在极短的时间内被处理,更应该以最高的速度最短的时延来为每个客户端响应;然而对于服务器来讲,不只要是能够响应客户就好,服务器需要做的事情就像上面说的那样,其实有很多步骤的。因此服务器就必须尽量合理分配和利用自身的资源,保证自身正常工作的前提下,尽可能多的处理客户发送的请求。但是每一个客户端请求都需要一个进程或线程来处理,这样就必须要综合考虑内存空间利用率、CPU计算资源的合理分配以及磁盘IO性能,于是就有了下列几种服务器的并发响应模型:
单进程I/O模型:利用极短的时间片分别处理所以请求,使得一系列鱼贯而入的请求得以在短时间内处理完成。这个模型适用于访问量较小请求较简单的场合,这是伪并发处理机制,其实就是串行处理机制。
多进程I/O模型:同时启动多个进程,每个进程响应一个客户端请求;这种模型相对比较重量级,能够真正同时处理的请求数的峰值并不会太大,对系统资源消耗较大,但胜在管理简单,进程的创建和销毁也较容易。
复用的I/O模型:一个进程响应多个请求;这种情况略微复杂,其实是利用线程完成处理的,但是在Linux中使用的线程是伪线程,其实是轻量级进程(LWP),所以与多进程模型比较起来并没有太大的区别。下面是两种常见的实现方式:
多线程模型:只启动一个进程,该进程可生成多个线程,每个线程响应一个请求;
事件驱动模型:只启动一个进程,一个进程直接响应多个请求;这种模型相对来说性能更加优化。
复用的多进程I/O结构模型:启动m个进程,每个进程生成n个线程,每个线程响应一个请求;这个模型在性能上没有明显的改观,但是这是多进程I/O模型和复用I/O多线程模型的折中模型,因此兼具两种模型的优势。
那么,每次的Request到底是请求什么呢?可能很多粗略接触或非业内人士会认为,我用自己的计算机浏览网页,不就是想看哪个网页就请求哪个网页么!这个说法不能说完全错误,因为最终非常有可能是服务器将整个页面都传输到了客户端,但其过程并不是一次性传输整个页面。其实每个页面都是由很多个更小的基本单元构成的,我们可以将这些基本单元称为资源。也就是说,每个页面可能由一个或N多个资源共同组成,而HTTP的每个请求只能从服务器上请求一个资源。如果这个页面只是一个资源组成的,那么这一次就可以返回整个页面;但绝大多数情况下,一个页面包含了不止一个资源,因此,需要请求者连续完成多次HTTP事务,将所有需要的资源全部缓存到本地,再经过客户端程序组合之后显示出来,才成为用户所看到的完整的网页页面。
因为TCP协议的特性,使得在实现每一次完整的HTTP事务时,都是四个阶段:
1.三次握手建立TCP连接
2.客户端发生Request报文
3.服务器响应Response报文
4.四次挥手断开TCP连接
可以看出,TCP的面向连接的特性会大大的降低HTTP的整体的工作效率。于是在HTTP/1.1种开始默认使用长连接来执行HTTP事务,即:如果请求是来自于同一个客户端地址,那么在服务器响应之后没有必要断开此TCP连接,客户端仍然可以利用这个TCP连接进行后续的资源请求。这样一来看起来和谐多了。但另一个问题又随之出现:服务器的资源和服务能力都是很宝贵的,因为大量的建立长连接而消耗了大量的系统资源(内存资源、CPU计算资源以及IO性能等),因此再强大的服务器也会有一个资源分配的上限。面对数量众多的客户端请求,该如何管理那些没有请求发送的长连接呢?又应该如何控制不让某个客户端一直占用服务器的服务能力呢?最终,人们选择了折中,即:每个长连接最多只能发送一定数量的请求,耗尽之后,服务器必须断开此次连接;在一定时间内,如果该长连接没有再次接收到任何的请求,服务器也会断开此次连接。通过这样的双保险设置,可以比较高效的为客户端进行响应,也可以在一定程度上避免资源的巨大浪费。
http协议的实现:
简单的基本http协议服务器,主要提供静态页面内容的浏览和访问,一般包括以下几种:
httpd (apache)
nginx
lighttpd
当然,除了这些之外还有很多是基于Nginx的二次开发版本,比如淘宝的TEngine等。
动态服务器技术,一般是指安放在基本http服务器后端的应用程序服务器,包括:
iis
tomcat
jetty
resin
weblogic
websphere
jboss
glassfish等。
接下来我们简单的就httpd(apache)进行介绍,展开来讨论其功能和工作原理。
首先,我们来说一下httpd的性能特性:
httpd 2.2版本的特性:
高度模块化:core + modules
DSO: Dynamic shared objects,支持模块的动态装载和卸载;
MPM:multipath processing modules,以静态的方式装载到核心,更换后必须重新启动服务;
prefork:多进程模型,一个主进程,多个子进程;一个进程响应一个请求;
主进程:管理子进程;创建套接字;接收用户请求,并派发给某子进程处理;...
子进程:处理请求、响应请求;
worker:多进程多线程模型;一个线程响应一个请求;
主进程:管理子进程;创建套接字;接收用户请求,并派发给某子进程处理;...
子进程:负责管理线程;
线程:处理并响应请求;
event(在2.2版本中该模型尚处于测试阶段):事件驱动模型,多进程模型,每个进程响应多个请求;
主进程:管理子进程;创建套接字;接收用户请求,并派发给某子进程处理;...
子进程:处理并响应请求;
CGI:common gateway interface;
虚拟主机:IP, PORT, HOSTNAME
反向代理
负载均衡:bytraffic, bybusiness, byrequest
路径别名
丰富的目录和文件级别的访问控制机制
基于IP和FQDN的访问控制
基于用户认证机制
basic:明文验证
digest:摘要信息比对认证
支持第三方模块
接下来,我们可以使用CentOS官方光盘中提供的安装包进行httpd程序的安装。先配置好yum源,然后执行下列命令即可:
$ yum -y install httpd
注意:在安装httpd之前,需要先安装apr以及apr-util,这两个包是httpd运行时环境。
接下来我们看一看安装了哪些httpd的相关软件包,以及这些软件包在我们的Linux中安装了哪些文件?
[root@Centos68A ~]# rpm -qa httpd* httpd-tools-2.2.15-53.el6.centos.x86_64 httpd-2.2.15-53.el6.centos.x86_64 httpd-devel-2.2.15-53.el6.centos.x86_64
[root@Centos68A ~]# rpm -ql httpd /etc/httpd /etc/httpd/conf /etc/httpd/conf.d /etc/httpd/conf.d/README /etc/httpd/conf.d/welcome.conf /etc/httpd/conf/httpd.conf:httpd默认的主配置文件 /etc/httpd/conf/magic /etc/httpd/logs /etc/httpd/modules /etc/httpd/run 以上这些是服务器根目录,conf和conf.d中保存了httpd所以的配置文件;logs、modules和run都是符号链接,其中logs链接到/var/log/httpd,用于存放默认主服务器的日志文件;modules链接到/usr/lib64/httpd/modules,用于存放所有httpd所能装载的DSO模块文件;run链接到/var/run/httpd,用来存放主进程的PidFile。 /etc/logrotate.d/httpd:日志滚动的脚本 /etc/rc.d/init.d/htcacheclean /etc/rc.d/init.d/httpd:httpd服务的SysInit风格的启动脚本 /etc/sysconfig/htcacheclean /etc/sysconfig/httpd:httpd启动脚本的配置文件,其中可以选择MPM模块。 /usr/lib64/httpd /usr/lib64/httpd/modules:真正存放httpd可以装载的DSO模块文件的目录 /usr/sbin/apachectl /usr/sbin/htcacheclean /usr/sbin/httpd /usr/sbin/httpd.event /usr/sbin/httpd.worker /usr/sbin/httxt2dbm /usr/sbin/rotatelogs /usr/sbin/suexec /var/cache/mod_proxy /var/lib/dav /var/log/httpd:真正存放主服务器日志文件的目录 /var/run/httpd:真正存放主服务器PidFile的目录 /var/www /var/www/cgi-bin:存放第三方可执行的CGI程序的目录 /var/www/error:存放错误页面的目录 /var/www/html:默认的主服务器的文档根目录 /var/www/icons:存放了所有默认图标文件的目录 (省略了具体的模块内容、帮助文档和图标文件等)
[root@Centos68A ~]# rpm -ql httpd-tools /usr/bin/ab:httpd的压力测试工具 /usr/bin/htdbm /usr/bin/htdigest /usr/bin/htpasswd:用于生成用户文件和添加用户信息到用户文件的工具 /usr/bin/logresolve (省略了帮助文档)
最后,我们来简单的了解一下httpd的主配置文件的格式和常用的配置指令。
httpd的主配置文件是/etc/httpd/conf/httpd.conf文件,其中有大量的注释信息,所以可以用来进行服务功能配置和定义的内容,通常称为指令(Directive)。原则上来讲,Directive和Value都是大小写不敏感的,但是如果Value是位于某个大小写敏感的文件系统中的文件的路径,则也就变得大小写敏感了。每个指令的格式是:Directive Value。其中,Directive部分习惯上写出驼峰的形式,即:每个单词的首字母大小,其余字母为小写。如:DocumentRoot、ServerRoot、DirectoryIndex等。
常用的配置指令:
1、修改监听的地址和端口;
Listen [IP:]PORT :该指令可以在配置文件中多次定义,注意,如果省略IP,表示0.0.0.0/0;
Listen 80
Listen 172.16.109.224:80
Listen 8080
2、长连接
tcp连接建立后,资源获取完成不会断开此TCP的连接,而是继续等待请求其它资源,但并不是真正的永不断开。在一个TCP连接发送来的请求数量达到某个限制或者空闲时间超出了时间限制,长连接也会被断开,进程也有可能被清理。
相关指令:
KeepAlive On|Off 如果该值为OFF,则后面的两个指令不再生效。
MaxKeepAliveRequests 100
KeepAliveTimeout 15
默认情况下,KeepAlive指令的值为OFF,利用telnet进行请求测试结果如下:
[root@Centos68A ~]# telnet SERVER_IP PORT GET /test1.html HTTP/1.1 Host: SERVER_IP HTTP/1.1 200 OK Date: Tue, 12 Jul 2016 15:04:36 GMT Server: Apache/2.2.15 (CentOS) Last-Modified: Tue, 12 Jul 2016 09:34:43 GMT ETag: "60102-10-53534af955806" Accept-Ranges: bytes Content-Length: 20 Connection: close Content-Type: text/html; charset=UTF-8 This is a test page Connection closed by foreign host.
如果将KeepAlive指令的值修改为On,则不会立即出现最后一句提示,我们依然可以继续进行资源请求。有兴趣的小伙伴请自行尝试。
3、MPM
多路处理模块;
httpd-2.2的MPM不支持DSO机制,均需以静态的方式装载至核心中,而且event为测试模块,在主配置文件中并没有为其提供配置指令。在安装了httpd包之后,系统中在/usr/sbin目录中提供了下述三个文件:
httpd:prefork模块
httpd.worker: worker模块
httpd.event: event模块,在2.2版本中为测试模块,不建议使用
如果想要修改MPM模式的模块,可以修改下述文件中的特定行
/etc/sysconfig/httpd
HTTPD=/usr/sbin/httpd|httpd.worker|httpd.event
修改之后,必须重启服务才能让配置生效。可以利用下列命令查看httpd程序的模块列表:
查看静态编译的模块:
httpd -l
查看编译的所有模块:
httpd -M
在主配置文件中为prefork模块提供的指令如下:
<IfModule prefork.c> StartServers 8 MinSpareServers 5 MaxSpareServers 20 ServerLimit 256 MaxClients 256 MaxRequestsPerChild 4000 </IfModule>
在主配置文件中为worker模块提供的指令如下:
<IfModule worker.c> StartServers 4 MaxClients 300 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 </IfModule>
4、DSO——LoadModule指令
LoadModule Mod_Name modules/Module_File.so
模块的路径为相对路径,是相对于ServerRoot指令所定义的路径而言,即:/etc/httpd目录中的modules目录
5、‘Main‘ Server
定义一个主机的基本指令:
ServerName FQDN:PORT
DocumentRoot /var/www/html
6、站点资源访问控制
基于目录和文件进行访问控制
<Directory "/PATH/TO/SOME_DIR">
</Directory>
<File "/PATH/TO/SOME_FILE">
</File>
<FileMatch "PATTERN">
</FileMatch>
基于url路径进行访问控制
<Location "/PATH/TO/SOME_URL">
</Location>
<LocationMatch "URL_PATTERN">
</LocationMatch>
以上这些指令,因为必须成对出现,将所有的其他指令包含在其内部方能生效,我们便将这些指令形象的称为"容器指令"。
在Directory容器指令中的常用指令:
1) Options:用于定义资源的展示方式;后跟以空白字符分隔的“选项”列表;
Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews None All
Indexes:允许索引;
FollowSymLinks:允许跟踪符号链接;
SymLinksifOwnerMatch
ExecCGI:允许执行CGI脚本;
InCludes:服务器端包含
None:全部都不选择
All:全部都有效
2)AllowOverride
httpd允许在网页文档的各目录下使用.htaccess文件实现单目录资源的访问控制;表示哪些指令可以存放于.htaccess文件中。该指令的默认值为None,一旦将设置为其他的非"None"值,则每次检索资源的时候,都要逐级向上查找.htaccess文件,因此会消耗大量的资源来做这样的无用功,从而大大降低服务器的响应效率。因此这个选项非常不建议进行修改。
3)order和allow/deny from
基于IP地址的访问控制;
order用于定义allow和deny的生效次序;
allow from IP/NETWORK/FQDN
deny from IP/NETWORK/FQDN
来源请求遵循最佳匹配法则机制
7、定义站点主页面:
DirectoryIndex file1 file2 ...
8、定义路径别名:
Alias /URL/ "/PATH/TO/SOME_DIR/"
alias指定的URL右侧的“/”相当于后面的路径右侧的“/”
9、日志设定
错误日志:
ErrorLog logs/error_log
LogLevel warn
访问日志:
LogFormat:定义日志信息格式;
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog:指明日志文件路径及日志格式;
格式:
%h 远程客户端主机地址
%l 远程客户端用户登录名
%u 远程客户端用户名
%t 收到请求的时间,标准英文格式时间
%r 请求报文的首行
%s 状态信息
%b 响应报文中除了首部之外的报文大小,以字节为单位
%{Foobar}i 在请求报文首部中属性名为Foobar的对应的值
10、httpd-manual
[root@Centos68A ~]# yum install httpd-manual
配置文件:/etc/httpd/conf.d/manual.conf
[root@Centos68A ~]# service httpd reload
访问路径:
http://SERVER_IP/manual/
11、基于用户的访问控制机制
http协议的认证功能:
虚拟账号:仅用于访问某服务的账号和密码;可将虚拟用户账户存储于文本文件、SQL数据库或ldap目录数据库中,但httpd要有相应的适配模块。
认证质询:WWW-Authenticate:响应码为401,拒绝客户端请求,并说明要求客户端提供账号和密码;
认证:Authorization:客户端填入账号和密码后再次发送请求报文;认证通过后,服务端发送响应资源
认证的方式有两种:
basic:明文
digest:消息摘要认证
安全域:需要用户认证后方能访问的资源集合;通常基于名称对其进行标识;
basic认证的配置示例:
1) 定义安全域
<Directory "/PATH/TO/SOME_DIR"> Options None AllowOverride None AuthType Basic AuthName "SOME_STRING_HERE" AutuUserFile "/PATH/TO/HT_PASSWD_FILE" AuthGroupFile "/PATH/TO/HT_GROUP_FILE" Require user user1 user2 ... Require group group1 group2 ... Require valid-user 此处三行Require指令在配置文件中,建议让一行是生效的,这样控制的更加精确,减少不确定因素。 </Directory>
2) 创建账号文件
htpasswd [options] /PATH/TO/HT_PASSWD_FILE USERNAME
-c:创建文件;
-m:md5加密密码;
-s: SHA加密密码;
-D:删除指定用户
3) 如果需要,还得在指定的组文件中定义组以及组中所包含的用户账户,每行定义一个组,用户账户之间使用空白字符隔开即可
GROUP_NAME: username1 username2 ...
12、虚拟主机
虚拟主机与“主服务器”不能够同时使用。默认情况下,虚拟主机的配置指令是注释掉的,所以主服务器可以正常使用;一旦打开了虚拟主机的配置指令,主服务器默认自动失效。
建立虚拟主机的目的是:可以将多个访问量不大或者资源消耗较小的站点部署在一台服务器上,进而可以节省成本,提供服务器资源的利用率。
在构成虚拟主机标识的三个元素中:IP地址、端口号、FQDN(主机头)至少有一个能唯一标识该虚拟主机即可。
于是,常见的虚拟主机就有了下列三种实现方式:
基于IP的虚拟主机:每个虚拟主机使用一独有的IP地址;
基于PORT的虚拟主机:每个虚拟主机使用一个独有的PORT;
基于FQDN的虚拟主机:每个虚拟主机使用一个独有的FQDN;
虚拟主机的配置方法:
<VirtualHost IP:PORT>
ServerName
DocumentRoot
</VirtualHost>
其它常用指令:
Errorlog
CusomLog
Alias
ServerAlias
ScriptsAlias
<Directory "/PATH/TO/SOME_DIR">
</Directory>
...
httpd2.2版的虚拟主机示例:
NameVirtualHost 172.16.100.71:80 <VirtualHost 172.16.100.71:80> ServerName www1.myweb.com DocumentRoot /myseb/vhosts/www1 </VirtualHost> <VirtualHost 172.16.100.71:8080> ServerName www1.myweb.com DocumentRoot /myweb/vhosts/www2 </VirtualHost> NameVirtualHost 172.16.100.72:80 <VirtualHost 172.16.100.72:80> ServerName www2.myweb.com DocumentRoot /myweb/vhosts/www2 </VirtualHost> <VirtualHost 172.16.100.72:80> ServerName www3.myweb.com DocumentRoot /myweb/vhosts/www2 </VirtualHost>
本文出自 “运维者的家” 博客,请务必保留此出处http://zhaotianyu.blog.51cto.com/132212/1825825
原文地址:http://zhaotianyu.blog.51cto.com/132212/1825825