在TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认。为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。这里就涉及到一个名为Nagle的算法,该算法的目的就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。
TCP_NODELAY就是用于启用或关于Nagle算法。如果要求高实时性,有数据发送时就马上发送,就将该选项设置为true关闭Nagle算法;如果要减少发送次数减少网络交互,就设置为false等累积一定大小后再发送。默认为false。
浅谈tcp_nodelay的作用
今天在用nginx作web缓存的时候,发现在http里加入这样个参数,能有效的提高数据的实时响应性,那就是tcp_nodelay.下面我们来说说tcp_nodelay的原理:
TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,这里我们主要讲TCP_NODELAY.Nagle化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。JohnNagle是Nagle算法的发明人,后者就是用他的名字来命名的,他在1984年首次用这种方法来尝试解决福特汽车公司的网络拥塞问题(欲了解详情请参看IETF RFC 896)。他解决的问题就是所谓的silly window syndrome,中文称“愚蠢窗口症候群”,具体含义是,因为普遍终端应用程序每产生一次击键操作就会发送一个包,而典型情况下一个包会拥有一个字节的数据载荷以及40个字节长的包头,于是产生4000%的过载,很轻易地就能令网络发生拥塞,。Nagle化后来成了一种标准并且立即在因特网上得以实现。它现在已经成为缺省配置了,但在我们看来,有些场合下把这一选项关掉也是合乎需要的。
现在让我们假设某个应用程序发出了一个请求,希望发送小块数据,比如sns游戏中的点击确定按钮。我们可以选择立即发送数据或者等待产生更多的数据然后再一次发送两种策略。如果我们马上发送数据,那么交互性的以及客户/服务器型的应用程序将极大地受益。例如,当我们正在发送一个较短的请求并且等候较大的响应时,相关过载与传输的数据总量相比就会比较低,而且,如果请求立即发出那么响应时间也会快一些。以上操作可以通过设置套接字的TCP_NODELAY选项来完成,这样就禁用了Nagle算法,在nginx中设置tcp_nodelay on,注意放在http标签里。
另外一种情况则需要我们等到数据量达到最大时才通过网络一次发送全部数据,这种数据传输方式有益于大量数据的通信性能,典型的应用就是文件服务器。应用Nagle算法在这种情况下就会产生问题。但是,如果你正在发送大量数据,你可以设置TCP_CORK选项禁用Nagle化,其方式正好同TCP_NODELAY相反(TCP_CORK 和 TCP_NODELAY 是互相排斥的)。下面就让我们仔细分析下其工作原理。
假设应用程序使用sendfile()函数来转移大量数据(nginx里可以设置sendfile on)。应用协议通常要求发送某些信息来预先解释数据,这些信息其实就是报头内容。典型情况下报头很小,而且套接字上设置了TCP_NODELAY。有报头的包将被立即传输,在某些情况下(取决于内部的包计数器),因为这个包成功地被对方收到后需要请求对方确认。这样,大量数据的传输就会被推迟而且产生了不必要的网络流量交换。
但是,如果我们在套接字上设置了TCP_CORK(可以比喻为在管道上插入“塞子”)选项,具有报头的包就会填补大量的数据,所有的数据都根据大小自动地通过包传输出去。当数据传输完成时,最好取消TCP_CORK选项设置给连接“拔去塞子”以便任一部分的帧都能发送出去。这同“塞住”网络连接同等重要。
总而言之,如果你肯定能一起发送多个数据集合(例如HTTP响应的头和正文),那么我们建议你设置TCP_CORK选项,这样在这些数据之间不存在延迟。能极大地有益于WWW、FTP以及文件服务器的性能,同时也简化了你的工作.
最近用了用libsoup库,用它来写个HttpServ玩。结果发现性能不行,竟然比nginx/apache慢了20倍。拿wireshark一看,发现每个TCP回复都要耗时几百毫秒。这就一下子让我想到了Nagle算法(一般的Nagle算法都是延时200ms)。于是下载libsoup的库,看代码,果然没有setsockopt。于是设置了TCP_NODELAY,结果速度一下子就上去了,与nginx相差无几(WEB主要是耗IO,在高并发的时候才能显示出代码优化的好处)。
而这个Nagle算法,在Windows上的效果尤其明显。以前使用GIO中的GSocket,也是如此。
对于初学socket编程的人来说,可能会忘记这里还有个“陷阱”。Nagle算法适用于小包、高延迟的场合,而对于要求交互速度的b/s或c/s就不合适了。socket在创建的时候,默认都是使用Nagle算法的,这会导致交互速度严重下降,所以需要setsockopt函数来设置TCP_NODELAY为1.
不过取消了Nagle算法,就会导致TCP碎片增多,效率可能会降低。所以,这也是要有所取舍的。
相关推荐
SO_REUSEADDR配置 & TCP_NODELAY SO_REUSEADDR配置和TCP_NODELAY是两种重要的网络协议配置选项,分别用于解决TCP连接中的端口重用和数据传输效率问题。 SO_REUSEADDR配置 在TCP连接中,主机A断开连接时,会发送...
tcp_nodelay on; #keepalive_timeout 0; keepalive_timeout 65; gzip on; #设定负载均衡的服务器列表 upstream 127.0.0.1 { #设定负载均衡的服务器列表 #ip_hash; #同一机器在多网情况下,路由...
Rust 的异步 Redis 客户端。弗雷德 Valkey 和 Redis 的异步客户端例子use fred::... config.tcp = TcpConfig { nodelay: Some(true), ..Default::default() }; }) .build()?; client.init().await?; client.on_error
.option(ChannelOption.TCP_NODELAY, true); }); ``` WebClient 的使用 WebClient 的使用可以分为同步和异步两种方式。 同步方式: ```java WebClient client = WebClient.builder() .baseUrl(...
在Netty中,可以通过设置ChannelOption.TCP_NODELAY为true来启用TCP的Nagle算法,优化小包发送。同步通信通常涉及对端确认接收到消息后,本地端才会发送下一个消息。 5. 进阶学习 - **WebSocket和HTTP/2支持**:...
new_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) epoll.register(new_socket.fileno(), select.EPOLLIN) fd_to_socket[new_socket.fileno()] = new_socket ``` 对于其他已连接的客户端套接字,...
这里的参数`["localhost"]`表示连接本地的Memcached服务器,`binary=True`指定使用二进制协议,`tcp_nodelay=True`开启TCP_NODELAY选项,减少网络延迟。 总的来说,pylibmc是一个强大且高效的Python Memcached...
client = pylibmc.Client(["127.0.0.1"], binary=True, behaviors={"tcp_nodelay": True}) client.set("my_key", "my_value") value = client.get("my_key") ``` 这里,我们创建了一个连接到本地Memcached服务器的...
TcpNoDelayMod 我的世界1.7.2、1.7.10和1.8的伪造mod,将TCP_NODELAY设置为true,而不是常规的false。 这样可以减少游戏延迟,并提供更流畅的游戏体验。 在1.8.1及更高版本中不需要此mod,因为minecraft已经进行了...
Socket对象有许多可配置的属性,如`NoDelay`(禁用Nagle算法)、`ReceiveBufferSize`和`SendBufferSize`(设置缓冲区大小),可以根据应用需求调整以优化性能。 7. **示例代码** 服务端示例: ```csharp using ...
b.option(ChannelOption.TCP_NODELAY, true); // 初始化ChannelPipeline b.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ...
在Amoeba配置中,`<property name="tcpNoDelay">true</property>`表示禁用Nagle算法,这样可以确保数据实时发送,提高数据库交互的响应速度。 6. 配置数据库服务器信息:在`amoeba.xml`中还需要配置具体的MySQL...
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); ``` 四、异步Socket编程 在处理大量并发连接时,通常会使用异步Socket编程模型,以避免阻塞主线程。C#.NET提供了BeginConnect、...
tcp_nodelay on; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/...
例如,设置NoDelay为true可以消除小数据包的延迟。 9. **安全性**:在实际应用中,通常会结合SSL/TLS实现安全的网络通信。C#的SslStream类可以与Socket结合使用,提供加密的数据传输。 10. **多线程与并发**:为了...
- `amoeba.xml`配置示例中的`<dbservername="virtualSlave" virtual="true">`标签表示配置了一个虚拟从库,可以实现多主轮询写入和故障切换。 - 其他配置项如`port`、`ipAddress`定义了Amoeba服务监听的端口和IP...
客户端设置套接字选项TCP_NODELAY=true以防止写入小消息时出现多毫秒延迟。 对 1.4.0 的更改 SDK 支持 StreamManager 客户端。 对 1.3.1 的更改 改进的日志级别粒度。 对 1.3.0 的更改 SDK 支持 SecretsMa
`setsockopt()` 还支持许多其他选项,例如 `TCP_NODELAY`(禁用 Nagle 算法)、`IP_TOS`(设置 IP 服务类型)等。这些选项可以根据具体的应用需求来选择使用。 #### 五、注意事项 1. 使用 `setsockopt()` 时,...
client = pylibmc.Client(["127.0.0.1:11211"], binary=True, behaviors={"tcp_nodelay": True}) client.set("key", "value") # 存储键值对 value = client.get("key") # 获取键值 ``` **数据存储与过期策略** ...