Js:
Js:
<script>
function cometConnect(){
$.ajax({
cache:false,
type:"post",
data:'ts='+1,
url: 'Controller/chatting',
async: true,
success: function (arr1) {
$(".page-header").append(arr1);
},
complete:function(){
cometConnect(true);
nerr=false;
},
dataType: "text"
});
}
cometConnect();
</script>
Php:
Php:
public function chatting()
{
while(true)
{
if(memcache_get(new_message))
return new_message;
sleep(0.5);
}
}
Is this a better solution than setting setInterval which connects to the PHP method which returns message if there is any every 1 second (1 sec increases +0.25 every 5 seconds let's say)?
这比设置setInterval更好吗? setInterval连接到PHP方法,如果每1秒就返回一条消息(假设每5秒增加1秒+0.25)?
If I used first solution, I could probably use sleep(0.5) it would give me messages instantly, because php loop is cheap, isn't?
如果我使用第一个解决方案,我可能会使用sleep(0.5),它会立即给我消息,因为php循环很便宜,不是吗?
So, what solution is better (more importantly, which takes less resources?). Because there are going to be hundreds of chats like this.
那么,哪种解决方案更好(更重要的是,需要更少的资源?)因为会有几百次这样的聊天。
Plus, can first solution cause problems? Let's say I would reload a page or I would stop execution every 30 secs so I wouldn't get 502 Bad Gateway.
另外,第一个解决方案会导致问题吗?假设我要重载一个页面或者每30秒停止执行,这样就不会得到502个坏网关。
EDIT: I believe the second solution is better, so I am going to reimplement my site, but I am just curious if this can cause problems to the user or not? Can something not expected happen? First problem I noticed is that you can't go to other page until there is at least one new message.
编辑:我认为第二个解决方案更好,所以我打算重新实现我的站点,但我只是好奇这是否会给用户带来问题?有什么事情是不可能发生的吗?我注意到的第一个问题是,在至少有一条新消息之前,您不能访问其他页面。
5 个解决方案
#1
9
A chat is a one to many communication, while each one of the many can send messages and will receive messages from everybody else.
聊天是许多交流的一种,而每个人都可以发送消息,并接收来自其他人的消息。
These two actions (sending, receiving) happen continuously. So this looks like an endless loop whereas the user can enter into (join the chat) and exit (leave the chat).
这两个动作(发送、接收)是连续发生的。所以这看起来像一个无穷无尽的循环,而用户可以进入(加入聊天)和退出(退出聊天)。
- enter
- 输入
- send message
- 发送消息
- receive message
- 接收消息
- exit
- 退出
So the loop looks like this (pseudo-code) on the client side:
因此,在客户端,循环看起来是这样的(伪代码):
while (userInChat)
{
if (userEnteredMessages)
{
userSendMessages(userEnteredMessages)
}
if (chatNewMessages)
{
displayMessages(chatNewMessages)
}
}
As you already note in your question, the problem is in implementing such a kind of chat for a website.
正如您在您的问题中已经注意到的,问题是在为一个网站实现这种类型的聊天。
To implement such a "loop" for a website, you are first of all facing the situation that you don't want to have an actual loop here. As long as the user is in chat, it would run and run and run. So you want to distribute the execution of the loop over time.
要为网站实现这样的“循环”,首先要面对的情况是,您不想在这里有一个实际的循环。只要用户在聊天,它就会运行、运行和运行。所以你想要分配循环执行的时间。
To do this, you can convert it into a collection of event functions:
为此,您可以将其转换为事件函数集合:
ChatClient
{
function onEnter()
{
}
function onUserInput(messages)
{
sendMessages = send(messages)
display(sendMessages)
}
function onReceive(messages)
{
display(messages)
}
function onExit()
{
}
}
It's now possible to trigger events instead of having a loop. Only left is the implementation to trigger these events over time, but for the moment this is not really interesting because it would be dependent to how the chat data exchange is actually implemented.
现在可以触发事件而不是循环。随着时间的推移,只有实现触发这些事件,但目前还不是很有趣,因为它将取决于聊天数据交换的实际实现方式。
There always is a remote point where a chat client is (somehow) connected to to send it's own messages and to receive new messages from.
总是有一个远程的点,聊天客户端(以某种方式)连接到发送自己的消息和接收新消息。
This is some sort of a stream of chat messages. Again this looks like a loop, but infact it's a stream. Like in the chat clients loop, at some point in time it hooks onto the stream and will send input (write) and receive output (read) from that stream.
这是一些聊天信息。这看起来像一个循环,但实际上它是一个流。就像在聊天客户端循环中一样,在某些时候,它会挂钩到流中,并从流中发送输入(写)和接收输出(读)。
This is already visible in the ChatClient pseudo code above, there is an event when the user inputs one or multiple messages which then will be send (written). And read messages will be available in the onReceive event function.
这在上面的ChatClient伪代码中已经可见,当用户输入一个或多个消息时,将会发送(写入)。读消息将在onReceive事件函数中可用。
As the stream is data in order, there needs to be order. As this is all event based and multiple clients are available, this needs some dedicated handling. As order is relative, it will only work in it's context. The context could be the time (one message came before another message), but if the chat client has another clock as the server or another client, we can't use the existing clock as time-source for the order of messages, as it normally differs between computers in a WAN.
由于流是按顺序排列的数据,所以需要顺序。由于这是基于事件的,并且有多个客户端可用,因此需要一些专门的处理。由于顺序是相对的,它只在它的上下文中起作用。上下文可能是时间(一个消息在另一个消息之前出现),但是如果聊天客户端有另一个时钟作为服务器或另一个客户端,我们不能使用现有的时钟作为消息顺序的时间源,因为它通常在WAN中不同于计算机。
Instead you create your own time to line-up all messages. With a shared time across all clients and servers an ordered stream can be implemented. This can be easily done by just numbering the messages in a central place. Luckily your chat has a central place, the server.
相反,你可以创建自己的时间来排列所有的信息。通过在所有客户端和服务器上共享时间,可以实现有序流。只需在中心位置对消息进行编号,就可以轻松做到这一点。幸运的是,您的聊天有一个中心位置——服务器。
The message stream starts with the first message and ends with the last one. So what you simply do is to give the first message the number 1 and then each new message will get the next higher number. Let's call it the message ID.
消息流以第一个消息开始,以最后一个消息结束。所以你要做的就是给第一个消息一个数字,然后每个新消息都会得到下一个更高的数字。我们称它为消息ID。
So still regardless which server technology you'll be using, the chat knows to type of messages: Messages with an ID and messages without an ID. This also represents the status of a message: either not part or part of the stream.
因此,无论您将使用哪种服务器技术,聊天都知道要输入消息:带有ID的消息和没有ID的消息。
Not stream associated messages are those that the user has already entered but which have not been send to the server already. While the server receives the "free" messages, it can put them into the stream by assigning the ID:
不是流关联消息是用户已经输入但尚未发送到服务器的消息。当服务器接收到“free”消息时,它可以通过分配ID将它们放入流中:
function onUserInput(messages)
{
sendMessages = send(messages)
display(sendMessages)
}
As this pseudo code example shows, this is what is happening here. The onUserInput event get's messages that are not part of the stream yet. The sendMessages routine will return their streamed representation which are then displayed.
正如这个伪代码示例所示,这就是这里正在发生的事情。onUserInput事件get的消息还不是流的一部分。sendmessage例程将返回流表示,然后显示流表示。
The display routine then is able to display messages in their stream order.
然后,显示例程可以按照消息流的顺序显示消息。
So still regardless how the client/server communication is implemented, with such a structure you can actually roughly handle a message based chat system and de-couple it from underlying technologies.
因此,不管客户端/服务器通信是如何实现的,通过这种结构,您实际上可以大致地处理基于消息的聊天系统,并将其与底层技术分离。
The only thing the server needs to do is to take the messages, gives each message an ID and return these IDs. The assignment of the ID is normally done when the server stores the messages into it's database. A good database takes care to number messages properly, so there is not much to do.
服务器需要做的唯一一件事是获取消息,给每个消息一个ID并返回这些ID。当服务器将消息存储到它的数据库中时,通常会完成ID的分配。一个好的数据库要注意正确地对消息进行编号,所以没有多少事情要做。
The other interaction is to read new messages from the server. To do this over network effectively, the client tells the server from which message on it likes to read from. The server will then pass the messages since that time (ID) to the client.
另一个交互是从服务器读取新消息。为了在网络上有效地做到这一点,客户端告诉服务器它喜欢从哪个消息中读取消息。然后,服务器将把消息从那个时间(ID)传递给客户机。
As this shows, from the "endless" loop in the beginning it's now turned into an event based system with remote calls. As remote calls are expensive, it is better to make them able to transfer much data with one connection. Part of that is already in the pseudo code as it's possible to send one or multiple messages to the server and to receive zero or more messages from the server at once.
正如这显示的,从一开始的“无尽”循环中,它现在变成了一个基于事件的远程调用系统。由于远程调用很昂贵,所以最好让它们能够通过一个连接传输大量数据。其中的一部分已经在伪代码中,因为可以向服务器发送一个或多个消息,同时从服务器接收零或更多的消息。
The ideal implementation would be to have one connection to the server that allows to read and write messages to it in full-duplex. However no such technology exists yet in javascript. These things are under development with Websockets and Webstream APIs and the like but for the moment let's take things simple and look what we have: stateless HTTP requests, some PHP on the server and a MySQL database.
理想的实现是有一个到服务器的连接,允许在全双工状态下读取和写入消息。然而,javascript中还没有这种技术。这些东西都在开发Websockets和Webstream api之类的东西,现在让我们简单地看看我们有什么:无状态HTTP请求,服务器上的PHP和MySQL数据库。
The message stream can be represented in a database table that has an auto-incrementing unique key for the ID and other fields to store the message.
消息流可以在一个数据库表中表示,该数据库表具有一个自动递增的唯一键,用于存放消息的ID和其他字段。
The write transaction script will just connect to the database, insert the message(s) and return the IDs. That's a very common operation and it should be fast (mysql has a sort of memcache bridge which should make the store operation even more fast and convenient).
写事务脚本将只连接到数据库,插入消息并返回id。这是一个非常常见的操作,它应该是快速的(mysql有一种memcache桥,它可以使存储操作更加快捷和方便)。
The read transaction script is equally simple, it will just read all messages with an ID higher than passed to it and return it to the client.
读事务脚本同样简单,它只需读取所有ID高于传递给它的消息并将其返回给客户端。
Keep these scripts as simple as possible and optimize the read/write time to the store, so they can execute fast and you're done even with chatting over plain HTTP.
让这些脚本尽可能简单,并优化存储的读/写时间,这样它们就可以快速执行,您甚至可以通过普通的HTTP进行聊天。
Still your webserver and the overall internet connection might not be fast enough (although there is keep-alive).
不过,你的网络服务器和整个互联网连接可能还不够快(尽管还有keepalive)。
However, HTTP should be good enough for the moment to test if you chat system is actually working without any loops, not client, nor server side.
但是,如果聊天系统实际上没有任何循环(而不是客户端或服务器端),HTTP应该足够好,可以测试一下。
It's also good to keep servers dead simple, because each client relies on them, so they should just do their work and that's it.
保持服务器的简单性也很好,因为每个客户机都依赖于它们,所以它们应该只做自己的工作,仅此而已。
You can at any time change the server (or offer different type of servers) that can interact with your chat client by giving the chat client different implementations of the send and receive functions. E.g. I see in your question that you're using comet, this should work as well, it's probably easy to directly implement the server for comet.
您可以随时更改服务器(或提供不同类型的服务器),通过向聊天客户机提供发送和接收功能的不同实现,可以与聊天客户机进行交互。我在你的问题中看到你正在使用comet,这也应该可以,直接为comet实现服务器很容易。
If in the future websockets are more accessible (which might never be the case because of security considerations), you can offer another type of server for websockets as well. As long as the data-structure of the stream is intact, this will work with different type of servers next to each other. The database will take care of the congruency.
如果未来的websockets更容易访问(由于安全考虑,这可能永远不会发生),你也可以为websockets提供另一种类型的服务器。只要流的数据结构是完整的,这将与相邻的不同类型的服务器一起工作。数据库将负责一致性。
Hope this is helpful.
希望这是有帮助的。
Just as an additional note: HTML5 offers something called Stream Updates with Server-Sent Events with an online demo and PHP/JS sources. The HTML 5 feature offers already an event object in javascript which could be used to create an exemplary chat client transport implementation.
还有一点要注意的是:HTML5提供了一种名为流更新的功能,可以使用服务器发送的事件进行在线演示和PHP/JS源代码。HTML 5特性提供了javascript中的一个事件对象,可以用来创建一个示例性的聊天客户端传输实现。
#2
5
I wrote a blog post about how I had to handle a similar problem (using node.js, but the principles apply). http://j-query.blogspot.com/2011/11/strategies-for-scaling-real-time-web.html
我写了一篇关于如何处理类似问题的博客文章(使用node)。但原则是适用的)。http://j-query.blogspot.com/2011/11/strategies-for-scaling-real-time-web.html
My suggestion is, if it's going to be big either a) you need to cache like crazy on your web server layer, which probably means your AJAX call needs to have a timestamp on it or b) use something like socket.io, which is built for scaling real-time web apps and has built-in support for channels.
我的建议是,如果它将是大的a)你需要疯狂地在你的web服务器层上缓存,这可能意味着你的AJAX调用需要有一个时间戳或者b)使用socket之类的东西。io是用于扩展实时web应用程序的,内置了对通道的支持。
#3
5
Infinite loops in php can and will use 100% of your CPU. Sleep functions will fix that problem. However, you probably don't want to have a separate HTTP process running all the time for every client that is connected to your server because you'll run out of connections. You could just have one php process that looks at all inbound messages and routes them to the right person as they come in. This process could be launched from a cron job once a minute. I've written this type of thing many times and it works like a charm. Note: Make sure you don't run the process if it's already running or you will run into multiprocessing problems (like getting double messages). In other words, you need to make the process thread safe.
php中的无限循环可以并将使用100%的CPU。睡眠功能将解决这个问题。但是,您可能不希望在连接到服务器的每个客户机上始终运行一个单独的HTTP进程,因为您将耗尽连接。您可以使用一个php进程来查看所有入站消息,并在它们进入时将它们路由到正确的人。这个过程可以每分钟从cron任务启动一次。我写过很多这样的东西,它就像一个咒语。注意:确保在已经运行的过程中不运行该进程,否则将会遇到多处理问题(比如获得双重消息)。换句话说,您需要使进程线程安全。
If you want to get real time chatting, then you might want to take a look at StreamHub which opens a full duplex connection to the client's browser.
如果您想要实时聊天,那么您可能想要看一下StreamHub,它打开了客户端浏览器的全双工连接。
#4
5
It's not a PHP or jQuery task now. Node.js! There is socket.io, which means WebSockets.
它现在不是PHP或jQuery任务。node . js !套接字。io,这意味着WebSockets。
I'll explain why node.js is better. I have a task to refresh on-page markers every, for example, 10 seconds. I've done it with the first method. When the persistent users count come to 200. Http server and php were in trouble. There were a lot of requests which was unnesessary.
我将解释为什么节点。js更好。我有一个任务来刷新页面标记,例如,10秒。我用第一种方法做了。当持续用户计数达到200时。Http服务器和php有问题。有很多要求是不需要的。
Whats give you Node.js:
什么给你node . js:
- Creating separate rooms for chats (here)
- 创建单独的聊天室(这里)
- Sends data, only for those who has updates (for example, if I do not have any new message my refresh will be blocked when there will be selection from database)
- 发送数据,只针对那些有更新的人(例如,如果我没有任何新消息,当从数据库中选择时,我的刷新将被阻塞)
- You run 1 query to the DB per 0.5 second, no matter how much users there are
- 无论有多少用户,每0.5秒运行1个查询到DB
Just look into Node.js and Socket.io. This solution help me with a great boost.
只考虑节点。js和socket . io。这个解决方案对我有很大的帮助。
#5
2
First off, ask yourself if it's necessary to update the chat frequently. What type of chats will be happening? Is it real-time? Simple Q&A? Tech support? Etc. In all but the real-time chat cases, you will be better off using a long polling JS-based design, because instantaneous responses are not that important. If this is for real-time chats, then you should consider a Gmail-like design whereby you keep an XHR open and push messages back to the client as they are received. If connection resources are a concern, you can get by using long polling with a very brief interval (ex. 5-10 seconds).
首先,问问自己是否有必要经常更新聊天记录。什么样的聊天会发生?它是实时的吗?简单的问答吗?技术支持?等等。在除了实时聊天的情况之外的所有情况下,最好使用基于jsp的长轮询设计,因为即时响应不是那么重要。如果这是用于实时聊天,那么您应该考虑一个类似gmail的设计,在接收到消息时打开XHR,并将消息推送回客户机。如果关心连接资源,可以使用长轮询,间隔很短(例如5-10秒)。
#1
9
A chat is a one to many communication, while each one of the many can send messages and will receive messages from everybody else.
聊天是许多交流的一种,而每个人都可以发送消息,并接收来自其他人的消息。
These two actions (sending, receiving) happen continuously. So this looks like an endless loop whereas the user can enter into (join the chat) and exit (leave the chat).
这两个动作(发送、接收)是连续发生的。所以这看起来像一个无穷无尽的循环,而用户可以进入(加入聊天)和退出(退出聊天)。
- enter
- 输入
- send message
- 发送消息
- receive message
- 接收消息
- exit
- 退出
So the loop looks like this (pseudo-code) on the client side:
因此,在客户端,循环看起来是这样的(伪代码):
while (userInChat)
{
if (userEnteredMessages)
{
userSendMessages(userEnteredMessages)
}
if (chatNewMessages)
{
displayMessages(chatNewMessages)
}
}
As you already note in your question, the problem is in implementing such a kind of chat for a website.
正如您在您的问题中已经注意到的,问题是在为一个网站实现这种类型的聊天。
To implement such a "loop" for a website, you are first of all facing the situation that you don't want to have an actual loop here. As long as the user is in chat, it would run and run and run. So you want to distribute the execution of the loop over time.
要为网站实现这样的“循环”,首先要面对的情况是,您不想在这里有一个实际的循环。只要用户在聊天,它就会运行、运行和运行。所以你想要分配循环执行的时间。
To do this, you can convert it into a collection of event functions:
为此,您可以将其转换为事件函数集合:
ChatClient
{
function onEnter()
{
}
function onUserInput(messages)
{
sendMessages = send(messages)
display(sendMessages)
}
function onReceive(messages)
{
display(messages)
}
function onExit()
{
}
}
It's now possible to trigger events instead of having a loop. Only left is the implementation to trigger these events over time, but for the moment this is not really interesting because it would be dependent to how the chat data exchange is actually implemented.
现在可以触发事件而不是循环。随着时间的推移,只有实现触发这些事件,但目前还不是很有趣,因为它将取决于聊天数据交换的实际实现方式。
There always is a remote point where a chat client is (somehow) connected to to send it's own messages and to receive new messages from.
总是有一个远程的点,聊天客户端(以某种方式)连接到发送自己的消息和接收新消息。
This is some sort of a stream of chat messages. Again this looks like a loop, but infact it's a stream. Like in the chat clients loop, at some point in time it hooks onto the stream and will send input (write) and receive output (read) from that stream.
这是一些聊天信息。这看起来像一个循环,但实际上它是一个流。就像在聊天客户端循环中一样,在某些时候,它会挂钩到流中,并从流中发送输入(写)和接收输出(读)。
This is already visible in the ChatClient pseudo code above, there is an event when the user inputs one or multiple messages which then will be send (written). And read messages will be available in the onReceive event function.
这在上面的ChatClient伪代码中已经可见,当用户输入一个或多个消息时,将会发送(写入)。读消息将在onReceive事件函数中可用。
As the stream is data in order, there needs to be order. As this is all event based and multiple clients are available, this needs some dedicated handling. As order is relative, it will only work in it's context. The context could be the time (one message came before another message), but if the chat client has another clock as the server or another client, we can't use the existing clock as time-source for the order of messages, as it normally differs between computers in a WAN.
由于流是按顺序排列的数据,所以需要顺序。由于这是基于事件的,并且有多个客户端可用,因此需要一些专门的处理。由于顺序是相对的,它只在它的上下文中起作用。上下文可能是时间(一个消息在另一个消息之前出现),但是如果聊天客户端有另一个时钟作为服务器或另一个客户端,我们不能使用现有的时钟作为消息顺序的时间源,因为它通常在WAN中不同于计算机。
Instead you create your own time to line-up all messages. With a shared time across all clients and servers an ordered stream can be implemented. This can be easily done by just numbering the messages in a central place. Luckily your chat has a central place, the server.
相反,你可以创建自己的时间来排列所有的信息。通过在所有客户端和服务器上共享时间,可以实现有序流。只需在中心位置对消息进行编号,就可以轻松做到这一点。幸运的是,您的聊天有一个中心位置——服务器。
The message stream starts with the first message and ends with the last one. So what you simply do is to give the first message the number 1 and then each new message will get the next higher number. Let's call it the message ID.
消息流以第一个消息开始,以最后一个消息结束。所以你要做的就是给第一个消息一个数字,然后每个新消息都会得到下一个更高的数字。我们称它为消息ID。
So still regardless which server technology you'll be using, the chat knows to type of messages: Messages with an ID and messages without an ID. This also represents the status of a message: either not part or part of the stream.
因此,无论您将使用哪种服务器技术,聊天都知道要输入消息:带有ID的消息和没有ID的消息。
Not stream associated messages are those that the user has already entered but which have not been send to the server already. While the server receives the "free" messages, it can put them into the stream by assigning the ID:
不是流关联消息是用户已经输入但尚未发送到服务器的消息。当服务器接收到“free”消息时,它可以通过分配ID将它们放入流中:
function onUserInput(messages)
{
sendMessages = send(messages)
display(sendMessages)
}
As this pseudo code example shows, this is what is happening here. The onUserInput event get's messages that are not part of the stream yet. The sendMessages routine will return their streamed representation which are then displayed.
正如这个伪代码示例所示,这就是这里正在发生的事情。onUserInput事件get的消息还不是流的一部分。sendmessage例程将返回流表示,然后显示流表示。
The display routine then is able to display messages in their stream order.
然后,显示例程可以按照消息流的顺序显示消息。
So still regardless how the client/server communication is implemented, with such a structure you can actually roughly handle a message based chat system and de-couple it from underlying technologies.
因此,不管客户端/服务器通信是如何实现的,通过这种结构,您实际上可以大致地处理基于消息的聊天系统,并将其与底层技术分离。
The only thing the server needs to do is to take the messages, gives each message an ID and return these IDs. The assignment of the ID is normally done when the server stores the messages into it's database. A good database takes care to number messages properly, so there is not much to do.
服务器需要做的唯一一件事是获取消息,给每个消息一个ID并返回这些ID。当服务器将消息存储到它的数据库中时,通常会完成ID的分配。一个好的数据库要注意正确地对消息进行编号,所以没有多少事情要做。
The other interaction is to read new messages from the server. To do this over network effectively, the client tells the server from which message on it likes to read from. The server will then pass the messages since that time (ID) to the client.
另一个交互是从服务器读取新消息。为了在网络上有效地做到这一点,客户端告诉服务器它喜欢从哪个消息中读取消息。然后,服务器将把消息从那个时间(ID)传递给客户机。
As this shows, from the "endless" loop in the beginning it's now turned into an event based system with remote calls. As remote calls are expensive, it is better to make them able to transfer much data with one connection. Part of that is already in the pseudo code as it's possible to send one or multiple messages to the server and to receive zero or more messages from the server at once.
正如这显示的,从一开始的“无尽”循环中,它现在变成了一个基于事件的远程调用系统。由于远程调用很昂贵,所以最好让它们能够通过一个连接传输大量数据。其中的一部分已经在伪代码中,因为可以向服务器发送一个或多个消息,同时从服务器接收零或更多的消息。
The ideal implementation would be to have one connection to the server that allows to read and write messages to it in full-duplex. However no such technology exists yet in javascript. These things are under development with Websockets and Webstream APIs and the like but for the moment let's take things simple and look what we have: stateless HTTP requests, some PHP on the server and a MySQL database.
理想的实现是有一个到服务器的连接,允许在全双工状态下读取和写入消息。然而,javascript中还没有这种技术。这些东西都在开发Websockets和Webstream api之类的东西,现在让我们简单地看看我们有什么:无状态HTTP请求,服务器上的PHP和MySQL数据库。
The message stream can be represented in a database table that has an auto-incrementing unique key for the ID and other fields to store the message.
消息流可以在一个数据库表中表示,该数据库表具有一个自动递增的唯一键,用于存放消息的ID和其他字段。
The write transaction script will just connect to the database, insert the message(s) and return the IDs. That's a very common operation and it should be fast (mysql has a sort of memcache bridge which should make the store operation even more fast and convenient).
写事务脚本将只连接到数据库,插入消息并返回id。这是一个非常常见的操作,它应该是快速的(mysql有一种memcache桥,它可以使存储操作更加快捷和方便)。
The read transaction script is equally simple, it will just read all messages with an ID higher than passed to it and return it to the client.
读事务脚本同样简单,它只需读取所有ID高于传递给它的消息并将其返回给客户端。
Keep these scripts as simple as possible and optimize the read/write time to the store, so they can execute fast and you're done even with chatting over plain HTTP.
让这些脚本尽可能简单,并优化存储的读/写时间,这样它们就可以快速执行,您甚至可以通过普通的HTTP进行聊天。
Still your webserver and the overall internet connection might not be fast enough (although there is keep-alive).
不过,你的网络服务器和整个互联网连接可能还不够快(尽管还有keepalive)。
However, HTTP should be good enough for the moment to test if you chat system is actually working without any loops, not client, nor server side.
但是,如果聊天系统实际上没有任何循环(而不是客户端或服务器端),HTTP应该足够好,可以测试一下。
It's also good to keep servers dead simple, because each client relies on them, so they should just do their work and that's it.
保持服务器的简单性也很好,因为每个客户机都依赖于它们,所以它们应该只做自己的工作,仅此而已。
You can at any time change the server (or offer different type of servers) that can interact with your chat client by giving the chat client different implementations of the send and receive functions. E.g. I see in your question that you're using comet, this should work as well, it's probably easy to directly implement the server for comet.
您可以随时更改服务器(或提供不同类型的服务器),通过向聊天客户机提供发送和接收功能的不同实现,可以与聊天客户机进行交互。我在你的问题中看到你正在使用comet,这也应该可以,直接为comet实现服务器很容易。
If in the future websockets are more accessible (which might never be the case because of security considerations), you can offer another type of server for websockets as well. As long as the data-structure of the stream is intact, this will work with different type of servers next to each other. The database will take care of the congruency.
如果未来的websockets更容易访问(由于安全考虑,这可能永远不会发生),你也可以为websockets提供另一种类型的服务器。只要流的数据结构是完整的,这将与相邻的不同类型的服务器一起工作。数据库将负责一致性。
Hope this is helpful.
希望这是有帮助的。
Just as an additional note: HTML5 offers something called Stream Updates with Server-Sent Events with an online demo and PHP/JS sources. The HTML 5 feature offers already an event object in javascript which could be used to create an exemplary chat client transport implementation.
还有一点要注意的是:HTML5提供了一种名为流更新的功能,可以使用服务器发送的事件进行在线演示和PHP/JS源代码。HTML 5特性提供了javascript中的一个事件对象,可以用来创建一个示例性的聊天客户端传输实现。
#2
5
I wrote a blog post about how I had to handle a similar problem (using node.js, but the principles apply). http://j-query.blogspot.com/2011/11/strategies-for-scaling-real-time-web.html
我写了一篇关于如何处理类似问题的博客文章(使用node)。但原则是适用的)。http://j-query.blogspot.com/2011/11/strategies-for-scaling-real-time-web.html
My suggestion is, if it's going to be big either a) you need to cache like crazy on your web server layer, which probably means your AJAX call needs to have a timestamp on it or b) use something like socket.io, which is built for scaling real-time web apps and has built-in support for channels.
我的建议是,如果它将是大的a)你需要疯狂地在你的web服务器层上缓存,这可能意味着你的AJAX调用需要有一个时间戳或者b)使用socket之类的东西。io是用于扩展实时web应用程序的,内置了对通道的支持。
#3
5
Infinite loops in php can and will use 100% of your CPU. Sleep functions will fix that problem. However, you probably don't want to have a separate HTTP process running all the time for every client that is connected to your server because you'll run out of connections. You could just have one php process that looks at all inbound messages and routes them to the right person as they come in. This process could be launched from a cron job once a minute. I've written this type of thing many times and it works like a charm. Note: Make sure you don't run the process if it's already running or you will run into multiprocessing problems (like getting double messages). In other words, you need to make the process thread safe.
php中的无限循环可以并将使用100%的CPU。睡眠功能将解决这个问题。但是,您可能不希望在连接到服务器的每个客户机上始终运行一个单独的HTTP进程,因为您将耗尽连接。您可以使用一个php进程来查看所有入站消息,并在它们进入时将它们路由到正确的人。这个过程可以每分钟从cron任务启动一次。我写过很多这样的东西,它就像一个咒语。注意:确保在已经运行的过程中不运行该进程,否则将会遇到多处理问题(比如获得双重消息)。换句话说,您需要使进程线程安全。
If you want to get real time chatting, then you might want to take a look at StreamHub which opens a full duplex connection to the client's browser.
如果您想要实时聊天,那么您可能想要看一下StreamHub,它打开了客户端浏览器的全双工连接。
#4
5
It's not a PHP or jQuery task now. Node.js! There is socket.io, which means WebSockets.
它现在不是PHP或jQuery任务。node . js !套接字。io,这意味着WebSockets。
I'll explain why node.js is better. I have a task to refresh on-page markers every, for example, 10 seconds. I've done it with the first method. When the persistent users count come to 200. Http server and php were in trouble. There were a lot of requests which was unnesessary.
我将解释为什么节点。js更好。我有一个任务来刷新页面标记,例如,10秒。我用第一种方法做了。当持续用户计数达到200时。Http服务器和php有问题。有很多要求是不需要的。
Whats give you Node.js:
什么给你node . js:
- Creating separate rooms for chats (here)
- 创建单独的聊天室(这里)
- Sends data, only for those who has updates (for example, if I do not have any new message my refresh will be blocked when there will be selection from database)
- 发送数据,只针对那些有更新的人(例如,如果我没有任何新消息,当从数据库中选择时,我的刷新将被阻塞)
- You run 1 query to the DB per 0.5 second, no matter how much users there are
- 无论有多少用户,每0.5秒运行1个查询到DB
Just look into Node.js and Socket.io. This solution help me with a great boost.
只考虑节点。js和socket . io。这个解决方案对我有很大的帮助。
#5
2
First off, ask yourself if it's necessary to update the chat frequently. What type of chats will be happening? Is it real-time? Simple Q&A? Tech support? Etc. In all but the real-time chat cases, you will be better off using a long polling JS-based design, because instantaneous responses are not that important. If this is for real-time chats, then you should consider a Gmail-like design whereby you keep an XHR open and push messages back to the client as they are received. If connection resources are a concern, you can get by using long polling with a very brief interval (ex. 5-10 seconds).
首先,问问自己是否有必要经常更新聊天记录。什么样的聊天会发生?它是实时的吗?简单的问答吗?技术支持?等等。在除了实时聊天的情况之外的所有情况下,最好使用基于jsp的长轮询设计,因为即时响应不是那么重要。如果这是用于实时聊天,那么您应该考虑一个类似gmail的设计,在接收到消息时打开XHR,并将消息推送回客户机。如果关心连接资源,可以使用长轮询,间隔很短(例如5-10秒)。