HTTP/2 in GO(二)

相关阅读:

上一篇文章中介绍了HTTP/2的二进制分帧和多路复用的特性,这次来介绍下头部压缩和服务端推送。

HTTP/2新增特性

  • 二进制分帧(HTTP Frames)
  • 多路复用
  • 头部压缩
  • 服务端推送(Server Push)

头部压缩

在HTTP/1.x中,每次HTTP请求都会携带需要的header信息,这些信息以纯文本形式传递,所以每次的请求和响应,都会浪费一些带宽,如果header信息中包含cookie等之类的信息,那么浪费的带宽就更可观了。为了减少带宽开销和提升性能,HTTP/2 使用 HPACK 压缩格式压缩请求和响应标头元数据,这种格式采用两种简单但是强大的技术:

  • 这种格式支持通过静态Huffman 编码对传输的header字段进行编码,从而减小了传输的大小。
  • 这种格式要求客户端和服务器同时维护和更新一个包含之前见过的header字段的索引列表(换句话说,它可以建立一个共享的压缩上下文),此列表随后会用作参考,对之前传输的值进行有效编码。

利用 Huffman 编码,可以在传输时对各个值进行压缩,而利用之前传输值的索引列表,我们可以通过传输索引值的方式对重复值进行编码,索引值可用于有效查询和重构完整的标头键值对。

客户端和服务端都有一个内置的静态表,部分内容如下:

静态表
+-------+-----------------------------+---------------+
| Index | Header Name                 | Header Value  |
+-------+-----------------------------+---------------+
| 1     | :authority                  |               |
| 2     | :method                     | GET           |
| 3     | :method                     | POST          |
| 4     | :path                       | /             |
| 5     | :path                       | /index.html   |
| 6     | :scheme                     | http          |
| 7     | :scheme                     | https         |
| 8     | :status                     | 200           |
| 9     | :status                     | 204           |
| 10    | :status                     | 206           |
| 11    | :status                     | 304           |
| 12    | :status                     | 400           |
| 13    | :status                     | 404           |
| 14    | :status                     | 500           |
| 15    | accept-charset              |               |
| 16    | accept-encoding             | gzip, deflate |
| 17    | accept-language             |               |
...
| 58    | user-agent                  |               |
| 59    | vary                        |               |
| 60    | via                         |               |
| 61    | www-authenticate            |               |
+-------+-----------------------------+---------------+

可以看到,部分静态表已经包含了value,比如 Index=2:method = GET,当客户端发起请求时,如果发起的是GET请求,那么只需要在Header信息中携带一个Index=2的索引即可,服务端收到通过静态表即可查出对应的请求头信息。 在静态表中传输的Header Block是这种格式的:

     0   1   2   3   4   5   6   7
   +---+---+---+---+---+---+---+---+
   | 1 |        Index (7+)         |
   +---+---------------------------+

从图中可以看到,只需要8-bit即可实现一个method的Header传输:

with index

对于静态表中不存在value的值,或者value的值跟想传递的值不一样时,就不能只传递简单的Index了;比如对于:path的头信息,如果要请求的path不在静态表里,就需要用到 Huffman 编码 了。

阅读全文

HTTP/2 in GO(一)

最近由于做一些相关项目,需要使用到HTTP/2的一些特性,花了两天的时间看了下HTTP/2的RFC-7540 的文档,又花了一天时间看了下go语言中http server中对HTTP/2的实现,做一些笔记,记录一些心得。内容比较多,会分多篇写,具体是几篇,看情况定吧。

HTTP/2 RFC7540

先来看一下什么是HTTP/2,为什么不是HTTP/1.2?HTTP/2 没有改动 HTTP 的应用语义。HTTP 方法、状态代码、URI 等概念都跟HTTP/1.1一样,但是HTTP/2在数据传输过程中做了二进制分帧(frame)处理,这点跟之前不一样,通过分帧,HTTP/2对我们的应用隐藏了其复杂性,达到了既能支持一些新特性,又能兼容之前的所有应用。所以,如果我们是跟之前一样,做一些普通的web应用,对HTTP/2的使用跟HTTP/1没有任何区别。但如果我们希望能利用到HTTP/2的一些新特性,就需要对它有一些更深入的了解。

HTTP/2新增特性

  • 二进制分帧(HTTP Frames)
  • 多路复用
  • 头部压缩
  • 服务端推送(server push)

二进制分帧(HTTP Frames)

HTTP/2最革命性的原因就在于这个二进制分帧了,要了解二进制分帧在客户端和服务端传输的过程,需要了解三个概念:

  • Frame,帧,HTTP/2协议里通信的最小单位,每个帧有自己的格式,不同类型的帧负责传输不同的消息
  • Message, 消息,类似Request/Response消息,每个消息包含一个或多个帧
  • Stream,流,建立链接后的一个双向字节流,用来传输消息,每次传输的是一个或多个帧

HTTP/2里边,这些概念的关系是这样的:

  • 所有的通信都在一个tcp链接上完成,会建立一个或多个stream来传递数据
  • 每个stream都有唯一的id标识和一些优先级信息,客户端发起的stream的id为单数,服务端发起的stream id为偶数
  • 每个message就是一次Request或Response消息,包含一个或多个帧,比如只返回header帧,相当于HTTP里HEAD method请求的返回;或者同时返回header和Data帧,就是正常的Response响应。
  • Frame是最小的通信单位,承载着特定类型的数据,例如 Headers, Data, Ping, Setting等等。 来自不同stream的frame可以交错发送,然后再根据每个Frame的header中的数据流标识符重新组装。

简言之,HTTP/2 将 HTTP 协议通信分解为二进制编码Frame的交换,这些Frame对应着特定Stream中的Message。所有这些都在一个 TCP 连接内复用。这是 HTTP/2 协议所有其他功能和性能优化的基础。

阅读全文

转载自:Kris' Blog

本文的架子参考张开套的《亿级流量网站架构核心技术》这本书分为四个部分:指导原则,高可用,高并发,实践案例。这篇文章说一说前三个部分,大部分内容都是我自己的思考,书只作为参考。

指导原则

书中所列举的,里有一些可能并不是原则,而是技巧。我理解的原则如下:

高并发原则:

  1. 无状态设计:因为有状态可能涉及锁操作,锁又可能导致并发的串行化。
  2. 保持合理的粒度:无论拆分还是服务化,其实就是服务粒度控制,控制粒度为了分散请求提高并发,或为了从管理等角度提高可操性。
  3. 缓存、队列、并发等技巧在高并发设计上可供参考,但需依场景使用。

高可用原则:

  1. 系统的任何发布必须具有可回滚能力。
  2. 系统任何外部依赖必须准确衡量是否可降级,是否可无损降级,并提供降级开关。
  3. 系统对外暴露的接口必须配置好限流,限流值必须尽量准确可靠。

业务设计原则:

  1. 安全性:防抓取,防刷单、防表单重复提交,等等等等。
  2. at least 消费,应考虑是否采用幂等设计
  3. 业务流程动态化,业务规则动态化
  4. 系统owner负责制、人员备份制、值班制
  5. 系统文档化
  6. 后台操作可追溯

以上原则只是大千世界中的一小部分,读者应当在工作学习中点滴积累。

阅读全文

入手了MBP16,但是好多东西用的还是不熟练。 浏览器用chrome一直用的比较多,比较熟。但是Safari自家的跨平台做的还是挺好的。如果快下班了,还有没看完想继续想看的网页,直接点击地址栏位置左边的+号按钮。关机走人。 在手机上,打开Safari浏览器进入像个眼睛似的的那个to read模式,就可以继续看了,而且手机网速不好也没关系哦,手机在wifi的时候已经下载好了。 这个用起来真是太方便了。 开始试着尝试多使用Safari一些,在使用过程中,确不知道怎么查看dom结构,怎么查看源代码,。后来才发现,是没有打开开发者模式的原因,做以下操作: 打开 Safari偏好设置 > 高级 > 选中 在菜单栏显示‘开发’ 然后右键,就可以看到 检查元素 啦。

阅读全文

今天在Linux下使用shell的时候,发现当我想使用Ctrl+箭头进行快速跳跃的时候,并没有出现预期的 光标 移动,而是出现了 5D, 5C 的字样。 这个很奇怪,查下相关资料,可以这样避免: 把以下两行添加到 ~/.inputrc文件中: "\e[1;5C": forward-word # ctrl + right<br /> "\e[1;5D": backward-word # ctrl + left 退出shell再重新登录,就可以解决了。

阅读全文

最近在梳理某项目上各服务接口的性能情况,遇到两个问题。以下是定位和解决问题的一个思路,分享给大家。 业务之前并没有详细的性能日志记录,仅在电信机房(T机房)进行了性能测试,结果是各接口满足预期,服务上线。 在进一步对接口进行性能分析时,对各业务接口的关键路径添加了日志统计,通过日志进行分析,将接口的延迟进行统计,接入Grafana,观察数据后,发现两类问题。 连接MongoDB的服务,网通机房(C机房)延迟比电信机房(T机房)要高。 连接Mysql的服务,网通机房(C机房)延迟比电信机房(T机房)高。 > **NOTE**: 这些服务接口,都是只读,没有写操作。 对两类问题分别进行排查: MongoDB 简单的排查后发现,MongoDB实例有过一次迁移,并且迁移后只保留了电信机房(T机房)的实例,网通机房(C机房)没有从库,所以网通机房(C机房)延迟比电信机房(T机房)高。对网通机房(C机房)部署了从库实例后,却意外发现电信机房(T机房)的延迟比网通机房(C机房)高了。再次排查后发现,代码中配置的MongoDB的读策略是secondary(从库优先),所以网通机房(C机房)有从库后,电信机房(T机房)也去网通机房(C机房)读取,导致了电信机房(T机房)的延迟变高。更改读策略为nearest(就近优先),有所好转,但并没有预想的效果那么好。仔细看下官方文档 The driver reads from a random member of the set that has a ping time that is less than 15ms slower than the member with the lowest ping time. Reads in the MongoClient::RP_NEAREST mode do not consider the member’s type and may read from both primaries and secondaries. 就会发现,nearest是在客户端维护一个到各个实例延迟小于15ms的集合,而我们电信机房(T机房)到网通机房(C机房)是光纤直连,延迟在12ms左右,所以,每次客户端可能会连接到电信机房(T机房),也可能到网通机房(C机房)。 这点在以后的应用中,大家可以注意下。 Mysql 在所有的服务中,只有一个服务接口是读mysql实现的,而这个接口的表现更是奇怪,网通机房(C机房)的延迟比电信机房(T机房)多100 ms+。 开始时猜测有可能业务内做了某些写主库的操作,比如写mysql,或写redis之类的,跨机房写导致的延迟高。

阅读全文

家里电脑重装了,想安装chrome,网络不好啊,用online的方式安装,代理都不好设置。 所以最好下载个offline的安装包。 http://www.google.com/chrome/eula.html?system=true&standalone=1 然后开始安装。 安装中遇到了0x80004002的错误提示,使用管理员权限打开又提示 已经有另一个chrome安装中。 解决办法就是 重启电脑,按F8进入安全模式,进行安装,即可安装成功。

阅读全文

作者的图片

DigDeeply

Technology Stack: Golang/PHP/Openresty, and so on…

Web Development Engineer

Beijing China