javascript 扩展聊天应用程序 - 短轮询与长轮询(AJAX、PHP)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5313641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 16:45:26  来源:igfitidea点击:

Scaling a chat app - short polling vs. long polling (AJAX, PHP)

phpjavascriptajaxsockets

提问by Andy Hin

I run a website where users can chat with each other through the browser (think Facebook chat). What is the best way to handle the live interaction? (Right now I have a poll going every 30 seconds to update online users and new incoming messages, and another poll going on chat pages every second to get new messages.)

我经营一个网站,用户可以通过浏览器相互聊天(想想 Facebook 聊天)。处理实时交互的最佳方式是什么?(现在我每 30 秒进行一次民意调查,以更新在线用户和新传入的消息,并且每秒在聊天页面上进行另一次民意调查以获取新消息。)

Things I've considered:

我考虑过的事情:

  • HTML5 Web Sockets: didn't use this because it doesn't work in all browsers (only chrome).
  • Flash Sockets: didn't use this because I wanted to eventually support mobile web.
  • HTML5 Web Sockets:没有使用它,因为它不适用于所有浏览器(仅 chrome)。
  • Flash Sockets:没有使用这个,因为我想最终支持移动网络。

Right now, I am using short polling because I don't know how scalable AJAX long polling would be. I'm running a VPS server from servint right now (running apache). Should I use long polling or short polling? I don't need absolutely immediate response times (just "good enough" for a chat app). Is short polling this often with a few hundred-thousand users going to kill my server? How do I scale this, please help!

现在,我正在使用短轮询,因为我不知道 AJAX 长轮询的可扩展性如何。我现在正在从 servint 运行 VPS 服务器(运行 apache)。我应该使用长轮询还是短轮询?我不需要绝对即时的响应时间(对于聊天应用程序来说“足够好”)。是不是经常有几十万用户的短轮询会杀死我的服务器?我如何缩放这个,请帮忙!

回答by Cory House

A few notes:

一些注意事项:

  • Polling every second is overkill. The app will still feel very responsive with a few seconds of delay between checks.
  • To save your db's traffic and speed responses, consider using an in memory cache to store undelivered messages. You could still persist messages to the db, the in memory cache would simply be used for queries for new messages to avoid queries to the db every x seconds by each user.
  • Timeout the user's chat after x seconds of inactivity to stop polling to your server. This assures someone leaving a window open won't continue to generate traffic. Offer a simple "Still there? Continue chatting." link for sessions that timeout and warn the user before the timeout so they can extend the timeout.
  • I'd suggest starting out with polling rather than comet/long polling/sockets. Polling is simple to build and support and will likely scale just fine in the short-term. If you get a lot of traffic you can throw hardware and a load balancer at the problem to scale. The entire web is based on polling - polling most certainly scales. There's a point where the complexity of alternatives like comet/long polling/etc make sense, but you need a lot of traffic before the extra development time/complexity are justified.
  • 每秒轮询一次是矫枉过正的。该应用程序仍然会感觉非常灵敏,检查之间会有几秒钟的延迟。
  • 为了节省数据库的流量和速度响应,请考虑使用内存缓存来存储未传递的消息。您仍然可以将消息保存到数据库中,内存缓存将仅用于查询新消息,以避免每个用户每 x 秒查询一次数据库。
  • 在 x 秒不活动后超时用户的聊天以停止轮询到您的服务器。这可以确保打开窗户的人不会继续产生流量。提供一个简单的“还在吗?继续聊天。” 超时会话的链接并在超时之前警告用户,以便他们可以延长超时。
  • 我建议从轮询而不是彗星/长轮询/套接字开始。轮询很容易构建和支持,并且可能会在短期内很好地扩展。如果您获得大量流量,您可以将硬件和负载平衡器用于解决问题以进行扩展。整个网络都基于轮询——轮询无疑是规模化的。在某种程度上,彗星/长轮询/等替代方案的复杂性是有意义的,但在证明额外的开发时间/复杂性之前,您需要大量流量。

回答by Tass Skoudros

This is something everyone did once upon a time before the introduction of cometd and nodejs.

这是在 Cometd 和 nodejs 引入之前每个人都做过的事情。

The issue as I see it is PHP requests on Apache are very expensive. If your chat application checks for messages every second you will find yourself in a situation where Apache does not have enough resources to respond to requests. The other area I think needs improvement is to improve the context of your chat application.

我看到的问题是 Apache 上的 PHP 请求非常昂贵。如果您的聊天应用程序每秒都检查消息,您会发现 Apache 没有足够的资源来响应请求。我认为需要改进的另一个方面是改进聊天应用程序的上下文。

Why does it update every second if not to retrieve new messages? What if there are no messages?

如果不检索新消息,为什么它每秒更新一次?如果没有消息怎么办?

Some techniques you can use;

您可以使用的一些技术;

  • Provide a light-weight endpoint to your clients that has some context about the chat session, is a new message pending, how many messages etc. The client can respond to this by updating immediately or not if there are no new messages. This endpoint can provide a simple json object via http request. You are guaranteed that this status message will be a fixed size and if the response of the status does not change you can decay it. See next message.

  • A simple decay in your javascript polling, if the client receives the same response from the server a few times in a row you can increment the poll by a set time, at present you said it was every second. If you did this you would increment to every 2,4,6,8,10 seconds. As soon as the response from the server changes you reset the decay.

  • 为您的客户端提供一个轻量级端点,该端点具有一些关于聊天会话的上下文、是否有新消息待处理、有多少消息等。如果没有新消息,客户端可以通过立即更新或不更新来对此做出响应。这个端点可以通过 http 请求提供一个简单的 json 对象。您可以保证此状态消息的大小是固定的,如果状态的响应没有改变,您可以衰减它。见下一条消息。

  • javascript 轮询中的一个简单衰减,如果客户端连续几次从服务器收到相同的响应,您可以按设定的时间增加轮询,目前您说的是每秒一次。如果你这样做,你会增加到每 2、4、6、8、10 秒。一旦来自服务器的响应发生变化,您就会重置衰减。

Some optimizations to consider;

一些需要考虑的优化;

  • Use a PHP Opcode cache like APC.

  • Set a low timeout on all requests, you do not want any requests to hang your server.

  • Optimize your PHP code, make it lean and fast.

  • Run some load tests to see what your limits are.

  • Benchmark performance often to make sure your applications is getting faster.

  • Check apache logs for tell tale signs of overall health of the application and response times.

  • 使用像 APC 这样的 PHP 操作码缓存。

  • 为所有请求设置一个较低的超时时间,您不希望任何请求挂起您的服务器。

  • 优化您的 PHP 代码,使其精简且快速。

  • 运行一些负载测试以查看您的限制。

  • 经常对性能进行基准测试,以确保您的应用程序变得更快。

  • 检查 apache 日志以了解应用程序整体健康状况和响应时间的迹象。

When scaling becomes necessary, add a new server and use a load balancer to distribute requests. I have used Varnish and HAProxy with great success, setting them up is not complicated either.

当需要扩展时,添加一个新服务器并使用负载均衡器来分发请求。我已经成功使用 Varnish 和 HAProxy,设置它们也不复杂。

回答by Joseph Le Brech

If i were you i'd pick a library that uses html5 web sockets yet falls back on flash sockets if html5 isn't available, the browser that fall through the crack should be minute.

如果我是你,我会选择一个使用 html5 网络套接字的库,但如果 html5 不可用,则依赖于 Flash 套接字,那么通过破解的浏览器应该是分钟。

Also you should either abandon php or supplement it with a threaded socket server written either in python or ruby with em-websocket.

此外,您应该放弃 php 或使用 em-websocket 用 python 或 ruby​​ 编写的线程套接字服务器补充它。