Hertz 口水话|青训营笔记

153 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 20 天

本篇文章归档于 “第五届字节跳动青训营”,主要是为了完成和记录掘金的 “伴学笔记创作活动” 活动,如果你对我的其他文章感兴趣,可以去我的 专栏 中逛逛看有没有你想要的东西。

HTTP 的相关概念

关于 HTTP(Hypertext Transfer Protocol),很多面试官会把它与 RPC、TCP 之类的混在一起考察。但实际上,HTTP 作为应用层的协议,从操作系统的角度来看仅存在于用户态,本质相差甚远,更多知识也建议出门右转 Google,这里简单记录一点概念:

  • 请求行/状态行:方法名、URL、协议版本、状态码、状态码描述;
  • 请求头/响应头:协议约定相关业务;
  • 请求体/响应体:更多信息。

HTTP 在应用层的请求流程:

  • 业务层:实现业务逻辑;
  • 服务治理层:可以自己实现,也可以利用中间件进行服务治理;
  • 路由层:为 URL 和处理函数设计匹配策略;
  • 编解码层:将协议编解码为字节流进行传输。

HTTP 的演化之路:

  • HTTP 1.0 -> HTTP 1.1:
    • 短连接改为长连接
    • 支持管道传输 -> 可能导致 HTTP 队头阻塞
  • HTTP 1.1 -> HTTP 2.0:
    • 头部压缩
    • 二进制格式
    • 多路复用(并发传输 Stream)-> 可能导致 TCP 队头阻塞
    • 服务推送(Server 主动连接 Client)
  • HTTP 2.0 -> HTTP 3.0:
    • UDP 替代 TCP,使用 QUIC
    • 解决 TCP 队头阻塞
    • 加密减少 3 次握手次数
    • 连接迁移(连接 ID)

Anyway,还有很多如缓存策略等细节没有提及,有空可以自行 Google~

HTTP 的分层设计

分层设计的核心:高内聚、低耦合,易复用和高扩展性,系统设计应由简至繁。

这一部分的课程感觉很注重实践,和之前的开发经历产生了很多共鸣,可以反复体会一下,这里就简单归纳一下:

  • 应用层:API 的可读性(特别是对于开源项目来说,这能极大地降低维护成本),兼容性,可观测,可测试,可扩展;
  • 服务治理层:保障完整的生命周期,预处理和后处理,多中间件可插拔,易用性;
  • 路由层:静态路由,参数路由,路由修复,冲突和优先级,HTTP 匹配和多处理函数;
  • 编解码层:抽象合适的接口,应该传递上下文,而非嵌入,在连接上读取数据;
  • 传输层:BIO、AIO 和 NIO 之类的网络模型。

总的来说,在进行分层设计时,应该:明确需求 -> 业界调研 ->方案权衡 -> 方案评审 -> 确定开发

HTTP 的性能优化

课程里谈到了两方面的优化:网络库和协议。网络库的优化就是之前提到的 Netpoll,这里不再赘述啦。我们看看 Hertz 是如何对协议进行优化的:

  • Headers 解析:找到特征边界 \n\r,通过 key 的首字母筛除 key,解析对应的 value 并使用 byte slice 进行管理;-> 核心字段快速解析,额外存储负担,普通 Header 性能低(无 map)
  • Header key 规范化:表映射;-> 高转换率,额外内存负担,变更困难
  • 热点资源池化。-> 减少内存分配、GC 压力,提高内存复用、性能,需要额外的 Reset 逻辑,问题难定位,请求内有效

顺便记录一下一些思考,后面会进行解答:

  1. 为什么HTTP框架做要分层设计?分层设计有哪些优势与劣势;
  2. 现有开源社区HTTP框架有哪些优势与不足;
  3. 中间件还有没有其他实现方式?可以用伪代码说明;
  4. 完成基于前缀路由树的注册与查找功能?可以用伪代码说明;
  5. 路由还有没有其他的实现方式?

Hertz 架构

之前的内容已经提到了 Hertz 的一些优化思路,这里就直接上官网链接(中文)啦:

image.png

最后想说的话

追求性能会不可避免地让上手难度增加,以及生态建设缓慢,但这些优化思路还是蛮有意思的,值得回味。