土法炼钢兴趣小组的算法知识备份

现代 Web 协议集成

目录

Libevent 的 evhttp 停留在 HTTP/1.1 时代。面对 HTTP/2 的多路复用和 HTTP/3 (QUIC) 的低延迟需求,我们需要引入第三方协议栈。

1. HTTP/2 集成 (nghttp2)

nghttp2 是 C 语言实现的 HTTP/2 核心库,它只负责协议解析和状态维护,不负责 I/O。这正好与负责 I/O 的 Libevent 互补。

1.1. 架构设计

我们将 bufferevent 作为传输层(Transport Layer)。 * 读数据: 当 bufferevent 读到数据时,将其喂给 nghttp2_session_mem_recv。 * 写数据: 注册 nghttp2send_callback,当协议栈需要发送数据时,调用 bufferevent_write

1.2. ALPN 协商

HTTP/2 通常运行在 TLS 之上。我们需要在 OpenSSL 握手阶段通过 ALPN (Application-Layer Protocol Negotiation) 协商协议。

// OpenSSL 回调
static int alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
                          const unsigned char *in, unsigned int inlen, void *arg) {
    // 优先选择 "h2"
    if (select_protocol(in, inlen, "h2", out, outlen)) {
        return SSL_TLSEXT_ERR_OK;
    }
    return SSL_TLSEXT_ERR_NOACK;
}

// 在 SSL_CTX 中设置
SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, NULL);

2. HTTP/3 & QUIC 集成

QUIC 基于 UDP,这改变了 Libevent 的使用方式。

2.1. UDP 事件循环

我们不再使用 bufferevent(它是为 TCP 流设计的),而是直接使用 event_new 监听 UDP socket 的 EV_READ 事件。

struct event *udp_ev = event_new(base, udp_fd, EV_READ | EV_PERSIST, on_udp_packet, NULL);
event_add(udp_ev, NULL);

2.2. 集成 quiche / ngtcp2

以 Cloudflare 的 quiche 为例: 1. on_udp_packet: recvfrom 读取 UDP 包。 2. Process: 调用 quiche_conn_recv 处理数据包。 3. Send: 调用 quiche_conn_send 获取待发送数据,通过 sendto 发出。 4. Timer: QUIC 极其依赖定时器(重传、ACK)。需要根据 quiche_conn_timeout_as_nanos 设置 Libevent 的定时器。

3. 总结

虽然 Libevent 没有内置现代协议支持,但其灵活的 bufferevent 和事件机制使其成为构建 HTTP/2 / QUIC 服务的绝佳底座。通过集成 nghttp2quiche,我们可以享受到 Reactor 模式带来的高性能,同时拥抱最新的 Web 标准。


上一篇: 05-protocols/evdns.md - 异步 DNS 解析 下一篇: 06-production/ecosystem.md - 生态集成

返回 Libevent 专题索引


By .