0 目录
1 http
1.1 http是什么
http :(hyper text transfer protocol),超文本传输协议,一个基于TCP的应用层协议。
超文本指的是使用html(hyper text mark language,超文本标记语言)编程语言所开发的文本文件。
1.2 工作机制
1.2.1 服务器端与客户端
服务器端即web服务器。运行了http服务端程序(如httpd、nginx等),存放了web资源的主机,可响应给客户端请求的资源,这些资源存放在web服务器上的某文件系统的某路径。服务器端监听在80端口(tcp)。
客户端就是各种浏览器。
1.2.2 web资源与MIME
一次请求和响应的内容,叫做web资源。分为静态、动态资源。
静态资源,jpg、html、mp3等等。就是无需服务端处理,直接发送给客户端的资源(httpd仅能处理静态资源)。为加快响应速度,静态资源可被浏览器缓存一段时间;
动态资源,php、jsp等。是需要服务端运行,将运行结果传给客户端的资源。
一个网页页面上通常有多个资源,一个图片、一个文本、一个链接都是各自独立的资源。不要误以为整个网页是一个资源。
所以,在打开一个页面时,客户端要对每个资源单独请求。显示一个完整网页,客户端其实是请求了多次的。
早期的http协议,仅能够用于文本文件(传输过程使用ASCII码)的传输。1.0之后引入MIME1,从而客户端可请求图片、音频等类型文件(传输过程中仍是文本)。
1.2.3 URL
客户端如何指定要请求哪些资源?
通过URL指定。只需在浏览器地址栏中输入指定URL即可。
URL(Uniform Resource Locator,统一资源定位符),用于唯一标识页面。
格式:Scheme://Server_IP:[port]/[PATH][;PARAMS][?QUERY][#FLAG]
各字段 | 意义 |
---|---|
Scheme | 指定协议,可以是http、ftp等 |
Server_IP:port | 指定的服务器和端口号 |
PATH | 页面在服务器上的路径映射 |
;PARAMS | 向服务器传递参数PARAMS。有的请求需要得到服务器的运行结果,运行中需要传递给服务器的参数PARAMS通过此字段指定 |
?QUERY | 查询语句。如果需要服务器端通过数据库查询时,可在此输入查询语句QUERY |
#FLAG | 页面的锚点。当页面过长时(比如一个长文档),可在不同位置定义锚点,从而通过输入不同的FLAG跳转至页面不同位置方便浏览。当然一般是做成不同的链接供点击来跳转,而非让用户手动输入。 |
比如,http://www.sohu.com/
Scheme是http;
www.sohu.com是Server_IP:port,只是没有直接用IP而是域名,且http默认80端口,所以可省;
之后的PATH省略,表示访问的是默认主页面index.html。
再比如,https://baike.baidu.com/item/MIME/2900607?fr=aladdin等。
1.2.4 http事务的过程
http的工作机制很简单:客户端向服务器端发送请求资源报文;服务器端返回给客户端响应报文。而这也称为一次http事务。
从服务器端来看,具体过程:
1、对于来访的请求,建立或拒绝连接;
2、接收并处理请求。包括分析请求报文的首部(header)信息,从而得知客户端的请求方法(method)。由于http基于tcp,所以每个资源的请求都要3次握手、4次断开;
3、服务器根据请求报文指定的URL,访问存储设备上对应的资源;
4、服务器得到指定资源,构建响应报文(即加上各首部信息),发送给客户端;
5、服务器将此次访问相关的信息记录日志。
1.3 http报文格式
http的请求、响应报文包括http协议首部(其实行+各headers)和数据实体。
不过请求报文和响应报文的起始行格式、常使用的headers有所不同。
1.3.1 请求报文格式
请求报文格式:
<method> <URL> <version> # 起始行
header1: value # 各首部信息
header2: value
……
headerN: value
<request body> # 与上述信息隔两行,是数据实体
method:请求方法。即客户端请求服务端对资源完成的动作。
URL:指定资源的URL
version:指明http协议版本
headers:各首部信息。用于描述报文的各种属性。
request body:请求报文的数据实体
起始行信息与各headers,就是http协议首部。隔两行之后是数据实体。
1.3.1.1 常见请求方法
方法 | 意义 |
---|---|
GET | 请求从服务器端获取一个资源。所以GET方法对应的数据实体常为空,无需向服务器传输什么数据 |
HEAD | 请求从服务器获取响应报文的http首部。HEAD和GET方法不同就在于,不请求获取数据实体 |
POST | 请求向服务器发送要被服务器处理的数据。比如一些表单、帐号密码的填写。该方法对应的数据实体,就是要发给服务器的数据 |
PUT | 请求向服务器发送要存储在服务器上的数据(相比于POST,这些数据是无需处理的)。比如上传一个文件到服务器。显然该方法对应的数据实体就是要上传的数据 |
DELETE | 请求删除服务器上的指定数据 |
OPTIONS | 请求获取服务器对指定资源,开放支持了哪些请求方法。比如DELETE方法比较危险,未必所有服务器对所有资源都开放。通过此方法可知对指定服务器上的各资源能使用哪些请求方法 |
TRACE | 追踪请求报文从客户端到服务器端,经过了哪些代理服务器2。 |
1.3.2 响应报文格式
响应报文与请求报文的格式,主要是起始行的不同:
<version> <status-code> <reason phrase> # 起始行
header1: value # 各首部信息
header2: value
……
headerN: value
<entity body> # 与上述信息隔两行,是数据实体
version,仍是http协议版本;
status-code,状态码,用于描述不同的响应状态(成功、失败等)
reaon phrase,原因短语,就是对状态码的解释
headers,响应报文用到的各首部
entity body,数据实体。比如客户端要GET某资源,则这时的数据实体就是该资源
1.3.2.1 常见状态码
状态码就是3位数字,其中按1、2、3、4、5开头的对应不同的状态类型:
开头数字 | 范围 | 意义 |
---|---|---|
1 | 100、101 | 基本无意义 |
2 | 200至206 | 客户端请求成功 |
3 | 300至305 | 请求的资源被重定向等 |
4 | 400至415 | 因客户端原因导致请求失败 |
5 | 500至505 | 因服务端原因导致请求失败 |
常见状态码:
状态码 | 对应的原因短语 | 意义 |
---|---|---|
200 | OK | 请求的资源内容已构建响应报文发给客户端 |
301 | moved permanently | 请求的URL指向的资源已被永久移动,放在了其他位置。响应报文会通过首部”Location”告知客户端资源的新URL |
302 | found | 类似301,只是资源是被临时移动到了其他位置,过短时间或许还会恢复原样。服务端同样通过首部”Location”,告知客户端资源目前的临时URL |
304 | Not Modified | 当客户端发出条件式请求请求指定资源时,服务端的对应资源正好也没有改变,则返回此状态,告知客户端继续使用缓存内容3 |
401 | Unauthorized | 需要输入帐号密码才能访问指定资源,比如http自带的basic认证等 |
403 | Forbidden | 请求被禁止。比如服务端对访问控制做了相关配置,拒绝某些IP的访问等 |
404 | Not Found | 客户端请求的URL对应的资源不存在 |
500 | Internal Server Error | 服务器内部错误 |
502 | Bad Gateway | 用户请求报文到达了代理服务器,而代理服务器从它的后端服务器(显然,这可能是真正的web服务器也可能还是个代理服务器)收到了错误响应,导致它无法正确响应用户请求 |
1.3.3 常见header
如上所述,请求报文、响应报文的起始行之后,都有任意个首部(header)信息,以描述当前报文的属性等信息。
格式为:header_name: value
如有多个header,则每行一个。
比如,打开浏览器的调试界面(F12),地址栏输入www.sohu.com。随便找一个资源对应的首部信息,可看到该资源对应的请求、响应报文各首部,大致如下:
各常见首部:
1.3.3.1 通用首部
通用首部就是在请求、响应报文都可能用到的首部。
名称 | 意义 |
---|---|
Date | 报文创建的时间 |
Connection | 连接状态。比如keepalive(长连接)、close(连接关闭)等 |
Via | 显示报文经过的中间结点(如代理服务器等) |
Cache-control | 缓存控制 |
1.3.3.2 请求首部
仅用于请求报文中的常见首部:
名称 | 意义 |
---|---|
Accept | 告知服务端,客户端能够识别的媒体类型(即MIME类型) |
Accept-Charset | 告知服务端,客户端所能接收的字符集 |
Accept-Encoding | 告知服务端,客户端所能接收的编码格式(比如gzip等压缩格式) |
Accept-Language | 告知服务端,客户端所能接收的语言 |
Client-IP | 指明客户端IP |
Host | 请求的服务器IP和端口号(包括FQDN) |
Referer | 当前所请求资源的上一级资源。即当前请求的资源是由哪个页面跳转而来,如果是直接从浏览器地址栏键入而非从其他页面跳转来的,则为空 |
User-agent | 客户端代理类型。就是浏览器类型 |
If-Modified-Since | 自从指定的时间后,请求的资源是否发生过修改(条件式请求,以此决定是否使用缓存内容) |
Authorization | 客户端向服务端发送认证信息 |
Cookie | 客户端发送Cookie以使服务器识别客户端来源(http是无状态的,服务端无法识别客户端来源,看待任何请求都是一样的,所以使用Cookie来标记客户端) |
1.3.3.3 响应首部
仅用于响应报文中的常见首部:
名称 | 意义 |
---|---|
Age | 响应持续时长 |
Server | 服务器端运行的程序名称和版本(如apache、nginx等),这个信息一般是不发的 |
Accept-Ranges | 服务端可接收的请求范围 |
Set-Cookie | 为服务端设置并发送一cookie |
WWW-Authenticate | 来自服务端对客户端的质询认证表单(如帐号密码) |
Allow | 列出对当前数据实体可使用的请求方法。响应客户端Options方法时,要用此首部 |
Location | 用于资源重定向时,告知客户端资源的新位置在哪 |
Cotent-Encoding | 数据实体内容的编码格式 |
Cotent-Language | 数据实体内容的语言 |
Cotent-Length | 数据实体内容的长度 |
Cotent-Type | 数据实体的类型(即MIME类型) |
Expires | 响应资源的缓存过期时间 |
Last-Modified | 响应资源的最后依次修改时间 |
1.4 cookie和session简要说明
http协议是无状态的,就是服务器端无法识别访问者来源。即便是同一用户访问同一资源,在服务端看来也是两次不同的、独立的请求。
这在需要输入帐号密码、或是电商站点的情形是有问题的:只要一刷新页面就要重新输入验证信息,并且重新选购物品等。
使用cookie就是为了追踪访问者,以保持访问页面的状态。它会记录用户信息和操作记录。在客户端第一次向服务端发请求时,服务端发cookie给客户端。cookie存储在客户端本地,只要再访问服务端,就发送cookie以标明身份。
这样,在安全上又有较大风险,cookie可能泄露隐私信息。
于是引入session,session可看作服务端为用户建立的一种数据结构,用于存储用户操作记录。把cookie的部分信息用session来存储,cookie与session对应起来。
这样,根据指定cookie可在服务器上找到对应用户session,session中记录了用户的操作、行为记录等。
2 httpd2.2
应用层协议的实现,都是通过具体的软件。
httpd就是http协议中,服务器端的安装程序。以下说明httpd2.2的常用配置。笔者使用的是CentOS 6(6的光盘上的rpm包就是httpd2.2,如需在6上安装2.4,需编译安装),IP为192.168.0.105。
安装后只需在浏览器键入地址,即可看到测试页:
httpd2.2的配置文件为:主配置文件/etc/httpd/conf/httpd.conf和其他配置文件/etc/httpd/conf.d/*.conf。
上面的测试页面就是/etc/httpd/conf/httpd.conf/welcome.conf定义配置的。
主配置文件分3段:
### Section 1: Global Environment # 全局环境配置
……
### Section 2: 'Main' server configuration # 中心主机配置
……
### Section 3: Virtual Hosts # 虚拟主机配置
……
配置格式为:”Command Value”各Command不严格区分大小写,但一般是把每个单词首字母大写。
修改其中的参数后可使用“httpd -t”检查配置文件语法。
下面列出主配置文件中的常用配置:
2.1 主配置文件Section 1
此段中的配置对全局有效。
2.1.1 ServerRoot
ServerRoot,用于定义服务端httpd程序的配置、日志等文件所在的目录(可看作是httpd的工作目录)。
注意,不要在最后加“/”:
……
# Do NOT add a slash at the end of the directory path.
#
ServerRoot "/etc/httpd"
2.1.2 Listen
Listen,用于定义服务端监听的IP和端口。IP可省略,表示监听在所有IP;端口不可省。
可多次使用,表示同时监听在多个IP和端口。
修改监听的IP或端口,只有重启服务才能生效。
比如,修改为监听在80和8000端口:
Listen 80
Listen 8000
重启服务后,查看监听端口验证:
[root@localhost ~]% netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1592/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1671/master
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 1757/sshd
tcp 0 0 127.0.0.1:6011 0.0.0.0:* LISTEN 2243/sshd
tcp 0 0 :::8000 :::* LISTEN 2347/httpd
tcp 0 0 :::80 :::* LISTEN 2347/httpd
……
2.1.3 LoadModule
httpd是高度模块化的,支持动态装载、卸载各功能模块(就像内核一样)。
httpd的各模块文件放在/usr/lib64/httpd/modules。
LoadModule,用于指定装载的模块。
格式:LoadModule Module_Name Module_Path
其中模块所在的文件路径可以是相对路径,相对于ServerRoot定义的路径。
可看到httpd默认已经装载了诸多模块:
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_alias_module modules/mod_authn_alias.so
……
httpd命令的”-M”选项,可列出当前装载的所有模块。
2.1.4 Include
包含指定文件到配置文件。
主配置文件中使用了此指令,/etc/httpd/conf.d/*.conf才会作为配置文件生效,因为默认定义的就是此路径:
# Load config files from the config directory "/etc/httpd/conf.d".
#
Include conf.d/*.conf
2.1.5 持久连接相关
2.1.5.1 持久连接是什么
http基于tcp(连接需3次握手、4次断开)。
默认情况下是非持久连接:客户端每请求一个资源都要与服务端3次握手、获取到资源、4次断开。
当用户数较多时,应采取默认方式,以保证所有用户都能轮流得到响应;
当用户数较少时(比如只有1个用户,请求多个资源),频繁地3次握手、4次断开增加了不必要的开销。
对于后者应采取持久连接(也叫长连接):客户端与服务端一直保持连接状态,直到获取到一定数量的资源或连接达到一定时长才断开(注意,是满足二者中任一条件就断开)。
显然,长连接的情况下,当达到断开条件时,由服务端向客户端发出断开要求,因为只有服务端知道是否达到了资源数或指定时长;
默认情况断开请求是由客户端发出的。
2.1.5.2 KeepAlive
KeepAlive,用于指定是否启用长连接。
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive Off # 默认是关闭的,如需开启改为on
2.1.5.3 KeepAliveTimeOut
KeepAliveTimeOut,用于指定长连接的时长。
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 15 # 默认15秒
2.1.5.4 MaxKeepAliveRequests
MaxKeepAliveRequests,用于指定客户端在长连接中最多请求的资源数。
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
#
MaxKeepAliveRequests 100 # 默认100个
2.1.6 MPM
MPM(Multipath Processing Module,多路处理模块),是指httpd在同时响应多个请求时的工作模型。
分为3种:prefork、worker、event。只能启用其中一种。并且在需要切换模型时,最好是在关闭服务的情况下修改配置文件,修改完成后再开启。
虽然叫做模块,但httpd2.2不支持MPM的动态装载、卸载,2.4开始支持。
所以只要编译时采用了哪种模型,则使用的就是哪种模型。CentOS 6为了方便,3中模型都编译了,对应的应用程序分别为/usr/sbin/httpd、/usr/sbin/httpd.worker、/usr/sbin/httpd.event。
不过2.2上,event模型处于测试阶段;2.4可正常使用。
服务脚本启用httpd时,用的是哪种模型,在服务脚本配置文件/etc/sysconfig/httpd中进行了定义:
# The default processing model (MPM) is the process-based
# 'prefork' model. A thread-based model, 'worker', is also
# available, but does not work with some modules (such as PHP).
# The service must be stopped before changing this variable.
#
#HTTPD=/usr/sbin/httpd.worker 如需启用则把该行注释掉
2.1.6.1 prefork
默认情况下,服务脚本启动的是prefork模型对应的应用程序/usr/sbin/httpd:
[root@localhost ~]# ps aux | grep httpd
root 2000 0.0 0.3 175332 3688 ? Ss 16:07 0:00 /usr/sbin/httpd
apache 2002 0.0 0.2 175332 2464 ? S 16:07 0:00 /usr/sbin/httpd
apache 2003 0.0 0.2<