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

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

如何在短时间内向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带宽
复制全文 生成海报 编程 网络 性能优化 云计算

推荐文章

如何在Vue3中处理全局状态管理?
2024-11-18 19:25:59 +0800 CST
php常用的正则表达式
2024-11-19 03:48:35 +0800 CST
如何在 Vue 3 中使用 TypeScript?
2024-11-18 22:30:18 +0800 CST
PHP 压缩包脚本功能说明
2024-11-19 03:35:29 +0800 CST
H5抖音商城小黄车购物系统
2024-11-19 08:04:29 +0800 CST
55个常用的JavaScript代码段
2024-11-18 22:38:45 +0800 CST
Vue3中如何处理WebSocket通信?
2024-11-19 09:50:58 +0800 CST
MySQL 1364 错误解决办法
2024-11-19 05:07:59 +0800 CST
Nginx 负载均衡
2024-11-19 10:03:14 +0800 CST
Nginx 防盗链配置
2024-11-19 07:52:58 +0800 CST
go发送邮件代码
2024-11-18 18:30:31 +0800 CST
Boost.Asio: 一个美轮美奂的C++库
2024-11-18 23:09:42 +0800 CST
PHP中获取某个月份的天数
2024-11-18 11:28:47 +0800 CST
服务器购买推荐
2024-11-18 23:48:02 +0800 CST
CSS 媒体查询
2024-11-18 13:42:46 +0800 CST
Nginx rewrite 的用法
2024-11-18 22:59:02 +0800 CST
最全面的 `history` 命令指南
2024-11-18 21:32:45 +0800 CST
初学者的 Rust Web 开发指南
2024-11-18 10:51:35 +0800 CST
mysql 计算附近的人
2024-11-18 13:51:11 +0800 CST
WebSQL数据库:HTML5的非标准伴侣
2024-11-18 22:44:20 +0800 CST
JavaScript设计模式:观察者模式
2024-11-19 05:37:50 +0800 CST
imap_open绕过exec禁用的脚本
2024-11-17 05:01:58 +0800 CST
介绍25个常用的正则表达式
2024-11-18 12:43:00 +0800 CST
程序员茄子在线接单