第六届字节跳动青训营第一课 | 青训营

90 阅读5分钟

本次笔记主要围绕第四节课——HTTP框架修炼之道展开

1 走进HTTP协议

第一节课为HTTP协议的基本介绍,给刚入门的人梳理更清晰的知识点,让人能快速回忆起来。 超文本传输协议最开始起源于通网后将两台PC端之间互相交流和分享点什么东西,于是通过网线将两台PC端连接起来,在网线上传输0和1,实现了网络文本传输,随着进一步发展逐渐有了图片、音乐、视频、超文本的传输需求,这些资源针对text是一种扩充,于是被称为超文本,传输这种资源的协议就叫做hypertext transfer protocol。

1.1 为什么需要协议

在网线上传输的都是0和1的数据,需要一定规则才能让对方理解,具体需要:

  1. 明确的边界即开始和结束
  2. 能够携带信息即什么消息,消息类型等

1.2 协议里有什么

  1. 请求行/状态行:请求行包括方法名(常见方法名有GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH,GET是HTTP0.9协议里唯一的一个;1.0扩充了HEAD和POST;PUT、DELETE、CONNECT、OPTIONS、TRACE扩充在1.1里面,PATCH在1.1之后额外增加的一个使用比较广泛的方法,PATCH对应部分更新且不是幂等的,PUT对应完整更新且是幂等的)、URL、协议版本。状态行包括协议版本、状态码(1xx:信息类、2xx:成功、3xx:重定义、4xx:客户端错误、5xx:服务端错误)、状态码描述。
  2. 请求头/响应头:主要分为协议约定和业务相关的部分,比如content-length去指定包里有多少个字节属于协议相关,业务相关的就是自己去定义自己需要传输的源数据了。
  3. 请求体/响应体

1.3 请求流程

主要分为业务层服务治理层中间件层路由层协议编(解)码层传输层。在业务层,业务方使用框架提供API去完成业务逻辑,完成业务逻辑之后会进入服务治理的逻辑,服务治理层会存在一些垄断,限流等,服务治理层是依托于中间件层中间件层对每一个业务层都有一个先后处理的逻辑,是和请求级别绑定的,服务治理也不例外,比如打一个计时的点,进入业务层之前记录一下当前的时间,在业务层执行完毕之后,再记录一下业务执行完毕的时间,再进行一个上报,这样可以记录整个业务逻辑的耗时。之后进入协议编解码,变成别人能看懂的东西。

1.4 不足与展望

  • HTTP1:队头阻塞、传输效率低、明文传输不安全(基于TCP)
  • HTTP2:多路复用、头部压缩、二进制协议
  • QUIC:基于UDP实现、解决队头阻塞、加密减少握手次数、支持快速启动

2 HTTP框架的设计与实现

2.1 分层设计

进行分层设计的时候考虑的一些点:高内聚、低耦合、易复用、高扩展性,这个架构分为五层,层与层之间接口连接,最顶上是应用层,直接跟用户打交道的一层,提供丰富的API。下一层是中间件层,对用户有一些预处理和后处理的逻辑。路由层会有一个原生的路由曲线,提供注册、寻址相关的操作。协议层,有了这一层只要实现对应的接口,就能完成协议的扩展了。最后是网络层,不同的网络库使用场景并不相同,需要有灵活替换网络库的能力,comments会放一些公共逻辑,每一层都会使用。

  1. 应用层设计主要提供合理的API,具有可理解性,简单性,不要冗余性,兼容性,可测性,可见性。
  2. 中间件设计需要
  • 配合Handler实现一个完整的请求处理生命周期
  • 拥有预处理逻辑和后处理逻辑
  • 可以注册多中间件
  • 对上层模块用户逻辑模块易用
  1. 路由设计中框架路由实际上就是为URL匹配对应的处理函数(Handlers)
  • 静态路由:/a/b/c、/a/b/d
  • 参数路由:/a/:id/c (/a/b/c, /a/d/c)、/*all
  • 路由修复:/a/b <-> /a/b/
  • 冲突路由以及优先级:/a/b、/:id/c
  • 匹配HTTP方法
  • 多处理函数:方便添加中间件
  • ...
  1. 协议层设计
  • 抽象出合适的接口
  1. 网络层设计(传输层)
  • BIO(超时,会卡在读数据这里)
  • NIO(设置一个监听器,在监听到有足够的数据之后再去唤醒下面的function)

3 性能修炼之道与企业实践

3.1 针对网络库的优化

  1. go net “BIO”(流式友好、小包性能高)
  • 存下全部的Header
  • 减少系统调用次数
  • 能够复用内存
  • 能够多次读
  1. 可以绑定一块缓冲区go net with bufio netpoll(中大包性能高、时延低)
  • 存下全部Header
  • 拷贝出完整的Body netpoll with nocopy peek
  • 分配足够大的buffer
  • 限制最大buffer size

3.2 针对协议的优化

  • 找到Header Line边界:\r\n
  • 先找到\n再看它前一个是不是\r 采用SIMD更快:Sonic
  • 针对协议相关的Header快速解析:
  1. 通过Header key首字母快速筛除掉完全不可能的key
  2. 解析对应value到独立字段
  3. 使用byte slice管理对应header存储,方便复用。请求体中同样处理的Key:User-Agent、Content-Type、Content-Length、Connection、Transfer-Encoding

最后:追求性能;追求易用,减少误用;打通内部生态;文档建设、用户群建设