1. 基于ABNF语义定义的HTTP消息格式
- HTTP协议格式
start-line: 分为request-line, status-line
header-field header-field
message-body
- ABNF (扩充巴科斯-瑙尔范式)操作符
- 空白字符: 用来分隔定义中的各个元素
- method SP request-target SP HTTP-version CRLF
- 选择/: 表示多个规则都是可供选择的规则
- start-line = request-line / status-line
- 值范围%c##-## :
OCTAL = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7"
与OCTAL = %x30-37
等价
- 序列组合(): 将规则组合起来,视为单个元素
- 不定量重复
m*n
:*
元素表示零个或多个元素:*( header-field CRLF )
1*
元素表示一个或更多元素2*4
元素表示两个至四个元素
- 以逗号相隔的多个元素
#
:#method
可以表达put,get,post
- 可选序列[]:
- [ message-body ]
- ABNF (扩充巴科斯-瑙尔范式)核心规则
规则 | 形式定义 | 意义 |
---|---|---|
VCHAR | %x21-7E |
可见(打印)字符 |
CTL | %x00-1F / %x7F | 控制字符 |
CHAR | %x01-7F | 任何7-位US-ASCII字符,不包括NUL (%x00) |
OCTET | %x00-FF | 8位二进制,一个字节,表示二进制字节 |
ALPHA | %x41-5A / %x61-7A | 大写和小写ASCII字母(A-Z,a-z) |
DIGIT | %x30-39 | 数字(0-9) |
HEXDIG | DIGIT / “A” / “B” / “C” / “D” / “E” / “F” | 十六进制数字(0-9, A-F, a-f) |
DQUOTE | %x22 | 双引号 |
SP | %x20 | 空格 |
HTAB | %x09 | 横向制表符 |
WSP | SP / HTAB | 空格或横向制表符 |
LWSP | *(WSP / CRLF WSP) |
直线空白(晚于换行) |
CR | %x0D | 回车 |
LF | %x0A | 换行 |
CRLF | CR LF | 互联网标准换行 |
BIT | “0” / “1” | 二进制数字 |
- 基于ABNF描述的HTTP协议格式
|
|
2. URI
2.1 使用ABNF来表述URI
URL: RFC1738 (1994.12), Uniform Resource Locator, 表示资源的位置,期望提供查找资源的方法。
URN: RFC2141 (1997.5), Uniform Resource Name, 期望为资源提供持久的、位置无关的标识方式,并允许简单地将多个命名空间映射到单个URN命名空间
- 例如磁力链接magnet:?xt=urn:sha1:YNCKHTQC5C
URI: RFC1630 (1994.6)、RFC3986 (2005.1,取代RFC2396和RFC2732),Uniform Resource Identifier,用以区分资源,是URL和URN的超集,用以取代URL和URN的概念。
URI格式:
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
* sheme = ALPHA * ( ALPHA / DIGIT / "+" / "-" / "." )
* 例如: http, https, ftp, mailto, rtsp, file, telnet
* query = *( pchar / "/" / "?" )
* fragment = *( pchar / "/" / "?" )
hier-part = [ "//" ] authority path
* authority = [ userinfo "@" ] host [ ":" port ]
* userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
* host = IP-literal / IPv4address / reg-name
* port = *DIGIT
* path = path-abempty/ path-absolute/ path-noscheme / path-rootless/ path-empty
* path-abempty = *("/" segment)
* 以/开头的路径或者空路径
* path-absolute = "/" [ segment-nz *( "/" segment ) ]
* 以/开头的路径,但不能以//开头
* path-noscheme = segment-nz-nc *( "/" segment )
* 以非:号开头的路径
* path-rootless = segment-nz *( "/" segment )
* 相对path-noscheme,增加允许以:号开头的路径
* path-empty = 0<pchar>
* 空路径
相对URI:
2.2 对URI进行编码
- 为什么要进行URI编码
- 传递数据中,如果存在用作分隔符的保留字怎么办?
- 对可能产生歧义性的数据编码
- 不在ASCII码范围内的字符
- ASCII码中不可显示的字符
- URI中规定的保留字符
1 2 3 4 5 6 7 8 9
reserved = gen-delims / sub-delims * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" * ALPHA: %41-%5A and %61-%7A * DIGIT: %30-%39 * -:%2D .:%2E _:%5F * ~:%7E, 某些实现将其作为保留字符
- 不安全字符 (传输环节中可能会被不正确处理),如空格、引号、尖括号等
示例: https://www.baidu.com/s?wd=?#! https://www.baidu.com/s?wd=极客 时间 https://www.baidu.com/s?wd=极客’?时间
- URI百分号编码
- 百分号编码的方式
- pct-encoded = “%” HEXDIG HEXDIG
- US-ASCII: 128个字符 (95个可显示字符,33个不可显示字符) 参见: https://zh.wikipedia.org/wiki/ASCII
- pct-encoded = “%” HEXDIG HEXDIG
- 非ASCII码字符(例如中文):建议先UTF8编码,再US-ASCII编码
- 对URI合法字符,编码与不编码是等价的
- 例如,“URI转换"既可以"URI%e8%bd%ac%e6%8d%a2”,也可以 “%55%52%49%e8%bd%ac%e6%8d%a2”
3. start line
3.1 请求行
|
|
- 常见方法 (RFC7231)
- GET: 主要的获取信息方法,大量的性能优化都针对该方法,幂等方法
- HEAD:类似GET方法,但服务器不发送BODY,用以获取HEAD元数据,幂等方法
- POST: 常用于提交HTML FROM表单、新增资源等
- PUT:更新资源,带条件时是幂等方法
- DELETE:删除资源,幂等方法
- CONNECT:建立tunnel隧道
- OPTIONS:显示服务器对访问资源支持的方法,幂等方法,该方法的响应头中的Allow字段定义访问该资源允许使用的方法。
- TRACE: 回显服务器收到的请求,用于定位问题。有安全风险,所以在2007年nginx的0.5.17版本之后不再支持该方法了,直接返回405状态码。
幂等方法:调用一次和调用多次是一样的。幂等方法对于设计分布式系统的事务是有意义的。
- 用于文档管理的WEBDAV方法(RFC2518)
- PROPFIND: 从服务器中检索以XML格式存储的属性,例如目录,目录的树状结构可以以XML格式进行存储
- PROPPATCH: 在单个原子性动作中更改和删除资源的多个属性,比如同时修改文件的修改时间和文件名。
- MKCOL: 创建集合或者目录
- COPY: 将资源从一个URI复制到另一个URI
- MOVE:将资源从一个URI移动到另一个URI
- LOCK:锁定一个资源。WebDAV支持共享锁和互斥锁
- UNLOCK:解除资源的锁定
3.1.1 Connect方法
- HTTP Tunnel隧道
- 用于通过HTTP连接传输非HTTP协议格式的消息,常用于穿越防火墙
- (d)之后,隧道就建立成功了
- 建立隧道后,由于传输的并非HTTP消息,因此不再遵循请求/响应模式,已变为双向传输
|
|
- HTTP Tunnel隧道的认证
|
|
3.2 响应行
响应码规范:RFC6585 (2012.4)、RFC7231 (2014.6) 这些规范可以指导服务器设计,但是并不是所有服务器都遵循响应码中的规范。
- 1xx: 请求已接收到,需要进一步处理才能完成,HTTP1.0不支持
- 100 Continue:上传大文件前使用 客户端发起请求时携带Expect:100-continue头部, 然后服务器返回100状态码,表示已准备好大文件的接收。
- 101 Switch Protocols: 协议升级使用 由客户端发起请求中携带Upgrade:头部触发,如升级websocket或者http/2.0, 如果服务器支持的话,就会返回101状态码。
- 102 Processing: WebDav请求可能包含许多涉及文件操作的子请求,需要很长时间才能完成请求。 如果服务器等到这些子请求全部完成后才向客户端发送响应,就有可能导致客户端超时。 所以,服务器可以先发送102的状态码给客户端,表示这个请求已经收到了, 但是服务器可能需要很长时间才能处理完,当前并没有响应返回给你。
- 2xx: 成功处理请求
- 200 OK: 成功返回响应
- 201 Created: 有新资源在服务器端被成功创建
- 202 Accepted: 服务器接收并开始处理请求,但请求未处理完成。 这样一个模糊的概念是有意如此设计,可以覆盖更多的场景。 例如异步、需要长时间处理的任务。
- 203 Non-Authoritative Information: 当代理服务器修改了origin server的原始响应包体时(例如更换了HTML中的元素值), 代理服务器可以通过修改200为203的方式告知客户端这一事实,方便客户端为这一行为作出相应的处理。203响应可以被缓存。 203状态码并没有被广泛接收。
- 204 No Content: 成功执行了请求且不携带响应包体,并暗示客户端无需更新当前的页面视图。
- 205 Reset Content:成功执行了请求且不携带响应包体,同时指明客户端需要更新当前页面视图。
- 206 Partial Content:使用range协议时返回部分响应内容时的响应码。
- 207 Multi-Status: RFC4918,在WEBDAV协议中以XML返回多个资源的状态。
- 208 Already Reported:RFC5842,为避免相同集合下资源在207响应码下重复上报,使用208可以使用父集合的响应码。
- 3xx: 重定向使用Location指向的资源或者缓存中的资源。在RFC2068中规定客户端重定向次数不应超过5次,以防止死循环。
- 300 Multipart Choices: 资源有多种表述,通过300返回给客户端后由其自行选择访问哪一种表述。由于缺乏明确的细节,300很少使用。
- 301 Moved Permanently: 资源永久性的重定向到另一个URI中。
- 302 Found:资源临时的重定向到另一个URI中。
- 303 See Other: 重定向到其他资源,常用于POST/PUT等方法的响应中,和302一致。
- 304 Not Modified: 当客户端拥有可能过期的缓存时,会携带缓存的标识etag、时间等信息询问服务器缓存是否仍可复用,而304是告诉客户端可以复用缓存。
- 307 Temporary Redirect:类似302,但明确重定向后请求方法必须与原请求方法相同,不得改变。
- 308 Permanent Redirect:类似301,但明确重定向后请求方法必须与原请求方法相同,不得改变。
- 4xx: 客户端出现错误
- 400 Bad Request: 服务器认为客户端出现了错误,但不能明确判断为以下哪种错误时使用此错误码。例如HTTP请求格式错误。
- 401 Unauthorized: 用户认证信息缺失或者不正确,导致服务器无法处理请求。
- 407 Proxy Authentication Required: 对需要经由代理的请求,认证信息未通过代理服务器的验证
- 403 Forbidden:服务器理解请求的含义,但没有权限执行此请求
- 404 Not Found: 服务器没有找到对应的资源
- 410 Gone: 服务器没有找到对应的资源,且明确的知道该位置永久性找不到该资源。
- 405 Method Not Allowd: 服务器不支持请求行中的method方法
- 406 Not Acceptable: 对客户端指定的资源表述不存在(例如对语言或者编码有要求),服务器返回表述列表供客户端选择。
- 408 Request Timeout: 服务器接收请求超时
- 409 Conflict: 资源冲突,例如上传文件时目标位置已经存在版本更新的资源
- 411 Length Required: 如果请求含有包体且未携带Content-Length头部,且不属于chunk类请求时,返回411。
- 412 Procondition Failed: 复用缓存时传递的If-Unmodified-Since或If-None-Match头部不被满足
- 413 Payload Too Large / Request Entity Too Large: 请求的包体超出服务器能处理的最大长度。
- 414 URI Too Long: 请求的URI超出服务器能接受的最大长度
- 415 Unsupported Media Type: 上传的文件类型不被服务器支持
- 416 Range Not Satisfiable: 无法提供Range请求中指定的那段包体
- 417 Expectation Failed: 对于Expect请求头部期待的情况无法满足时的响应码
- 421 Misdirected Request: 服务器认为这个请求不该发给它,因为它没有能力处理。
- 426 Upgrade Required: 服务器拒绝基于当前HTTP协议提供服务,通过Upgrade头部告知客户端必须升级协议才能继续处理。
- 428 Precondition Required: 用户请求中缺失了条件类头部,例如If-Match
- 429 Too Many Requests: 客户端发送请求的速率太快(一般使用503)
- 431 Request Header Fields Too Large: 请求的HEADER头部大小超过限制(一般只做414错误码限制,431错误码太细了)
- 451 Unavailable For Legal Reasons: RFC7725, 由于法律原因资源不可访问。
- 5xx: 服务器端出现错误
- 500 Internal Server Error: 服务器内部错误,且不属于以下错误类型
- 501 Not Implemented: 服务器不支持实现请求所需要的功能
- 502 Bad Gateway: 代理服务器无法获取到合法响应
- 503 Service Unavailable: 服务器资源尚未准备好处理当前请求,熔断降级限流时经常使用503
- 504 Gateway Timeout: 代理服务器无法及时的从上游获得响应
- 505 HTTP Version Not Supported:请求使用的HTTP协议版本不支持
- 507 Insufficient Storage: 服务器没有足够的空间处理请求(把服务器内部的问题暴露给了客户端,有安全性问题,通常不会使用)
- 508 Loop Detected: 访问资源时检测到循环
- 511 Network Authentication Required: 代理服务器发现客户端需要进行身份验证才能获得网络访问权限,网吧场景中经常使用。
注意: 当客户端接收到了一个它不认识的响应码,不知道如何处理的时候,将使用这些响应码所在系列的第一个,也就是00系列的错误码进行处理。比如收到了555状态码,而客户端不认这个状态码,就会使用500来处理。
3.2.1 重定向
- 重定向的流程
- 当浏览器接收到重定向响应码时,需要读取响应头部Location头部的值,获取到新的URI再跳转访问该页面
Client Server
| |
Initial request|------------------------------------------->|
|GET /doc HTTP/1.1 |
| |
|<-------------------------------------------|Resource moved.
| HTTP/1.1 301 Moved Permanently |New location returns
| Location: /doc_new |
| |
| |
Request to the |------------------------------------------->|
new location |GET /doc_new HTTP/1.1 |
| |
| |
|<-------------------------------------------|Resource returned
| HTTP/1.1 200 OK |
- Location头部
- 重定向循环
- 服务器端在生成Location重定向URI时,在同一条路径上使用之前的URI,导致无限循环出现
- Chrome浏览器会提示:
ERR_TOO_MANY_REDIRECTS
Client Server
| |
Initial request|------------------------------------------->|
|GET /doc HTTP/1.1 |
| |
|<-------------------------------------------|Resource moved.
| HTTP/1.1 301 Moved Permanently |New location returns
| Location: /doc_new |
| |
| |
Request to the |------------------------------------------->|
new location |GET /doc_new HTTP/1.1 |
| |
| |
|<-------------------------------------------|Resource Moved.
| HTTP/1.1 301 Moved Permanently |New location returns
| Location: /doc |
4. 请求头和响应头
4.1 Host头部
- Host = uri-host[":" port]
- HTTP/1.1规范要求,不传递Host头部则返回400错误响应码 因为上世纪90年代域名相对是比较少的,每一个服务器的IP地址仅对应一个域名,所以当用户 已经对你的服务器建立连接以后,是不需要考虑哪个域名对应的服务的。 但是,后来域名越来越多,而IP地址相对比较少,所以引入了Host头部。
- uri-host:表示URI中的host部分
4.2 消息转发
- Max-Forwards头部
- 限制Proxy代理服务器的最大转发次数,仅对TRACE/OPTIONS方法有效
Max-Forwards = 1*DIGIT
- Via头部: 指明经过的代理服务器名称及版本,例如Via: 1.0 th-openresty, 1.0 th-nginx
- Cache-Control:no-transform
- 禁止代理服务器修改响应包体。
4.3 请求与响应的上下文
4.3.1 请求上下文
- User-Agent: 指明客户端的类型信息,服务器可以据此对资源的表述做抉择
例如: User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:66.0) Gecko/20100101 Fireforx/66.0
- Referer 浏览器对来自某一页面的请求自动添加的头部
- Referer = absolute-URI / partial-URI
- 例如
- Referer:
https://developer.mozilla.org/zh_CN/docs/Web/HTTP/Headers/User-Agent
- Referer:
- Referer不会被添加的场景
- 来源页面采用的协议为表示本地文件的"file"或者"data"
- 当前请求页面采用的是http协议,而来源页面采用的是https协议
- 服务器常用Referer来做统计分析、缓存优化、防盗链等功能。
- From
- 主要用户网络爬虫,告诉服务器如何通过邮件联系到爬虫的负责人
- From = mailbox
- 例如: From: webmaster@example.org
4.3.2 响应上下文
- Server
- 指明服务器上所用软件的信息,用于帮助客户端定位问题或者统计数据
- Server =
product*(RWS product/comment)
- product = token ["/" product-version]
- 例如: Server: nginx
- Allow: 告诉客户端,服务器上该URI对应的资源允许哪些方法的执行
- Allow =
#method
- 例如:
- Allow: GET,HEAD,PUT
4.4 内容协商与资源表述
-
内容协商的前提 该URI指向的资源有多种不同的表述,例如一份文档可以有不同语言的翻译、不同的媒体格式、可以针对不同的浏览器提供不同的压缩编码等。
-
内容协商的两种方式
- Proactive 主动式内容协商: 指由客户端先在请求头部中提出需要的表述形式,而服务器根据这些请求头部提供特定的表述
Resource on the server
(with different available representation)
|--------------
| 法语| 德语 |-----< URLa
| text/html |-----< URLb
| text/pdf |-----< URLc
Client------1.Requests the resource----->URL-------| gzip压缩算法|-----< URLd
^ GET /URL HTTP/1.1 | br压缩算法 |-----< URLe
| Accept: text/* ---------------
| Accept-Language: en |
| Accept-Encoding: br,gzip; q=0.8 |
--------------------------------------------------------
2.Returns the most appropriate representation of the resource.
HTTP/1.1 200 OK
Content-Location: /URLe
Content-Type: text/html
Content-Language: en
Content-Encoding: br
- Reactive 响应式内容协商: 指服务器返回300 Multiple Choices或者406 Not Acceptable,由客户端 选择一种表述URI使用。 但是响应式内容协商它有个问题,因为RFC规范没有明确的告诉Client应该依据怎样的规则, 所以导致各大浏览器无法按照一个统一的策略,去选择合适的响应表述给用户,所以, 响应式内容协商相对是很少使用的。
Resource on the server
(with different available representation)
|--------------
| 法语| 德语 |-----< URLa
| text/html |-----< URLb
| text/pdf |-----< URLc
Client------1.Requests the resource----->URL-------| gzip压缩算法|-----< URLd
^|^ GET /URL HTTP/1.1 | br压缩算法 |-----< URLe
||| Accept: text/* ----------|---- ^
||| Accept-Language: en | | |
||| Accept-Encoding: br,gzip; q=0.8 | | |
||-------------------------<------------------------------ | |
|| 2.Returns the list of appropriate representations. | |
|| HTTP/1.1 300 Multiple Choices | |
||------------------------->--------------------------------|-------------
| 3. Requests the specific representation. |
| GET /URLe HTTP/1.1 |
| Accept: text/* |
| Accept-Language: en |
| Accept-Encoding: br,gzip; q=0.8 |
|--------------------------<--------------------------------|
4.Returns the requested representation.
HTTP/1.1 200 OK
Content-Location: /URLe
Content-Type: text/html
Content-Language: en
Content-Encoding: br
- 常见的协商要素
# 质量因子q: 内容的质量、优先级
# 媒体资源的MIME类型及质量因子
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,
image/apng,*/*;q=0.8,application/signed-exchange;v=b3
# 字符编码:由于UTF-8格式广为使用,Accept-Charset已被废弃
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
# 内容编码:主要指压缩算法
Accept-Encoding: gzip,deflate,br
# 表述语言
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
- 国际化与本地化
# internationalization (i18n,i和n之间有18个字符)
指设计软件时,在不同的国家、地区可以不做逻辑实现层面的修改便能够以不同语言显示
# localization (l10n, l和n之间有10个字符)
指内容协商时,根据请求中语言及区域信息,选择特定的语言作为资源表述
- 资源表述的元数据头部
# 媒体类型、编码
content-type:text/html; charset=utf-8
# 内容编码
content-encoding:gzip
# 语言
Content-Language:de-DE,en-CA
5. 包体
5.1 两种传输HTTP包体的方式
- 发送HTTP消息时已能够确定包体的全部长度
使用Content-Length头部明确指明包体长度(HTTP1.1协议中就明确指定必须指定Content-Length头部),
Content-Length = 1*DIGIT
。
使用Python来模拟:
|
|
- 发送HTTP消息时不能确定包体的全部长度 使用Transfer-Encoding头部指明使用Chunk传输方式,含Transfer-Encoding头部后Content-Length头部应被忽略。
优点: ① 基于长连接持续推送动态内容 ② 压缩体积较大的包体时,不必完全压缩完(计算出头部)再发送,可以边发送边压缩 ③ 传递必须在包体传输完才能计算出的Trailer头部
|
|
Trailer头部的传输:
- TE头部:客户端在请求中声明是否接收Trailer头部 TE: trailers
- Trailer头部:服务器告知接下来chunk包体后会传输哪些Trailer头部 Trailer: Date
- 以下头部不允许出现在Trailer的值中: 用于信息分帧的首部(例如Transfer-Encoding和Content-Length) 用于路由用途的首部(例如Host) 请求修饰首部(例如控制类和条件类的,如Cache-Control,Max-Forwards,或者TE) 身份验证首部(例如Authorization或者Set-Cookie) Content-Encoding, Content-Type, Content-Range, 以及Trailer自身
5.2 用于上传/下载附件的Content-Disposition头部
|
|
测试:
|
|
5.3 MIME
大小写不敏感,但通常是小写,例如: Content-type: text/plain; charset=“us-ascii”
|
|
5.4 form表单
-
FORM表单常见控件有: ① Text Input Controls: 文本输入控件 ② Checkboxes Controls: 复选框控件 ③ Radio Box Controls: 单选按钮控件 ④ Select Box Controls: 下拉列表控件 ⑤ File Select boxes: 选取文件控件 ⑥ Clickable Buttons: 可点击的按钮控件 ⑦ Submit and Reset Button: 提交或者重置按钮控件
-
FORM表单提交请求时的关键属性
- action: 提交时发起HTTP请求的URI
- method: 提交时发起HTTP请求的http方法 GET: 通过URI,将表单数据以URI参数的方式提交 POST: 将表单数据放在请求包体中提交
- enctype: 在POST方法下,对表单内容在请求包体中的编码方式
- application/x-www-form-urlencoded 数据被编码成以’&‘分隔的键-值对,同时以’=‘分隔键和值,字符以URL编码方式编码
- multipart/form-data boundary分隔符 每部分表述皆为HTTP头部描述子包体,例如Content-Type last boundary结尾
- multipart(RFC1521)的abnf定义
|
|
附录:评估Web架构的七大关键属性
- HTTP协议应当在以下属性中取得可接受的均衡:
(1) 性能Performance: 影响高可用的关键因素
(2) 可伸缩性Scalability: 支持部署可以相互交互的大量组件
(3) 简单性Simplicity: 易理解、易实现、易验证
(4) 可见性Visiable: 对两个组件间的交互进行监视或者仲裁的能力。如缓存、分层设计等
(5) 可移植性Portability: 在不同的环境下运行的能力
(6) 可靠性Reliability: 出现部分故障时,对整理影响的程度
(7) 可修改性Modifiability: 对系统作出修改的难易程度,由可进化性、可定制性、可扩展性、可配置性、可重用性构成
- 架构性能:性能
- 网络性能Network Performance
- Throughput吞吐量:小于等于带宽bandwidth
- Overhead开销:首次开销,每次开销
- 用户感知到的性能User-perceived Performance
- Latency延迟:发起请求到接收到响应的时间
- Completion完成时间:完成一个应用动作所花费的时间
- 网络效率Network Efficiency
- 重用缓存、减少交互次数、数据传输距离更近、COD
- 架构属性:可修改性
- 可进化性Evolvability: 一个组件独立升级而不影响其他组件
- 可扩展性Extensibility:向系统添加功能,而不会影响到系统的其他部分
- 可定制性Customizability:临时性、定制性地更改某一要素来提供服务,不对常规客户产生影响
- 可配置性Configurability:应用部署后可通过修改配置提供新的功能
- 可重用性Reusabilit:组件可以不做修改在其他应用在使用时
- 通过上面的架构属性可以推导出下面的REST架构:
http
/---->(-O){Proxy}($-)--http--(-O){Gateway}($-)--http--(-O)[OriginServer]
a/ \ /
/ \ /
/ DNS
/
{UserAgent}($-) ----b----------------------------------------------http---(-$)[OriginServer]
| \
DNS \
c\-------(-$){Proxy}------------------------------wais-------[DB]
ClientConnector: (O-) Client+Cache: ($-) ServerConnector: (-O) ServerCache: (-$)
- 五种架构风格
在分布式的web架构中呢,主要有5类架构风格,那什么叫做架构风格呢?我们在日常编程中,可能会有习惯用法,
在高级语言面向对象编程中,可能会有设计模式,再往上呢,更大粒度的抽象,我们可以用到架构。
而架构风格呢,是指某一类架构它具有相同的或者说类似的一些约束,我们把它归纳为一类架构风格。
(1) 数据流风格Data-flow Syles
优点:简单性、可进化性、可扩展性、可配置性、可重用性
管道与过滤器Pipe And Filter, PF
* PF: 每个Filter都有输入端和输出端,只能从输入端读取数据,处理后再从输出端产生数据
* UPF: 统一接口的管道与过滤器Uniform Pipe And Filter, UPF
在PF上增加了统一接口的约束,所有Filter过滤器必须具备同样的接口
Style : PF UPF <br>
Derivation : PF <br>
Net Perform : - <br>
UP Perform : ± ± <br>
Efficiency : <br>
Scalability : <br>
Simplicity : + ++ 统一接口以后它的简单性有了很大的提升,它的每个模块呢,每个Filter,都可以独立去升级<br>
Evolvability : + + <br>
Extensibility : + + 我们再增加一个协议层,或者再增加一个模块,都是很容易的,所以扩展性非常好<br>
Customiz. : <br>
Configur. : + ++ 我们可以通过配置文件来增加我们的filter,或者说我们的协议层级<br>
Reusability : + ++ 而在我们的可重用性上也是非常好的,每个filter我们可以独立拿出来以后,给新的架构去使用<br>
Visibility : + <br>
Portability : <br>
Reliability : <br>
(2) 复制风格Replication Styles
优点:用户可察觉的性能、可扩展性,网络效率、可靠性都会得到提升
复制风格中主要有两类架构:
* RR: 复制仓库Replicated Repository
多个进程提供相同的服务,通过反向代理对外提供集中服务
这种复制风格是非常常见的,比如mysql的冷热备份,我们很多的WebApplication,同时提供很多服务
* 缓存: $
RR的变体,通过复制请求的结果,为后续请求复用
Style : RR $ <br>
Derivation : RR <br>
Net Perform : <br>
UP Perform : ++ + 对于用户可以察觉的网络性能,RR和$都有所提升<br>
Efficiency : + 直接减少了网络的传输流量,所以缓存架构在网络效率上会更高些<br>
Scalability : + + 可伸缩性,因为有很多可以复制的进程或者可以复制的数据,也会导致我们的Scalability性能更好<br>
Simplicity : + 在简单性上,缓存风格的表现也会更好些<br>
Evolvability : <br>
Extensibility : <br>
Customiz. : <br>
Configur. : <br>
Reusability : <br>
Visibility : <br>
Portability : <br>
Reliability : + 因为有多个进程也就是说多个服务,所以RR的可靠性也会更好些<br>
(3) 分层风格Hierarchical Styles
优点:简单性、可进化性、可伸缩性
* CS: 客户端服务器Client-Server, CS
由Client触发请求,Server监听到请求后产生响应,Client一直等待收到响应后,会话结束
* LS: 分层系统Layered Syste, LS
每一层为其之上的层服务,并使用在其之上的层所提供的服务,例如TCP/IP
* LCS: 分层客户端服务器Layered Client-Server, LCS
LS+CS,例如正向代理和反向代理,从空间上分为外部层和内部层
正向代理,它自然会把客户端和我们的网络环境分离
反向代理,它自然会把企业内网和企业外面的Internet网络分离
* CSS: 无状态、客户端服务器Client-Stateless-Server CSS
基于CS,服务器上不允许有session state会话状态
也就是说,我们不应该期待同一个客户端向服务器发来的请求,第二个请求必须依赖上一个请求中的传输的数据,才可以服务第二个请求。
提升了可见性、可伸缩性、可靠性,但重复数据导致降低网络性能
但是因为每个请求都需要携带完整的数据,所以就导致我们的网络性能下降,其实现在http2.0到http1.1之间的很多的升级都体现在这几个方面,
比如我们http2.0中,不希望重复的传递http的头部,因为http的头部,特别是cookie,占用了大量的网络资源,
就是因为http2.0,它已经做不到无状态了,所以它的重复数据相对比较少,网络性能更高,
但是可见性、可伸缩性和可靠性上,http2.0就相对要差些。
* C$SS: 缓存、无状态、客户端服务器Client-Cache-Stateless-Server C$SS
* LC$SS: 分层、缓存、无状态、客户端服务器Layerd-Client-Cache-Stateless-Server,LC$SS
* RS: 远程会话Remote Session, RS
Rest架构没有采用
CS变体,服务器保存Application state应用状态
比如,FTP,FTP每次发送一个请求的时候,需要知道之前你发出来的请求导致现在这个客户是在哪一层目录,
它之前是发送了哪些端口等等,这样的一些信息,所以它其实是需要服务器来保存Application state的
* RDA: 远程数据访问Remote Data Access, RDA
Rest架构没有采用
CS变体,Application state应用状态同时分布在客户端和服务器
巨大的数据集有可能通过迭代而减少
比如,sql中的游标,我们在使用sql语言来查询数据的时候,因为我们查询的数据,可能会包含百万行的数据,
那么我们就可以使用游标,反复的一页一页的去获取数据,也就是客户端保存了当前在第几页的状态,
而服务器端也需要为游标保存相应的数据。它的好处是巨大的数据集有可能通过迭代而减少,但是它的简单性、
可伸缩性是非常差的,所以传统的关系型数据库,很少能够支撑这种高可用性的,基于数据仓库的这种多个热备份的分布式架构,是很难达到的。
Style : CS LS LCS CSS C$SS LC$SS RS RDA<br>
Derivation : CS+LS CS CSS+$ LCS+C$SS CS CS <br>
Net Perform : - - - <br>
UP Perform : - - + ± <br>
Efficiency : + + + + <br>
Scalability : + + ++ ++ ++ +++ - - <br>
Simplicity : + + + + ++ + - <br>
Evolvability : + + ++ + + ++ + <br>
Extensibility : <br>
Customiz. : <br>
Configur. : <br>
Reusability : + + + <br>
Visibility : + + + - + <br>
Portability : + + + <br>
Reliability : + + + - <br>
(4) 移动代码风格Mobile Code Styles
优点:可移植性、可扩展性、网络效率
* VM: 虚拟机Virtual Machine, VM
分离指令与实现
* REV: 远程求值Remote Evaluation, REV
基于CS的VM,将代码发送至服务器执行
所以,Rest架构下,我们的Web环境下是没有办法使用REV架构的,因为客户端的代码可能充满了这样恶意的代码,风险是非常大的。
* COD: 按需代码Code on Demand, COD
服务器在响应中发回处理代码,在客户端执行
优秀的可伸展性和可配置性,提升用户可察觉性能的网络效率
Javascript使用的就是COD模型
* LCODC$SS: 分层、按需代码、缓存、无状态、客户端服务器
Layered-Code-on-Demand-Client-Cache-Stateless-Server, LCODC$SS
LC$SS+COD L[COD]C$SS
* MA: 移动代理Mobile Agent,MA
相当于REV+COD
Style : VM REV COD LCODC$SS MA <br>
Derivation : CS+VM CS+VM LC$SS+COD REV+COD <br>
Net Perform : - <br>
UP Perform : + ++ + <br>
Efficiency : + + ++ ++ <br>
Scalability : - + +4+ <br>
Simplicity : ± ± ± +±+ ± <br>
Evolvability : ++ <br>
Extensibility : + + + + ++ <br>
Customiz. : + + <br>
Configur. : + + + <br>
Reusability : + <br>
Visibility : - - - ± - <br>
Portability : + + + + <br>
Reliability : - + <br>
(5) 点对点风格Peer-to-Peer Styles(Rest架构没有使用,但是分布式网络中经常使用)
优点:可进化性、可重用性、可扩展性、可配置性
* EBI: Event-based Integration
基于事件集成系统,如由类似Kafka这样的消息系统 + 分发订阅来消除耦合
优秀的可重用性、可扩展性、可进化性
缺乏可理解性
由于消息广播等因素造成的消息风暴,可伸缩性差
* Chiron-2,C2
参见论文《A Component-and Message-Based Architectural Style for GUI Software》
相当于EBI+LCS,控制了消息的方向
* Distributed Objects, DO
组件结对交互
* Brokered Distributed Objects, BDO
引入名字解析组件来简化DO,例如CORBA
Style : EBI C2 DO BDO <br>
Derivation : EBI+LCS CS+CS DO+LCS <br>
Net Perform : - - <br>
UP Perform : - - <br>
Efficiency : + + + <br>
Scalability : -- <br>
Simplicity : ± + <br>
Evolvability : + ++ + ++ <br>
Extensibility : + + + + <br>
Customiz. : <br>
Configur. : + + + + <br>
Reusability : + ++ + ++ <br>
Visibility : - ± - - <br>
Portability : + + <br>
Reliability : - ± - <br>
- 风格演化
|
+----------+--------------+-----------------+--------------+
| | | | |
replicated separated layered programmable uniform interface
| | | | |
(RR) (CS)----+--+ (LS) (VM) (U)
| | | | | | |
on-demand stateless | +----+----mobile------>| simple
| | intermediate | | visible
($) (CSS) +--->--(LCS) (COD) |
\ | | | |
cacheable reliable shared extensible reusable
\ | | | |
------| | | |
(C$SS)-scalable>(LC$SS)-multiorg>(LCODC$SS)---->(REST)
本文发表于 0001-01-01,最后修改于 0001-01-01。
本站永久域名「 jiavvc.top 」,也可搜索「 后浪笔记一零二四 」找到我。