HTTP介绍
-
前后端通过http进行通信
-
下面是一张前后端分离的流程图
!
-
HTTP协议
-
HTTP:超文本传输协议
-
需要明确的开始与结束的边界
-
能够携带信息:文本、图片、音频视频等
-
请求由请求行+请求头+请求体组成
-
响应由响应行+响应头+响应体组成
-
常见的请求方法:
- GET: 请求一个指定资源的表示形式,使用 GET 的请求应该只被用于获取数据。
- HEAD: 请求一个与 GET 请求的响应相同的响应,但没有响应体。
- POST: 用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用。
- PUT: 用请求有效载荷替换目标资源的所有当前表示。
- DELETE: 删除指定的资源。
- CONNECT: 建立一个到由目标资源标识的服务器的隧道。
- OPTIONS: 用于描述目标资源的通信选项。
-
常见的状态码
状态码 类别 描述 1xx Informational(信息状态码) 接受请求正在处理 2xx Success(成功状态码) 请求正常处理完毕 3xx Redirection(重定向状态码) 需要附加操作已完成请求 4xx Client Error(客户端错误状态码) 服务器无法处理请求 5xx Server Error(服务器错误状态码) 服务器处理请求出错 作者:青颜的天空 链接:juejin.cn/post/684490…
-
-
请求流程
HTTP框架的设计与实现
分层设计
-
与前面对比
应用层(API)设计
-
提供合理的API
- 可理解性
- 简单性
- 冗余性
- 兼容性
- 可测性
- 可见性
中间件设计(Middleware)
-
中间件:又译中间件、中介层,是一类提供系统软件和应用软件之间连接、便于软件各部件之间的沟通的软件,应用软件可以借助中间件在不同的技术架构之间共享信息与资源。中间件位于客户机服务器的操作系统之上,管理着计算资源和网络通信。
-
好的中间件设计:
- 配合Handler实现一个完整的请求处理生命周期
- 拥有预处理逻辑和后处理逻辑
- 可以注册多中间件
- 对上层模块用户逻辑模块易用
-
洋葱模型:
-
核心逻辑与通用逻辑分离
-
适用场景:
- 日志记录、性能统计、安全控制、事务处理、异常处理
-
路由层设计
框架路由实际上是为了URL匹配对应的处理函数(Handler)
-
路由层需要的功能
- 静态路由:/a/b/c
- 参数路由:/a/:id/c、/*all
- 路由修复:/a/b -> /a/b/
- 冲突路由以及路由优先级:/a/b、/:id/c
- 匹配HTTP方法
- 多处理函数:方便添加中间件
-
路由匹配的办法 有:
- map[string]handlers(键值对):只适用于静态路由
- 前缀匹配树
-
匹配HTTP方法 - 路由映射表:
协议层设计
抽象出合适的接口
网络层设计
- BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
- NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
- AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。
如何做设计
- 明确需求:考虑清楚解决什么问题,有哪些需求
- 业界调研:业界都有哪些解决方案可供参考
- 方案权衡:思考不同方案的取舍
- 方案评审:相关同学对不同方案做评审
- 确定开发:确定最合适的方案进行开发
框架优化
网络库优化
-
go net
- 存下所有Header
- 减少系统调用次数
- 能够复用内存
- 能过够多次读取
-
netpoll
- 存下所有Header
- 拷贝出完整的Body
-
不同网络库的优势
- go net : 流式友好,小包性能高
- netpoll:中大包性能高,时延低
-
总结:关键是buffer设计
针对协议优化
-
Headers解析
-
通过Header Key首字母快速筛选掉完全不可能的key
-
解析对应value到独立字段
-
使用byte slice管理对应header储存,方便复用
-
优点
- 核心字段快速解析
- byte slice储存
- 额外储存到成员变量中
-
缺点
- 普通header性能较低
- 没有map结构
-
-
Header key规范化
-
优点
- 超高的转换效率
- 比net.http提高40倍
-
缺点
- 额外的内存开销
- 变更困难
-
-
热点资源池化
-
正常情况下
-
-
RequestContext 与请求一一对应,贯穿一个请求始终,高并发时压力太大
-
-
池化后
-
-
请求来的时候,从池子中取出 RequestContext
-
处理完后将 RequestContext 放回池子里下个请求可以复用,
-
-
优点
- 减少内存分配
- 提高内存复用
- 降低 GC 压力
- 性能提升
-
缺点
- 额外的 Reset 逻辑
- 请求内有效
- 问题定位难度增加
-