<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>http &#8211; 科技改变生活-雨落星辰</title>
	<atom:link href="https://p1e.cn/html/tag/http/feed" rel="self" type="application/rss+xml" />
	<link>https://p1e.cn</link>
	<description>所有的伟大,都源于一个勇敢的开始</description>
	<lastBuildDate>Fri, 07 Jun 2019 11:12:09 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.2</generator>
	<item>
		<title>如何快速掌握HTTP协议？</title>
		<link>https://p1e.cn/html/1205.html</link>
					<comments>https://p1e.cn/html/1205.html#respond</comments>
		
		<dc:creator><![CDATA[Naoki]]></dc:creator>
		<pubDate>Fri, 07 Jun 2019 11:10:24 +0000</pubDate>
				<category><![CDATA[运维笔记]]></category>
		<category><![CDATA[http]]></category>
		<guid isPermaLink="false">http://www.815494.com/?p=1205</guid>

					<description><![CDATA[HTTP 协议极其庞杂，它影响着浏览器、爬虫、代理服务器、防火墙、CDN、Web 容器、微服务等诸多方面，自身的规范却并不统一，所要面对的各类软件的新旧版本也同时存在于网络上。在这种情况下，如果对 HTTP 没有一个深入的理解，就很容易被各种各样的网络问题难倒。 那么，如何才能快速掌握HTTP协议呢？ 在我看来，需要从以下四个方面入手： 工欲善其事，必先利其器，首先我们先要掌握好抓包及相关的工具，这样在分析各种网络协议时也就更加得心应手。 先从架构入手，搞清楚 HTTP 协议到底想解决什么问题，面临哪些非功能性的约]]></description>
										<content:encoded><![CDATA[<p><span data-shimo-docs="[[20,&quot;HTTP 协议极其庞杂，它影响着浏览器、爬虫、代理服务器、防火墙、CDN、Web 容器、微服务等诸多方面，自身的规范却并不统一，所要面对的各类软件的新旧版本也同时存在于网络上。在这种情况下，如果对 HTTP 没有一个深入的理解，就很容易被各种各样的网络问题难倒。&quot;]]">HTTP 协议极其庞杂，它影响着浏览器、爬虫、代理服务器、防火墙、CDN、Web 容器、微服务等诸多方面，自身的规范却并不统一，所要面对的各类软件的新旧版本也同时存在于网络上。在这种情况下，如果对 HTTP 没有一个深入的理解，就很容易被各种各样的网络问题难倒。</span></p>
<p><span data-shimo-docs="[[20,&quot;那么，如何才能快速掌握HTTP协议呢？&quot;]]">那么，如何才能快速掌握HTTP协议呢？</span></p>
<p>在我看来，需要从以下四个方面入手：</p>
<ol>
<li>工欲善其事，必先利其器，首先我们先要掌握好抓包及相关的工具，这样在分析各种网络协议时也就更加得心应手。</li>
<li>先从架构入手，搞清楚 HTTP 协议到底想解决什么问题，面临哪些非功能性的约束，又是怎样一步步发展变迁至今的。</li>
<li>熟悉协议格式，对隧道或者正向代理下的 URI 格式、对多表述包体和不定长包体的传输格式要了解，对 DNS 的 QUESTION/ANSWER 也要了解。</li>
<li>掌握应用场景，跨域访问与同源策略到底在纠结什么？代理服务器上的共享缓存如何精细化控制？</li>
</ol>
<p><span data-shimo-docs="[[20,&quot;先给大家分享我整理的 HTTP 学习知识图谱，你可以收藏起来，时不时地拿出来对照：&quot;]]">先给大家分享我整理的 HTTP 学习知识图谱，你可以收藏起来，时不时地拿出来对照：</span></p>
<p><img fetchpriority="high" decoding="async" class="alignnone size-full alignnone wp-image-1206" src="https://p1e.cn/wp-json/cs/v1/1206/full" width="2662" height="4829" /></p>
<p><span data-shimo-docs="[[20,&quot;下面，我们来一一详述这四个方面。&quot;]]">下面，我们来一一详述这四个方面。</span></p>
<h1>1、用好工具</h1>
<p>学好HTTP协议，至少要用到下面4个工具：</p>
<h3>1.1 Chrome Network抓包面板</h3>
<p>这个工具有4个优点：</p>
<ul>
<li>快速分析HTTP请求</li>
<li>便捷卸载TLS/SSL内容</li>
<li>可协助分析页面加载性能</li>
<li>方便分析websocket内容</li>
</ul>
<p>该工具包含5个面板，在过滤器的Filter输入栏中还支持复杂的属性过滤，在请求列表中可以看到请求的上下游，亦能看到每个请求的时间分布。</p>
<p><img decoding="async" class="alignnone size-full alignnone wp-image-1207" src="https://p1e.cn/wp-json/cs/v1/1207/full" width="1155" height="537" /></p>
<h3>1.2 telnet</h3>
<p>这个小工具主要用于构造原始的应用层协议，帮助我们理解HTTP实际在网络中传输的格式是什么样的。</p>
<h3>1.3 curl</h3>
<p>telnet有2个问题：</p>
<p>1、太过繁琐，每次要输入完整的请求。实际我们可能只是想改一下方法或者某个HEADER头部。</p>
<p>2、不支持HTTPS，不支持包体压缩，导致无法向某些站点发起请求。</p>
<p>而curl完美解决了这些问题。它也用于构造定制化的HTTP请求，并可以分析HTTP响应头部或者包体。</p>
<h3>1.4 Wireshark</h3>
<p>这是学习完整Web协议栈的必备工具，我们可以在服务器端用tcpdump抓包后，在可视化的Wireshark上便捷分析。</p>
<p>Wireshark功能极为强大：</p>
<ul>
<li>既支持BPF捕获过滤器，也支持分析时的显示过滤器；</li>
<li>通过流跟踪或者会话图标，我们可以轻松的以session会话为单位进行分析;</li>
<li>通过可配置的着色规则，但以不同的色彩帮助我们轻松找出有问题的报文；</li>
<li>通过报文的标注及导出，以及文件的合并、时间的平移，可以轻松将多台机器上的抓到的报文放在一起分析对比；</li>
<li>既可以通过Packet Detail中看到每层报文解析出的可读值，也能在Packet Byte中看到二进制流。</li>
<li>支持报文统计，对大量HTTP报文的分析非常方便！</li>
</ul>
<p>&nbsp;</p>
<h1>2、理解架构</h1>
<p>要理解HTTP的架构，需要从以下4个方面入手：</p>
<h3>2.1 HTTP协议想解决什么问题？</h3>
<p>HTTP协议设计之初用于解决人与机器间的通讯，所谓“B/S架构”中的浏览器是我们必须考虑进的因素。</p>
<p>因此，HTTP协议需要传输超媒体数据（包括图片、视频等大粒度数据）。</p>
<p>当然，现在许多物联网中的设备也在使用HTTP协议，所以，它也在解决机器与机器间的通讯。</p>
<p>当然，网络爬虫也是HTTP协议要面对的问题，robots.txt这样的规范也应运而生。</p>
<h3>2.2 HTTP协议面对哪些非功能性约束？</h3>
<p>主要包括以下5个方面：</p>
<ul>
<li>高可扩展性，因为它需要面对全世界用户群体以及数十年以上的寿命</li>
<li>低门槛，既有使用门槛也包括开发门槛，JavaApplet的式微与Javascript的如日中天就是极好的例证</li>
<li>分布式环境下的大粒度数据传输</li>
<li>internet下无法控制的负载以及种类版本繁多的组件</li>
<li>向前兼容，HTTP/1.1中的许多特性都需要照顾到还有仅支持HTTP/1.0的代理服务器在互联网上运行</li>
</ul>
<h3>2.3 遵循的架构设计方案是怎样的？</h3>
<p>HTTP/1.1是完全遵循REST架构设计，而REST架构主要包含以下4个子架构：</p>
<ul>
<li>LCS：空间上分层的客户端服务器，因此我们才有了隧道、代理、网关、CDN、负载均衡等产品；</li>
<li>CSS：无状态的客户端服务器，因此我们才有了Request/Response请求模式，才要求cookie头部或者URL不能超过4K等。</li>
<li>COD：按需代码，即将代码从服务器移至客户端再运行，今天的前端生态都是基于此架构下而生的Javascript衍伸的。</li>
<li>$：缓存，HTTP组件中无处没有缓存，共享缓存、私有缓存，没指明缓存时限还要预估一个缓存过期值。</li>
</ul>
<h3>2.4 HTTP协议特性有哪些？</h3>
<p>首先，我们需要理解它在OSI概念模型的哪一层，它又是处在TCP/IP体系的什么位置。</p>
<p>其次，我们可以从上述架构中推导出它的定义：一种无状态的、应用层的、以请求/应答方式运行的协议，它使用可扩展的语义和自描述消息格式，与基于网络的超文本信息系统灵活的互动！</p>
<h1>3、熟悉协议格式</h1>
<p>学习HTTP协议格式时，应从以下3个方面入手：</p>
<h3>3.1 扩充巴科斯-瑙尔范式：ABNF元语言</h3>
<p>元语言可用于描述协议格式，而ABNF就严谨定义了HTTP的格式。</p>
<p>ABNF并不复杂，只需要我们花10分钟即可学会，它包括操作符和核心规则2大部分，这里不再列出。</p>
<h3>3.2 HTTP协议格式</h3>
<p>掌握HTTP协议格式需要理清一个树状知识图，参见本文末尾我整理的HTTP知识图谱。</p>
<h3>3.3 DNS协议格式</h3>
<p>我们需要掌握3个方面的知识：</p>
<ul>
<li>DNS报文是基于UDP的，它的通用格式是固定的，需要理解各字段含义</li>
<li>Questions部分需要重点看QNAME域名是如何编码的，以及QTYPE的含义</li>
<li>Answers部分字段更多，特别是对NAME及RDATA部分的偏移表示法要有所了解</li>
</ul>
<h1>4、掌握应用场景</h1>
<p>HTTP的应用场景极其广泛，下面我列出常见的9个场景，在协议格式中提到的各方法、响应码、头部、包体编码方式都与具体场景相关。</p>
<h3>4.1 内容如何协商</h3>
<p>响应式协商由于RFC规范不明少有使用，而主动式协商关于语言、编码、媒体类型等是我们日常打交道的常见方式。</p>
<h3>4.2 FORM表单如何提交</h3>
<p>表单提交虽然有3种编码方式，但最常用的还是boundary分隔的多表述共存于单一包体的方式，waf防火墙必须考虑如何应用这种包体内的SQL注入攻击。</p>
<h3>4.3 Range请求的使用</h3>
<p>传输大文件所用到的断点续传和多线程下载，都需要使用Range规范，为防止多请求下载过程中服务器端更新的情况，还引入条件请求If-Range。</p>
<h3>4.4 Cookie与Session的设计</h3>
<p>Set-Cookie中有许多属性，既有限制有效期的expires-av、max-age-av，也有限制使用范围的domain-av、path-av，还有限制协议的secure-av或是限制使用对象的httponly-av。</p>
<p>这种种限制都在针对浏览器使用cookie是否安全，而同时为了便利性浏览器也支持第三方cookie，这更是为厂商搜集用户信息提供了方便。</p>
<h3>4.5 浏览器同源策略与跨域请求</h3>
<p>同源策略是浏览器所做的限制，如果我们直接基于网络库处理响应是不受此限制的。所以，这个同源策略的有效性非常依赖浏览器的实现。当然，同源策略中不包含防范CSRF攻击，服务器通常基于token策略解决CSRF攻击。</p>
<p>安全与便利是必须权衡取舍的，为了增加便利性，必须允许AJAX的跨域请求，于是CORS便诞生了。</p>
<h3>4.6 条件请求</h3>
<p>条件请求不只可应对多线程下载时的资源中途变量，也可针对多人协作的wiki系统生效，同时也能用于缓存更新。实际在Restful API设计中它大有发挥余地。</p>
<h3>4.7 共享缓存与私有缓存</h3>
<p>当下的互联网上缓存无处不在，即使服务器上没有配置某些资源可以缓存，浏览器也在想尽办法预估出一段时间缓存资源。因为，缓存能够极大的提升用户体验、降低网络负载！能够控制缓存的HTTP头部非常多，它不只控制缓存的有效期，也在控制缓存依据的关键字。</p>
<h3>4.8 重定向的应用</h3>
<p>关于重定向我们需要从2个维度4个象限去理解：可更改方法 | 不可更改方法、可缓存|不可缓存</p>
<p>这便引出了301、302、303、307、308这5种不同的响应状态码。</p>
<h3>4.9 网络爬虫</h3>
<p>爬虫无处不在，远不只久远的搜索引擎爬虫，当下在出行（例如12306火车票或者亚航）、电商、社交（新浪微博）等都广受爬虫骚扰，爬虫不只爬取信息，还模拟人类制造行为，例如许多抢票机、僵尸粉都如此。而另一方面，为了欢迎google/baidu的爬虫，又诞生了各种SEO策略及教程，还有许多利用PageRank漏洞提升关键词排名的商家在以此盈利。所以，理解爬虫的工作方式也是非常重要的。</p>
<p>&nbsp;</p>
<p>当然，HTTP应用场景远不止这些，但彻底掌握这些场景将使我们完全理解HTTP协议中常见的方法、头部、响应码等等。</p>
<p class="ql-long-3656577">HTTP 协议是 Web 协议里非常重的一块，作为程序员，无论你是前后端工程师，还是运维测试，如果<strong>想面试更高的职位，或者要站在更高的角度去理解技术业务架构，并能在问题出现时快速、高效地解决问题，Web 协议一定是你绕不过去的一道坎。</strong>熟练掌握各种常用 Web 协议，可以帮你在工作中轻松应对各种网络难题。</p>
<div></div>]]></content:encoded>
					
					<wfw:commentRss>https://p1e.cn/html/1205.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>两种浏览器缓存机制的了解</title>
		<link>https://p1e.cn/html/427.html</link>
					<comments>https://p1e.cn/html/427.html#respond</comments>
		
		<dc:creator><![CDATA[Naoki]]></dc:creator>
		<pubDate>Wed, 12 Sep 2018 05:10:18 +0000</pubDate>
				<category><![CDATA[运维笔记]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[缓存]]></category>
		<guid isPermaLink="false">https://www.815494.com/?p=427</guid>

					<description><![CDATA[浏览器缓存 浏览器缓存是指浏览器端用于在本地保存数据并进行快速读取的以避免重复资源请求的传输机制的统称。 打开Chrome浏览器，进入开发者工具，在Application那，你会发现有 HTTP 文件缓存、LocalStroage、SessionStorage、indexDB、Web SQL、Cookie、CacheStorage和Application Cache 。 这里只介绍 HTTP 文件缓存 和 Application Cache HTTP 文件缓存 HTTP 文件缓存是基于 HTTP 协议的浏览器文件级]]></description>
										<content:encoded><![CDATA[<h2 id="directory0300073947773903841">浏览器缓存</h2>
<p>浏览器缓存是指浏览器端用于在本地保存数据并进行快速读取的以避免重复资源请求的传输机制的统称。</p>
<p>打开Chrome浏览器，进入开发者工具，在Application那，你会发现有 HTTP 文件缓存、LocalStroage、SessionStorage、indexDB、Web SQL、Cookie、CacheStorage和Application Cache 。</p>
<p>这里只介绍 HTTP 文件缓存 和 Application Cache</p>
<h2 id="directory0300073947773903842">HTTP 文件缓存</h2>
<p>HTTP 文件缓存是基于 HTTP 协议的浏览器文件级缓存机制。这套机制决定了浏览器在文件重复请求时判断是否更新文件还是从本地读取文件。</p>
<p>流程图如下：</p>
<p><img decoding="async" class="alignnone size-large wp-image-431" src="https://i.p1e.cn/2018/09/3982592708-1-1024x780.png" alt="" width="1024" height="780" /></p>
<p>流程图步骤说明：</p>
<ol>
<li>浏览器会先查询 <code>Cache-Control</code> 来判断内容是否过期，未过期则直接读取缓存文件，不发送 HTTP 请求，否则进入步骤2</li>
<li>浏览器判断上次文件的响应头是否有 <code>Etag</code>，有则连同 <code>If-None-Match</code> 一起发送请求，由服务器判断 <code>Etag</code> ，如未修改则返回304，修改则返回200，否则进入步骤3</li>
<li>浏览器判断上次文件的响应头是否有 <code>Last-Modified</code>，有则连同 <code>If-Modified-Since</code> 一起发送请求，由服务器判断 <code>Last-Modified</code> ，失效则返回200，未失效则返回304</li>
<li><code>Etag</code> 和 <code>Last-Modified</code> 都没有，则直接200</li>
</ol>
<p>补充说明：<code>Cache-Control</code> 跟 <code>Expires</code> 是类似的，但前者指的是相对过期时间，后者指的是绝对过期时间，如果两者同时设置，则只有 <code>Cache-Control</code> 生效</p>
<p>缓存时长计算公式：缓存时长 ＝ 响应时间 ＋ 缓存寿命 － 当前时间</p>
<p>响应时间指浏览器接收到服务端的响应的时间</p>
<p>如需了解更多，可以查看我另外一篇博文：<a href="https://www.linpx.com/p/web-cache-optimization.html" target="_blank" rel="noopener noreferrer">Here</a></p>
<h2 id="directory0300073947773903843">cacheStorage</h2>
<p>如果对 PWA 有所了解的话同学应该知道 PWA 的离线能力就是由 cacheStorage 提供，所以这部分也是成为重点部分。</p>
<p>在讲解 cacheStorage 先介绍一下 Application Cache 。</p>
<p>Application Cache 是一种允许浏览器通过 manifest 配置文件在本地有选择性地存储静态资源的文件级缓存机制。页面第二次以后打开，资源将会根据 manifest 配置描述有选择地读取本地 Application Cache 里面的文件。优势主要有：1、离线访问；2、加载速度快；3、服务器负载小。但缺点也很明显，包括：1、开始被标准弃用；不兼容主流(移动)浏览器；3、容量仅有5MB；4、资源失效时，更新也跟着失效；5、manifest要同源等等</p>
<p>这里再提一下 RAIL ，一个以用户为中心的性能模型，看到这里，你就知道了 Application Cache 其实并不怎么符合 RAIL</p>
<p>终于可以讲 cacheStorage 了</p>
<p>Google 强势推 PWA 以及其支持的技术，其中就有 ServiceWorker。cacheStorage 就是在 ServiceWorker 规范中定义的，用于保存每个 ServiceWorker 声明的 Cache 对象。</p>
<p>cacheStorage 在 Chrome 浏览器端里全局内置了 caches 对象，通过五个核心 API 方法直接对 Cache 对象进行操作，如下：</p>
<ul>
<li>caches.match() : 匹配key中含有该字符串的 Cache 对象，有返回一个 Promise 对象</li>
<li>caches.has() : 检查是否包含 Cache 对象，是则返回一个 Promise 对象</li>
<li>caches.open() : 打开或新建一个 Cache 对象并返回一个 Promise 对象</li>
<li>caches.delete() : 成功找到和删除 Cache 对象并返回一个 Promise 对象，否则返回false</li>
<li>caches.keys() : 遍历所有 Cache 对象，当含有keys中字符串的任意一个时返回一个 Promise 对象</li>
</ul>
<p>要了解 cacheStorage 就得深入了解 ServiceWorker，ServiceWorker 与 WebWorker 一样是在浏览器后台作为一个独立的线程去运行JavaScript，并通过 message 与 postMessage 方法在页面之间通信。移动端的原生应用一般都有消息推送、离线使用、自动更新等能力。如果使用 ServiceWorker 也可以让 Web 应用具备类似的能力。</p>
<p>在使用 ServiceWorker 时，通常需要先注册 一个 ServiceWorker JavaScript脚本，然后在里面写入 caches 的缓存控制方法，下图为 ServiceWorker 运行的生命周期</p>
<p><img decoding="async" class="alignnone size-full wp-image-430" title="两种浏览器缓存机制的了解" src="https://i.p1e.cn/2018/09/2578044744.png" alt="两种浏览器缓存机制的了解" /></p>
<p>注册 ServiceWorker</p>
<pre><code class="lang-js hljs javascript"><span class="hljs-keyword">if</span>(navigator.serviceWorker){
  navigator.serviceWorker.register(<span class="hljs-string">'./sw.js'</span>).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">registration</span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'sw注册成功'</span>);
  }).catch(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">e</span>)</span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'sw注册失败'</span>);
  });
}</code></pre>
<p>sw.js里的缓存列表</p>
<pre><code class="lang-js hljs javascript"><span class="hljs-keyword">let</span> cacheList = [<span class="hljs-string">'index.js'</span>,<span class="hljs-string">'index.css'</span>];</code></pre>
<p>将缓存列表注册到 cacheStorage 里，使用caches管理</p>
<pre><code class="lang-js hljs javascript"><span class="hljs-keyword">this</span>.addEventListener(<span class="hljs-string">'install'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>)</span>{
  event.waitUntil(
    caches.open(<span class="hljs-string">'indexCache'</span>).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">cache</span>)</span>{
      <span class="hljs-keyword">return</span> caches.addAll(cacheList);
    })
  );
});</code></pre>
<p>监听 ServiceWorker 的 fetch 方法，如果有响应则使用响应，否则读取缓存</p>
<pre><code class="lang-js hljs javascript"><span class="hljs-keyword">this</span>.addEventListener(<span class="hljs-string">'fetch'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>)</span>{
  event.respondWith(cacnes.match(event.request).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">response</span>)</span>{
    <span class="hljs-keyword">if</span>(response){
      <span class="hljs-keyword">return</span> response;
    }
    <span class="hljs-keyword">let</span> responseToCache = response.clone();
    caches.open(<span class="hljs-string">'indexCache'</span>).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">cache</span>)</span>{
      cache.put(event.request, responseToCache);
    });
  }));
});</code></pre>
<h2 id="directory0300073947773903844">总结</h2>
<p>通过横向了解 HTTP 文件缓存机制 和 ServiceWorker的cacheStorage，我们可以知道，前者是一种基于客户端的缓存策略，比较固定，而后者则是一种基于页端缓存策略，极具自由和可定制。</p>
<div></div>]]></content:encoded>
					
					<wfw:commentRss>https://p1e.cn/html/427.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
