综合 如何在短时间内向250万个主机发送5亿个不符合RFC的HTTP/1.1请求

2024-11-18 13:38:35 +0800 CST views 747

如何在短时间内向250万个主机发送5亿个不符合RFC的HTTP/1.1请求

任务背景

我需要在短时间内向250万个主机发送5亿个不符合RFC的HTTP/1.1请求,理想情况下要在几个小时内完成。为此,我深入研究了HTTP/1.1和Go语言的细节,并通过多种方法来优化这个过程,包括利用Kubernetes进行水平扩展,优化代码以充分利用每个CPU核心,甚至修改了Go的HTTP库来加速这一过程。

为什么选择Go?

我选择Go语言,因为它简单易用,具有出色的并发支持,而且速度快。此外,Go语言的学习曲线较低,即使是JS开发者也能轻松上手。这点对于我来说尤其重要,因为我曾尝试过用Rust来实现这一任务,但由于异步编程的复杂性,我选择了更易理解的Go。

5亿个HTTP/1.1请求有多少?

你可能想知道这是多还是少。实际上,这是一个非常庞大的数量级。假设每个请求耗时0.5秒,如果你使用curl从单台机器依次发送这些请求,需要7.9年才能完成。然而,现实情况会更慢,服务器会限制速率,且响应时间可能超过0.5秒。

从数据传输的角度来看,这个量并不算巨大:

  • 5亿个请求 * 1 KB(平均请求大小)≈ 478 GB
  • 5亿个响应 * 5 KB(平均响应大小)≈ 2.33 TB

问题不在于数据量,而在于如何高效地发送这些请求。

HTTP/1.1请求的复杂性

images
发送单个HTTP/1.1请求涉及多个步骤,例如DNS解析、TCP连接、TLS握手、请求构建与发送、响应处理等。每个步骤都可能失败,因此必须准备好处理重试。

即使是在高性能服务器上,解析DNS记录和打开TLS连接也可能耗时160ms左右。对于需要向不同网络中的多个主机发送大量请求的任务,这种延迟是不可接受的。

优化策略

移除不必要的步骤

通过提前解析DNS记录并手动构建HTTP/1.1请求,我消除了请求解析和DNS解析的延迟。此外,我使用了massdns工具来快速解析大量DNS记录,进一步加快了请求速度。

HTTP/1.1发送大炮的设计

我使用多个工作池来处理请求生成、发送和响应处理,每个工作池由并发安全的队列隔离。这样做的好处是,每个组件可以独立扩展,且易于调试和优化。

选择合适的HTTP库

Go语言中的net/http库虽然功能强大,但在性能方面存在不足。我选择了fasthttp库,它是为速度优化的低级HTTP库。通过一些自定义优化,例如跳过请求规范化步骤,我进一步提升了性能。

跳过DNS解析

为了避免每次请求都进行DNS解析,我使用自定义拨号器直接连接到已解析的IP地址。这一优化显著减少了请求的延迟。

优化TLS握手

由于TLS握手消耗了大量的CPU周期,我考虑硬编码密钥来加快这一过程,尽管最终我选择了更易实现的方案。

工作分块

我将250万个主机分成每块200个主机,每个块由一个工作线程处理。这一分块策略平衡了效率和可靠性,确保在请求失败时能够最小化重试的工作量。

Kubernetes扩展

为了完成这一庞大的任务,我使用DigitalOcean上的Kubernetes集群进行扩展。每个Pod可以达到每秒100-400个请求,通过扩展到60个Pod,我在几个小时内完成了向250万个主机发送5亿个HTTP/1.1请求的任务。

结论

最终结果相当令人满意:

  • 每个Pod达到每秒100-400个请求
  • 扩展到60个Pod
  • 在几个小时内完成了任务

这次任务的成功归功于对Go语言和HTTP/1.1的深入理解,以及对工具和架构的有效优化。在下一篇文章中,我会分享更多关于任务结果的细节。

参考链接

  1. @kannthu1
  2. 通配符DNS
  3. massdns
  4. 并发安全队列
  5. fasthttp基准测试
  6. 自定义fasthttp库
  7. DigitalOcean带宽
复制全文 生成海报 编程 网络 性能优化 云计算

推荐文章

Rust 中的所有权机制
2024-11-18 20:54:50 +0800 CST
Vue3中如何处理组件的单元测试?
2024-11-18 15:00:45 +0800 CST
PHP 允许跨域的终极解决办法
2024-11-19 08:12:52 +0800 CST
PHP 唯一卡号生成
2024-11-18 21:24:12 +0800 CST
基于Webman + Vue3中后台框架SaiAdmin
2024-11-19 09:47:53 +0800 CST
Golang 中你应该知道的 Range 知识
2024-11-19 04:01:21 +0800 CST
html文本加载动画
2024-11-19 06:24:21 +0800 CST
PHP 如何输出带微秒的时间
2024-11-18 01:58:41 +0800 CST
Vue3中如何实现状态管理?
2024-11-19 09:40:30 +0800 CST
Golang Sync.Once 使用与原理
2024-11-17 03:53:42 +0800 CST
Go 协程上下文切换的代价
2024-11-19 09:32:28 +0800 CST
PHP解决XSS攻击
2024-11-19 02:17:37 +0800 CST
在 Nginx 中保存并记录 POST 数据
2024-11-19 06:54:06 +0800 CST
js生成器函数
2024-11-18 15:21:08 +0800 CST
Golang在整洁架构中优雅使用事务
2024-11-18 19:26:04 +0800 CST
HTML + CSS 实现微信钱包界面
2024-11-18 14:59:25 +0800 CST
Vue3中如何处理组件间的动画?
2024-11-17 04:54:49 +0800 CST
程序员茄子在线接单