MST

星途 面试题库

面试题:Node.js TCP 服务器性能调优与安全加固

基于 Node.js 创建的 TCP 服务器应用于高并发生产环境,从性能调优的角度,阐述如何利用 Node.js 的特性(如事件循环、非阻塞 I/O 等)以及操作系统资源(如文件描述符限制等)进行深度优化。另外,从安全层面考虑,需要采取哪些措施来防止常见的网络攻击,如 DDoS 攻击、端口扫描等,并说明具体实现方式。
40.8万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

性能调优

  1. 利用事件循环
    • 合理处理回调:确保回调函数执行时间尽可能短,避免在回调中执行长时间阻塞的操作。例如,避免在 I/O 回调中进行大量的 CPU 密集型计算。如果有这类计算,可考虑使用 Worker Threads 将其放到单独线程执行。
    • 优化任务队列:Node.js 的事件循环会依次处理微任务队列和宏任务队列。合理安排任务,尽量将一些不重要的任务延迟执行,避免在主线程事件循环中堆积过多任务,影响高并发处理能力。例如,使用 setImmediate 来延迟执行一些非紧急的任务,它会在当前轮次事件循环的宏任务队列末尾执行。
  2. 非阻塞 I/O
    • 高效使用 Stream:在 TCP 服务器中处理数据读写时,使用 Stream 来处理数据流。Stream 基于事件驱动,以非阻塞方式工作,能够高效处理大量数据。例如,使用 net.Socket 的可读可写流特性,在数据可读时及时处理,而不是一次性读取大量数据导致内存占用过高。可以通过 pipe 方法将可读流直接连接到可写流,实现数据的高效传输,如 readableStream.pipe(writableStream)
    • 连接池管理:对于需要与外部资源(如数据库)交互的情况,建立连接池。在高并发场景下,避免每次请求都创建新的连接,因为创建连接本身是一个 I/O 操作,会消耗资源和时间。使用连接池可以复用已有连接,提高效率。例如,在 Node.js 中操作 MySQL 数据库时,可以使用 mysql2 库的连接池功能。
  3. 操作系统资源
    • 调整文件描述符限制:在高并发场景下,TCP 服务器可能会同时处理大量连接,每个连接都需要一个文件描述符。默认情况下,操作系统对文件描述符数量有限制。可以通过 ulimit -n 命令查看当前文件描述符限制,并通过修改系统配置文件(如 /etc/security/limits.conf)来提高限制。在 Node.js 中,可以在启动脚本中通过 process.setMaxListeners 方法适当增加 EventEmitter 的监听器数量限制,因为每个 TCP 连接可能会触发多个事件。
    • 内存管理优化:合理释放不再使用的内存,避免内存泄漏。在处理大量连接和数据时,及时释放不再使用的缓冲区和对象。例如,当一个 TCP 连接关闭后,确保与之相关的所有资源(如缓冲区、事件监听器等)都被正确释放。可以使用 WeakMap 来存储一些弱引用对象,当对象没有其他强引用时,垃圾回收机制可以自动回收其内存。

安全措施

  1. 防止 DDoS 攻击
    • 流量限制
      • 基于 IP 限制:使用中间件记录每个 IP 的请求频率,例如使用 express-rate-limit 这样的库(虽然通常用于 HTTP 应用,但原理类似)。对于 TCP 服务器,可以自行实现类似逻辑。记录每个 IP 在一定时间内发起的连接数,如果超过设定阈值(如每分钟 100 次连接),则暂时拒绝该 IP 的连接请求一段时间(如 1 分钟)。
      • 基于全局流量限制:监控服务器整体的连接速率,如果超过服务器能够承受的最大连接速率(根据服务器硬件和网络带宽等因素确定),则采取限流措施。可以丢弃新的连接请求或者采用排队机制,在连接数下降后逐步处理排队的请求。
    • SYN 缓存与 Cookie 挑战
      • SYN 缓存:在 TCP 三次握手过程中,服务器接收到 SYN 包后,将连接信息存储在 SYN 缓存中,而不是立即分配大量资源建立完整连接。只有当接收到 ACK 包完成三次握手后,才正式建立连接并分配资源。这样可以防止恶意攻击者通过发送大量 SYN 包耗尽服务器资源。
      • Cookie 挑战:对于新连接请求,服务器发送一个带有特殊 Cookie 的 SYN + ACK 包,客户端必须在后续的 ACK 包中返回该 Cookie。只有返回正确 Cookie 的连接请求才被接受。这样可以有效过滤掉一些自动化的 DDoS 攻击工具,因为它们通常不会处理这种复杂的挑战。
  2. 防止端口扫描
    • 隐藏端口:不要将服务器端口暴露在公网上,如果必须暴露,尽量使用非标准端口(大于 1024 的端口)。同时,在服务器配置中,避免在服务发现协议(如 DNS 等)中公开服务器所使用的端口信息。
    • 端口访问控制:使用防火墙(如 iptables 在 Linux 系统中)限制对服务器端口的访问。只允许来自可信 IP 地址段的连接请求,对于其他 IP 的连接请求直接拒绝。例如,只允许公司内部 IP 段(如 192.168.1.0/24)访问服务器的特定 TCP 端口。
    • 检测异常连接尝试:通过监控系统记录每个端口的连接尝试次数和频率。如果某个端口在短时间内收到大量连接尝试且失败率很高,可能是端口扫描行为。可以在 Node.js 服务器中通过日志记录和分析模块实现对连接尝试的监控,一旦发现异常,及时采取措施,如暂时封禁发起扫描的 IP 地址。