扩展聊天应用——短轮询和长轮询(AJAX, PHP)

时间:2021-02-18 21:06:26

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).
  • HTML5 Web Sockets:没有使用它,因为它不能在所有浏览器中工作(只有chrome)。
  • Flash Sockets: didn't use this because I wanted to eventually support mobile web.
  • Flash socket:没有使用这个,因为我想最终支持移动web。

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)。我应该使用长轮询还是短轮询?我不需要绝对的即时回复时间(对于聊天应用来说“足够好”)。短轮询是否经常有几十万用户要杀了我的服务器?我该怎么做,请帮忙!

3 个解决方案

#1


41  

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.
  • 要保存db的流量和速度响应,请考虑使用内存缓存来存储未发送的消息。您仍然可以将消息持久化到db,内存缓存将仅仅用于查询新消息,以避免每个用户每隔x秒对db的查询。
  • 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.
  • 在不活动的x秒后暂停用户聊天,以停止对服务器的轮询。这就保证了打开窗口的人不会继续产生流量。提供一个简单的“还在吗?”继续聊天。”链接到会话超时,并在超时之前警告用户,以便他们可以延长超时。
  • 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.
  • 我建议从轮询开始,而不是comet/long轮询/套接字。轮询的构建和支持非常简单,并且在短期内可能会很好地扩展。如果你获得了大量的流量,你可以把硬件和负载均衡器扔到这个问题上。整个网络都是基于轮询——大多数都是按比例进行的。有一点是,像comet/long polling/etc这样的替代方案的复杂性是有意义的,但是在额外的开发时间/复杂性被证明是合理的之前,您需要大量的流量。

#2


22  

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.

    为您的客户端提供一个轻量级的端点,该端点具有一些关于聊天会话的上下文、一个新消息挂起、有多少消息等等。如果没有新消息,客户端可以立即更新或不更新。这个端点可以通过http请求提供一个简单的json对象。您可以保证这个状态消息将是一个固定的大小,如果状态的响应没有变化,您就可以将其衰变。看到下一个消息。

  • 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.

    javascript轮询中的一个简单的衰减,如果客户端在一行中多次收到来自服务器的相同响应,那么您可以将轮询增加一个设置的时间,目前您说它是每秒。如果你这样做,你会增加到每2 4 6 8 10秒。一旦服务器的响应发生变化,您就会重置衰退。

Some optimizations to consider;

一些优化考虑;

  • Use a PHP Opcode cache like APC.

    使用PHP操作码缓存,如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.

    优化PHP代码,使其精简、快速。

  • 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.

    检查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.

当需要扩展时,添加一个新的服务器并使用负载均衡器来分发请求。我用过清漆和HAProxy,效果很好,安装起来也不复杂。

#3


1  

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 web sockets的库,但是如果html5不能使用,它又会回到flash sockets上。

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

此外,您还应该放弃php,或者使用python或ruby编写的带有em-websocket的线程套接字服务器对其进行补充。

#1


41  

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.
  • 要保存db的流量和速度响应,请考虑使用内存缓存来存储未发送的消息。您仍然可以将消息持久化到db,内存缓存将仅仅用于查询新消息,以避免每个用户每隔x秒对db的查询。
  • 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.
  • 在不活动的x秒后暂停用户聊天,以停止对服务器的轮询。这就保证了打开窗口的人不会继续产生流量。提供一个简单的“还在吗?”继续聊天。”链接到会话超时,并在超时之前警告用户,以便他们可以延长超时。
  • 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.
  • 我建议从轮询开始,而不是comet/long轮询/套接字。轮询的构建和支持非常简单,并且在短期内可能会很好地扩展。如果你获得了大量的流量,你可以把硬件和负载均衡器扔到这个问题上。整个网络都是基于轮询——大多数都是按比例进行的。有一点是,像comet/long polling/etc这样的替代方案的复杂性是有意义的,但是在额外的开发时间/复杂性被证明是合理的之前,您需要大量的流量。

#2


22  

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.

    为您的客户端提供一个轻量级的端点,该端点具有一些关于聊天会话的上下文、一个新消息挂起、有多少消息等等。如果没有新消息,客户端可以立即更新或不更新。这个端点可以通过http请求提供一个简单的json对象。您可以保证这个状态消息将是一个固定的大小,如果状态的响应没有变化,您就可以将其衰变。看到下一个消息。

  • 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.

    javascript轮询中的一个简单的衰减,如果客户端在一行中多次收到来自服务器的相同响应,那么您可以将轮询增加一个设置的时间,目前您说它是每秒。如果你这样做,你会增加到每2 4 6 8 10秒。一旦服务器的响应发生变化,您就会重置衰退。

Some optimizations to consider;

一些优化考虑;

  • Use a PHP Opcode cache like APC.

    使用PHP操作码缓存,如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.

    优化PHP代码,使其精简、快速。

  • 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.

    检查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.

当需要扩展时,添加一个新的服务器并使用负载均衡器来分发请求。我用过清漆和HAProxy,效果很好,安装起来也不复杂。

#3


1  

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 web sockets的库,但是如果html5不能使用,它又会回到flash sockets上。

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

此外,您还应该放弃php,或者使用python或ruby编写的带有em-websocket的线程套接字服务器对其进行补充。