如何利用 send_timeout 在事件循环层面自动熔断慢速客户端响应 (慢速攻击防御)

落静吖_2792

落静吖_2792

2026-05-26

686人浏览

原创

send_timeout并非asyncio原生参数,而是http服务器层对响应发送阶段的超时控制;需通过streamwriter.drain()配合wait_for、aiohttp的write_timeout、uvicorn的--timeout-write或动态速率检测实现慢速客户端熔断。

如何利用 send_timeout 在事件循环层面自动熔断慢速客户端响应 (慢速攻击防御)

send_timeout 并不是 asyncio 的原生参数或标准 API,Python 标准库中 没有 send_timeout 这一事件循环级配置项。你提到的“在事件循环层面自动熔断慢速客户端响应”,实际对应的是 HTTP 服务器层对客户端写入(response send)阶段的超时控制,常见于异步 Web 框架(如 aiohttp、Starlette/FastAPI、Quart)或底层网络库(如 asyncio.StreamWriter),而非事件循环本身。

事件循环(asyncio.EventLoop)不直接管理 HTTP 响应发送超时;它只调度协程、处理 I/O 就绪事件。真正的“慢速客户端防御”需在 协议栈上层实现:当服务端已生成响应但客户端读取极慢(如每秒只收几个字节),服务端需主动中断连接,防止连接长期占用、耗尽文件描述符或内存。

以下是可落地的三类实践方式,覆盖从底层到框架的完整链路:

直接控制 StreamWriter 发送超时(最底层、最灵活)

适用于自定义 TCP/HTTP 服务器(如基于 asyncio.start_server 构建):

import asyncio

async def handle_client(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
    addr = writer.get_extra_info("peername")
    try:
        # 设置单次 write 的超时(非全局,需每次写前设)
        writer.write(b"HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello, World!")
        await asyncio.wait_for(writer.drain(), timeout=5.0)  # 关键:drain() 等待缓冲区清空
    except asyncio.TimeoutError:
        print(f"[SLOW CLIENT] {addr} failed to consume response in time")
        writer.close()
        await writer.wait_closed()
    except Exception as e:
        print(f"[ERROR] {addr}: {e}")
        writer.close()

async def main():
    server = await asyncio.start_server(handle_client, "0.0.0.0", 8080)
    async with server:
        await server.serve_forever()
  • writer.drain() 是关键:它等待内核发送缓冲区有空间,若客户端接收太慢,缓冲区会满,drain() 就会阻塞。
  • asyncio.wait_for(..., timeout=5.0) 对 drain() 施加硬性超时,超时即断连。
  • 此方式可精确控制每个 write + drain 组合的响应窗口,适合防御 Slowloris 类攻击。

在 aiohttp 中启用 client_timeout 和 write_timeout

aiohttp.web 提供了明确的传输层超时配置:

from aiohttp import web

async def handle(request):
    return web.Response(text="OK", content_type="text/plain")

app = web.Application()
app.router.add_get("/", handle)

# 全局写入超时(从响应开始发送起计时)
web.run_app(
    app,
    host="0.0.0.0",
    port=8080,
    # ⚠️ 注意:aiohttp 3.9+ 支持 write_timeout;旧版用 client_timeout(含读+写)
    write_timeout=5,        # 响应体发送总耗时上限(秒)
    keepalive_timeout=10,   # Keep-Alive 连接空闲超时
    shutdown_timeout=3,     # 优雅关闭等待时间
)
  • write_timeout 从 Response.prepare() 开始计时,覆盖整个响应体发送过程。
  • 若客户端接收速率低于阈值(如 send() 会反复阻塞,最终触发超时并关闭连接。
  • 配合 limit=1024*1024(request body 限制)和 client_max_size 可形成完整慢速攻击防护。

FastAPI / Starlette:通过底层 ASGI Server 配置生效

FastAPI 自身不暴露 send_timeout,但其运行依赖 ASGI 服务器(如 uvicorn 或 hypercorn)。防御需在服务器启动参数中设置:

# Uvicorn 示例:强制所有响应写入在 6 秒内完成
uvicorn main:app --host 0.0.0.0 --port 8000 \
  --timeout-keep-alive 5 \
  --timeout-write 6 \
  --limit-concurrency 1000 \
  --limit-max-requests 10000
  • --timeout-write(Uvicorn ≥ 0.29):即 send_timeout 的等效项,单位秒,作用于 ASGI send() 调用。
  • --limit-concurrency 防止慢连接挤占并发槽位。
  • 生产环境强烈建议开启 --proxy-headers 并校验 X-Forwarded-For,避免攻击者绕过反向代理直连。

补充:动态响应速率检测(进阶防御)

仅靠固定超时不够智能。可结合实时速率判断:

class RateLimitedStreamWriter:
    def __init__(self, writer: asyncio.StreamWriter, min_rate_bps=1024):
        self.writer = writer
        self.min_rate_bps = min_rate_bps
        self.start_time = None
        self.bytes_sent = 0

    async def write_and_drain(self, data: bytes):
        if self.start_time is None:
            self.start_time = asyncio.get_event_loop().time()
        self.writer.write(data)
        self.bytes_sent += len(data)
        now = asyncio.get_event_loop().time()
        elapsed = now - self.start_time
        if elapsed > 0 and (self.bytes_sent / elapsed) 
  • 按字节/秒动态评估客户端消费能力,比静态超时更抗扰动。
  • 可嵌入中间件或自定义 Response 类,在框架可控范围内复用。

本质上,“事件循环层面熔断”是误称——真正起效的是 I/O 层(socket send buffer + kernel TCP stack)与 asyncio 协作下的超时调度。只要你在 write → drain() 流程中施加 wait_for,或使用支持 write_timeout 的成熟服务器,就能可靠拦截慢速客户端,无需修改事件循环源码。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
nginx 重启
nginx 重启

nginx重启对于网站的运维来说是非常重要的,根据不同的需求,可以选择简单重启、平滑重启或定时重启等方式。本专题为大家提供nginx重启的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.27

403

5

nginx 配置详解
nginx 配置详解

Nginx的配置是指设置和调整Nginx服务器的行为和功能的过程。通过配置文件,可以定义虚拟主机、HTTP请求处理、反向代理、缓存和负载均衡等功能。Nginx的配置语法简洁而强大,允许管理员根据自己的需要进行灵活的调整。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3507

6

nginx配置详解
nginx配置详解

NGINX与其他服务类似,因为它具有以特定格式编写的基于文本的配置文件。本专题为大家提供nginx配置相关的文章,大家可以免费学习。

2023.08.04

6225

6

tomcat和nginx有哪些区别
tomcat和nginx有哪些区别

tomcat和nginx的区别:1、应用领域;2、性能;3、功能;4、配置;5、安全性;6、扩展性;7、部署复杂性;8、社区支持;9、成本;10、日志管理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

561

5

nginx报404怎么解决
nginx报404怎么解决

当访问 nginx 网页服务器时遇到 404 错误,表明服务器无法找到请求资源,可以通过以下步骤解决:1. 检查文件是否存在且路径正确;2. 检查文件权限并更改为 644 或 755;3. 检查 nginx 配置,确保根目录设置正确、没有冲突配置等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.07.09

1496

5

Nginx报404错误解决方法
Nginx报404错误解决方法

解决方法:只需要加上这段配置:try_files $uri $uri/ /index.html;即可。想了解更多Nginx的相关内容,可以阅读本专题下面的文章。

2024.08.07

3958

3

nginx部署php项目教程汇总
nginx部署php项目教程汇总

本专题整合了nginx部署php项目教程汇总,阅读专题下面的文章了解更多详细内容。

2026.01.13

122

12

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

2026.01.13

477

23

Nginx跨平台安装实操指南:Windows、macOS与Linux环境快速搭建
Nginx跨平台安装实操指南:Windows、macOS与Linux环境快速搭建

本指南详解Nginx在Windows、macOS及Linux系统的安装全流程。涵盖官方包解压、Homebrew一键部署、APT/YUM源配置及Docker容器化方案。无论新手或开发者,均可快速搭建运行环境,掌握跨平台核心指令,为后续配置与调优奠定坚实基础。

2026.03.16

159

12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.7万人学习