缓冲区设置

缓冲区设计

一、简介

在网络通讯中,用户态缓冲区和内核态缓冲区的大小设定对于优化网络性能和确保数据传输可靠性至关重要。下图是网路通讯的内核缓冲区使用情况:
在这里插入图片描述
数据的读写都需要进行系统调用,从用户态切换到内核态去接收数据,结束后需要切换回用户态;
在这里插入图片描述

二、网络数据的传输过程:
  • 发送
    1. 应用程序通过系统调用将用户数据拷贝sk_buff,并放到socket的发送缓冲区中
    2. 网络协议栈从socket法案送缓冲区中取出sk_buffer,并克隆一个新的sk_buffer(用于丢失重传)
    3. 向下依次增加TCP/UDP头部、IP头部、帧头(MAC头)、帧尾,(tcp层进行数据分段、IP层进行数据分片)
    4. 触发软件中断,通知网卡驱动程序有新的网络数据需要发送
    5. 网卡驱动程序从发送队列中取出sk_buffer写到ringbuffer(内存DMA区域)
    6. 网卡发送数据,发送成功后触发硬件中断,释放sk_buffer和ringbuffer没存
    7. 当接收到tcp报文的ack应答后释放sk_buffer
  • 接收
    1. 网卡接收到数据包,通过DMA协处理器将数据写入内存ringbuffer结构中
    2. 网卡向cpu发起硬件中断,cpu收到中断请求,根据中断表查找中断处理函数,进行中断处理
    3. 中断处理函数将屏蔽中断,发起软件中断
    4. 内核ksoftirqd软件中断线程负责软件中断处理,该线程从ringbuffer中逐个取出数据帧到sk_buffer
    5. 从帧头取出ip协议,去掉帧头帧尾
    6. 根据协议五元组找到socket,并将数据取出放到sicket的接收缓冲区中,软件中断处理结束后开启硬件中断
    7. 应用程序通过系统调用将socket中的接收缓冲区的数据拷贝到用户层缓冲区
用户态缓冲区(User-Space Buffer)

用户态缓冲区是指在应用程序地址空间中分配的缓冲区,用于存储待发送或已接收的数据。调整用户态缓冲区的大小可以影响应用程序处理数据的能力,特别是在高吞吐量或低延迟要求的场景中。

  • 在C/C++中,可以通过setsockopt函数来调整TCP或UDP套接字的发送(SO_SNDBUF)和接收(SO_RCVBUF)缓冲区大小。例如:

    1int snd_buff_size = 8192; // 自定义的发送缓冲区大小
    2int rcv_buff_size = 16384; // 自定义的接收缓冲区大小
    3setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &snd_buff_size, sizeof(snd_buff_size));
    4setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcv_buff_size, sizeof(rcv_buff_size));
    
  • 注意,实际设置的缓冲区大小可能会受到操作系统限制,并且可能不是精确设置的值。有时,内核可能会调整至最接近的允许值,通常是用户请求值的两倍。

三、内核态缓冲区(Kernel-Space Buffer)

内核态缓冲区是操作系统内核管理的一部分,用于在网络接口和用户空间之间暂存数据。它的大小直接影响到网络数据包的处理效率,尤其是在网络拥塞或高流量情况下。

  • 对于Linux系统,可以通过修改内核参数来调整某些类型的内核缓冲区大小,例如通过编辑/etc/sysctl.conf文件或使用sysctl命令动态调整。例如,调整网络接收缓冲区的默认最小值和最大值:

    # 动态调整
    sudo sysctl -w net.core.rmem_default=xxxx # 设定默认接收缓冲区大小
    sudo sysctl -w net.core.rmem_max=yyyy    # 设定最大接收缓冲区大小
    
    # 或者永久修改,在/etc/sysctl.conf中添加:
    net.core.rmem_default=xxxx
    net.core.rmem_max=</
### WebSocket 缓冲区配置方法及参数设置 在 Spring Boot 中,WebSocket 的缓冲区大小可以通过调整底层的 TCP/IP 协议栈以及应用层的相关配置来进行优化。以下是关于如何设置 WebSocket 缓冲区的具体说明: #### 一、操作系统层面的缓冲区配置 操作系统的网络协议栈会为每个 socket 提供默认的读写缓冲区大小。这些值通常可以在 `/proc` 文件系统中找到并修改。 - **读取当前缓冲区大小** 可以通过查看 `/proc/sys/net/core/rmem_default` 和 `/proc/sys/net/core/wmem_default` 来获取默认的读写缓冲区大小[^4]。 - **修改缓冲区大小** 修改 `/proc/sys/net/core/rmem_max` 和 `/proc/sys/net/core/wmem_max` 文件可以更改最大允许的读写缓冲区大小。例如: ```bash echo 1048576 > /proc/sys/net/core/rmem_max echo 1048576 > /proc/sys/net/core/wmem_max ``` 上述命令将读写缓冲区的最大值设置为 1 MB。需要注意的是,这种修改仅对当前运行环境有效,重启后可能会恢复到初始状态。 --- #### 二、Spring Boot 应用程序级别的缓冲区配置 除了操作系统层面的配置外,在应用程序级别也可以针对 WebSocket 进行更细粒度的控制。 - **Tomcat 嵌入式服务器缓冲区配置** 如果使用 Tomcat 作为嵌入式容器,则可以通过 `server.tomcat.*` 属性来调整缓冲区大小。例如,在 `application.properties` 或 `application.yml` 文件中添加如下配置: ```properties server.tomcat.max-swallow-size=1048576 # 设置吞吐量上限为 1MB server.tomcat.receive-buffer-size=262144 # 设置接收缓冲区大小为 256KB server.tomcat.send-buffer-size=262144 # 设置发送缓冲区大小为 256KB ``` - **Jetty 嵌入式服务器缓冲区配置** 若使用 Jetty 容器,可通过类似的属性进行配置: ```properties server.jetty.acceptors=2 server.jetty.selectors=2 server.jetty.max-http-post-size=1048576 # HTTP POST 请求的最大尺寸 server.jetty.output-buffer-size=32768 # 输出缓冲区大小 server.jetty.request-header-size=8192 # 请求头缓冲区大小 server.jetty.response-header-size=8192 # 响应头缓冲区大小 ``` --- #### 三、自定义 WebSocket 处理器中的缓冲区管理 如果需要进一步定制化处理逻辑,还可以通过实现自己的 `WebSocketHandler` 并覆盖其行为来手动管理数据流和缓冲区。例如: ```java @Override public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception { if (message instanceof TextMessage) { String payload = ((TextMessage) message).getPayload(); // 手动分片传输大消息体 int chunkSize = 1024; // 每次处理的数据块大小 for (int i = 0; i < payload.length(); i += chunkSize) { int end = Math.min(i + chunkSize, payload.length()); session.sendMessage(new TextMessage(payload.substring(i, end))); } } } ``` 此代码片段展示了如何通过分割大数据包的方式减少单次传输的压力,从而间接影响缓冲区的需求。 --- #### 四、客户端侧的缓冲区管理 对于浏览器端或其他类型的 WebSocket 客户端来说,默认情况下也会有自身的缓冲机制。开发者可以通过 JavaScript 调整某些行为,比如监听 `bufferedAmount` 属性判断是否有未完成的消息等待发送。 ```javascript const ws = new WebSocket('ws://example.com/socket'); ws.onopen = () => { console.log("Connection opened"); let data = "A".repeat(1e6); // 发送超大数据 while (data && ws.bufferedAmount < 1e5) { // 控制每次不超过 100 KB ws.send(data.slice(0, 1e5)); data = data.slice(1e5); } }; ``` 以上脚本实现了逐步发送大量数据的功能,防止一次性占用过多内存资源。 --- ### 总结 为了合理设置 WebSocket 的缓冲区,可以从以下几个方面入手:一是调整操作系统的网络堆栈参数;二是利用 Spring Boot 提供的应用级配置选项;三是编写自定义处理器以适应特定场景下的需求;四是注意客户端的行为模式及其可能带来的性能瓶颈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值