本文介绍了当 tcp/udp 服务器的发布速度快于客户端的消耗速度时会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解当服务器发布(通过 tcp、udp 等)的速度快于客户端使用数据时会发生什么.

I am trying to get a handle on what happens when a server publishes (over tcp, udp, etc.) faster than a client can consume the data.

在一个程序中,我知道如果一个队列位于生产者和消费者之间,它会开始变大.如果没有队列,那么生产者根本无法生产任何新东西,直到消费者可以消费(我知道可能会有更多变化).

Within a program I understand that if a queue sits between the producer and the consumer, it will start to get larger. If there is no queue, then the producer simply won't be able to produce anything new, until the consumer can consume (I know there may be many more variations).

我不清楚当数据离开服务器(可能是不同的进程、机器或数据中心)并发送到客户端时会发生什么.如果客户端根本无法足够快地响应传入的数据,假设服务器和消费者非常松散耦合,那么传输中的数据会发生什么?

I am not clear on what happens when data leaves the server (which may be a different process, machine or data center) and is sent to the client. If the client simply can't respond to the incoming data fast enough, assuming the server and the consumer are very loosely coupled, what happens to the in-flight data?

我在哪里可以阅读以获取有关此主题的详细信息?我只需要阅读 TCP/UDP 的底层细节吗?

Where can I read to get details on this topic? Do I just have to read the low level details of TCP/UDP?

谢谢

推荐答案

使用 TCP 有一个 TCP 窗口 用于流量控制.TCP 一次只允许一定数量的数据保持未确认状态.如果服务器生成数据的速度快于客户端消耗数据的速度,则未确认的数据量将增加,直到 TCP 窗口满",此时发送 TCP 堆栈将等待并且不会再发送任何数据,直到客户端确认一些待处理的数据.

With TCP there's a TCP Window which is used for flow control. TCP only allows a certain amount of data to remain unacknowledged at a time. If a server is producing data faster than a client is consuming data then the amount of data that is unacknowledged will increase until the TCP window is 'full' at this point the sending TCP stack will wait and will not send any more data until the client acknowledges some of the data that is pending.

UDP 没有这样的流量控制系统;毕竟这是不可靠的.客户端和服务器上的 UDP 堆栈如果愿意,都可以丢弃数据报,它们之间的所有路由器也是如此.如果您发送的数据报多于链接可以传递给客户端的数据,或者如果链接传递的数据报多于您的客户端代码可以接收的数据报,那么其中一些将被丢弃.除非您在基本 UDP 上构建了某种形式的可靠协议,否则服务器和客户端代码可能永远不会知道.尽管实际上您可能会发现数据报不会被网络堆栈丢弃,并且 NIC 驱动程序只是简单地咀嚼所有可用的非分页池并最终使系统崩溃(请参阅 这篇博文了解更多详情).

With UDP there's no such flow control system; it's unreliable after all. The UDP stacks on both client and server are allowed to drop datagrams if they feel like it, as are all routers between them. If you send more datagrams than the link can deliver to the client or if the link delivers more datagrams than your client code can receive then some of them will get thrown away. The server and client code will likely never know unless you have built some form of reliable protocol over basic UDP. Though actually you may find that datagrams are NOT thrown away by the network stack and that the NIC drivers simply chew up all available non-paged pool and eventually crash the system (see this blog posting for more details).

回到 TCP,您的服务器代码如何处理 TCP 窗口变满取决于您使用的是阻塞 I/O、非阻塞 I/O 还是异步 I/O.

Back with TCP, how your server code deals with the TCP Window becoming full depends on whether you are using blocking I/O, non-blocking I/O or async I/O.

  • 如果您使用阻塞 I/O,那么您的发送调用将阻塞,您的服务器将变慢;实际上,您的服务器现在与您的客户端同步.在客户端收到待处理的数据之前,它不能发送更多数据.

  • If you are using blocking I/O then your send calls will block and your server will slow down; effectively your server is now in lock step with your client. It can't send more data until the client has received the pending data.

如果服务器使用非阻塞 I/O,那么您可能会收到一个错误返回,告诉您调用将被阻塞;您可以做其他事情,但您的服务器需要在以后重新发送数据...

If the server is using non blocking I/O then you'll likely get an error return that tells you that the call would have blocked; you can do other things but your server will need to resend the data at a later date...

如果您使用的是异步 I/O,那么事情可能会更复杂.例如,对于在 Windows 上使用 I/O 完成端口的异步 I/O,您根本不会注意到任何不同.您的重叠发送仍然会被接受,但您可能会注意到它们需要更长的时间才能完成.重叠的发送正在您的服务器计算机上排队,并且正在为您的重叠缓冲区使用内存,并且可能也使用了非分页池".如果您继续发出重叠发送,那么您将面临耗尽非分页池内存或使用可能无限量的内存作为 I/O 缓冲区的风险.因此,使用异步 I/O 和服务器生成数据的速度可能快于其客户端使用数据的速度,您应该编写自己的流控制代码,并使用写入的完成来驱动.我已经在我的博客 这里这里 和我的服务器框架提供了自动为您处理它的代码.

If you're using async I/O then things may be more complex. With async I/O using I/O Completion Ports on Windows, for example, you wont notice anything different at all. Your overlapped sends will still be accepted just fine but you might notice that they are taking longer to complete. The overlapped sends are being queued on your server machine and are using memory for your overlapped buffers and probably using up 'non-paged pool' as well. If you keep issuing overlapped sends then you run the risk of exhausting non-paged pool memory or using a potentially unbounded amount of memory as I/O buffers. Therefore with async I/O and servers that COULD generate data faster than their clients can consume it you should write your own flow control code that you drive using the completions from your writes. I have written about this problem on my blog here and here and my server framework provides code which deals with it automatically for you.

就传输中"的数据而言,双方的 TCP 堆栈将确保数据按预期到达(即按顺序到达且没有任何遗漏),他们将通过在需要时重新发送数据来做到这一点.

As far as the data 'in flight' is concerned the TCP stacks in both peers will ensure that the data arrives as expected (i.e. in order and with nothing missing), they'll do this by resending data as and when required.

这篇关于当 tcp/udp 服务器的发布速度快于客户端的消耗速度时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 05:13