前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TrafficServer http2 代码分析

TrafficServer http2 代码分析

作者头像
byronhe
发布2021-06-25 11:02:26
5780
发布2021-06-25 11:02:26
举报
文章被收录于专栏:Tech Explorer

TrafficServer 是Apache基金会的 HTTP/HTTP2 代理服务器。

TrafficServer 的 HTTP2 部分主要的代码在 :

  1. trafficserver/proxy/http2/HTTP2.h, HTTP2.cc
  2. trafficserver/proxy/http2/Http2Stream.h, Http2Stream.cc
  3. trafficserver/proxy/http2/Http2ClientSession.h, Http2ClientSession.cc
  4. trafficserver/proxy/http2/Http2ConnectionState.h, Http2ConnectionState.cc
  5. trafficserver/proxy/http2/ Http2DependencyTree.h, Http2DependencyTree.cc
  6. trafficserver/proxy/http2/HPACK.h, HPACK.cc
  7. trafficserver/proxy/http2/HuffmanCodec.h, HuffmanCodec.cc

1. trafficserver/proxy/http2/HTTP2.h, HTTP2.cc

10种Frame 的struct定义,解析/序列化函数,HeaderList转换函数,一些常量定义

2. trafficserver/proxy/http2/Http2ClientSession.h, Http2ClientSession.cc

Http2ClientSession 处理 io event 事件,解析 FrameHeader,

调用顺序:

1 2 3 4 5 6 7 8 9 10 11 12

Http2ClientSession::main_event_handler() --> state_read_connection_preface() --> state_start_frame_read() --> state_process_frame_read() 解析出一个完整的Frame --> do_complete_frame_read() --> Http2ConnectionState::main_event_handler(HTTP2_SESSION_EVENT_RECV )

3. trafficserver/proxy/http2/Http2ConnectionState.h, Http2ConnectionState.cc

Http2ConnectionState,对应一个 HTTP2 连接,代码基本等价于 proxygen 的 HTTPSession,主要的成员变量:

1 2 3 4 5 6 7 8 9 10 11

{ 双链表<Http2Stream> //略挫,有个find_stream 用的遍历,改map好点。 Http2ClientSession, HpackHandle 2个, DependencyTree, Http2ConnectionSettingsclient_settings server_settings,连接的几个 Settings 配置项,一个int数组 }

主要的方法:各个 rcv_xxx_frame() 和 send_xxx_frame(0 Http2ConnectionState::main_event_handler(HTTP2_SESSION_EVENT_RECV )里面,解析输入的各种 Frame

  • rcv_data_frame, // HTTP2_FRAME_TYPE_DATA
  • rcv_headers_frame, // HTTP2_FRAME_TYPE_HEADERS
  • rcv_priority_frame, // HTTP2_FRAME_TYPE_PRIORITY
  • rcv_rst_stream_frame, // HTTP2_FRAME_TYPE_RST_STREAM
  • rcv_settings_frame, // HTTP2_FRAME_TYPE_SETTINGS
  • rcv_push_promise_frame, // HTTP2_FRAME_TYPE_PUSH_PROMISE
  • rcv_ping_frame, // HTTP2_FRAME_TYPE_PING
  • rcv_goaway_frame, // HTTP2_FRAME_TYPE_GOAWAY
  • rcv_window_update_frame, // HTTP2_FRAME_TYPE_WINDOW_UPDATE
  • rcv_continuation_frame, // HTTP2_FRAME_TYPE_CONTINUATION

还有发送各类 frame 的接口,send_data_frames()/send_headers_frame() / send_push_promise_frame() / send_rst_stream_frame() 等。

具体地:

rcv_data_frame :

find_stream,然后检查stream的state是不是OPEN/HALF_CLOSE_LOCAL,去除 padding,处理END_STREAM flag,检查本端流量控制 window_size ,保存buffer,更新本地的window,发回 Connection 和 Stream Level 的WindowUpdate Frame。

rcv_headers_frame:

find_stream/create_stream,处理padding,处理PRIORITY flag添加到 PriorityTree 里面,如果 Header Block 结束了(即有END_HEADERS FLAG),那就http2_decode_header_blocks() 做HPACK 解压缩,调用 Http2Stream 处理解析出的HeaderList

rcv_priority_frame:

find_stream,reprioritize,重新调整树。

rcv_rst_stream_frame

rcv_settings_frame:

parse检查收到的各个配置项,更新到client_settings中,并发送SETTINGS_ACK

rcv_push_promise_frame 等

包括 rcv_ping_frame

rcv_goaway_frame:

rcv_window_update_frame

比较简单,略。

rcv_continuation_frame

类似 rcv_headers_frame

send_data_frames_depends_on_priority

取了 DependencyTree的top(),

send_data_frames 等

send_a_data_frame

send_headers_frame

send_push_promise_frame

send_rst_stream_frame

send_settings_frame

send_ping_frame

send_goaway_frame

send_window_update_frame

比较简单,就是检查字段合法性,序列化,然后发送。

4. trafficserver/proxy/http2/Http2Stream.h, Http2Stream.cc

对应实现HTTP2 的Stream,重要的成员变量有:

Http2StreamState _state;//实现IDLE,OPEN,RESERVED,HALF_CLOSE等的切换。

DependencyTree::Node *priority_node;// Priority Tree中的节点指针。

5. trafficserver/proxy/http2/Http2DependencyTree.h, Http2DependencyTree.cc

Http2DependencyTree::Node 表示一个Stream,成员变量有:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

{ bool actived; //是否有输出数据 bool queued; //是否在 actived 队列中 uint32_t id; uint32_t weight; uint32_t point; //queue中的节点按照这个 point 做优先级排序 Node *parent; //父节点 DLL<Node> children; //子节点的双列表 PriorityQueueEntry<Node *> *entry; // PriorityQueue<Node *> *queue; //有输出数据的所有子节点的队列,按point 优先级降序排列 Http2Stream *t; }

Http2DependencyTree 中有个 Node * root 指向 树的根节点。

Http2DependencyTree的主要方法有:

  1. Node *find(uint32_t id); DFS 递归遍历树,查找一个Stream。
  2. Node *add(uint32_t parent_id, uint32_t id, uint32_t weight, bool exclusive, T t); 就是插入 parent 的 children 链表中,兼做 exclusive 处理。
  3. void remove(Node *node); 从parent 的 queue 中移除自己,把自己的 queue 全转给 parent,把自己的 children 全转给 parent
  4. void reprioritize(uint32_t new_parent_id, uint32_t id, bool exclusive); 重排优先级,就是移动节点
  5. Node *top(); 返回整个树中,point 最高的叶子节点。递归实现。
  6. void activate(Node *node); 往上遍历,如果当前节点没有 在 parent 的 queue中,加入
  7. void deactivate(Node *node, uint32_t sent); 从parent 的queue中去除自己。
  8. void update(Node *node, uint32_t sent);

这里使用 Weighted Fair Queue (WFQ) Scheduling 来调度 Stream 之间的优先级。

Http2ConnectionState::send_data_frames_depends_on_priority() 中,是直接取了 树的 top() 节点,

6. trafficserver/proxy/http2/HPACK.h, HPACK.cc

实现 HPACK 压缩/解压缩

7. trafficserver/proxy/http2/HuffmanCodec.h, HuffmanCodec.cc

实现静态的 Huffman 表,接口简单,只有4个函数,,

是实现成 二叉树,相比proxygen估计效率会低一些。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. trafficserver/proxy/http2/HTTP2.h, HTTP2.cc
  • 2. trafficserver/proxy/http2/Http2ClientSession.h, Http2ClientSession.cc
  • 3. trafficserver/proxy/http2/Http2ConnectionState.h, Http2ConnectionState.cc
    • rcv_data_frame :
      • rcv_headers_frame:
        • rcv_priority_frame:
          • rcv_rst_stream_frame
            • rcv_settings_frame:
              • rcv_push_promise_frame 等
                • rcv_continuation_frame
                  • send_data_frames_depends_on_priority
                    • send_data_frames 等
                    • 4. trafficserver/proxy/http2/Http2Stream.h, Http2Stream.cc
                    • 5. trafficserver/proxy/http2/Http2DependencyTree.h, Http2DependencyTree.cc
                    • 6. trafficserver/proxy/http2/HPACK.h, HPACK.cc
                    • 7. trafficserver/proxy/http2/HuffmanCodec.h, HuffmanCodec.cc
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档