我正在我的网站上开发用户之间的在线聊天。聊天功能正常,但如果打开长轮询连接,则任何人都无法进入该网站。
我的代码[更新]:
$time = $_GET['time'];
while (true) {
$sth = $db->prepare("SELECT * FROM messages LEFT JOIN users ON users.username=messages.chat_msg_user_id WHERE chat_msg_client_id=:chat_msg_client_id AND chat_msg_id>:chat_msg_id AND chat_notification='0' ORDER BY chat_msg_time DESC LIMIT 1");
$sth->execute([":chat_msg_client_id" => $client_id, ":chat_msg_id" => $last_message_id]);
$messages = [];
while ($answer = $sth->fetch()) {
$msg = ["chat_msg_id" => $answer["chat_msg_id"], "chat_msg_user_id" => $answer["chat_msg_user_id"], "chat_username" => $answer['username'], "chat_user_photo" => $answer['mainphoto'], "chat_user_status" => $answer['status'], "chat_user_name" => $answer["name"], "chat_msg_from" => $answer['chat_msg_from'], "chat_msg_time" => date("H:i", $answer["chat_msg_time"]), "chat_msg_date" => date("m.d.y", $answer["chat_msg_time"]), "chat_msg_text" => mb_str_replace("\n", "<br>", $answer["chat_msg_text"]), "read" => $answer['chat_read'], ];
$messages[] = $msg;
$last_message_id = $answer["chat_msg_id"];
// some variables here for json_encode below //
}
if (count($messages) > 0) {
$sth2 = $db->prepare("SELECT count(chat_read) as unread_messages_count FROM messages WHERE chat_msg_client_id='$client_id' AND chat_read='0'");
$sth2->execute();
$answers = $sth2->fetch();
$unread_messages_count = $answers['unread_messages_count'];
echo json_encode(["command" => "new_messages", "messages" => $messages, "last_message_id" => $last_message_id, "chat_msg_id" => $chat_msg_id, "chat_user_name" => $chat_user_name, "chat_user_status" => $chat_user_status, "chat_user_photo" => $chat_user_photo, "chat_msg_from" => $chat_msg_from, "chat_msg_time" => $chat_msg_time, "chat_msg_date" => $chat_msg_date, "chat_msg_text" => $chat_msg_text, "unread_messages_count" => $unread_messages_count, ]);
exit();
}
usleep(10000);
if ((time() - $time) > 60) {
echo json_encode(["command" => "timeout"]);
exit();
}
}
更新 2: 我的托管服务提供商发送了一些有关它的信息,但我不明白它是什么...:
sendto(3, "\306\0\0\0\3SELECT * FROM messages LEFT JOIN users ON users.username=messages.chat_msg_user_id WHERE chat_msg_client_id='222' AND chat_msg_id>'571' AND chat_notification='0' ORDER BY chat_msg_time DESC LIMIT 1", 202, MSG_DONTWAIT, NULL, 0) = 202
更新 3: 我忘了说 — 每个用户有 2 个长轮询连接。一个用于获取新聊天和新消息(用于通知),另一个用于在聊天时获取消息。
最佳答案
PHP 通常使用线程池来处理请求。这种方法并不真正支持让执行休眠。您最终很快就会耗尽可用线程,并且新请求不会得到处理,因为所有线程都在休眠。
您要么需要增加线程数量(这不会扩展并且您的托管服务提供商可能不支持),要么切换到不同的方法(通过使用支持异步请求处理的语言/框架,例如 NodeJS ).
另请参阅 an answer regarding long polling in PHP 中的这段摘录:
Note: With a real site, running this on a regular web-server like Apache will quickly tie up all the "worker threads" and leave it unable to respond to other requests.. There are ways around this, but it is recommended to write a "long-poll server" in something like Python's twisted, which does not rely on one thread per request. cometD is an popular one (which is available in several languages), and Tornado is a new framework made specifically for such tasks (it was built for FriendFeed's long-polling code)... but as a simple example, Apache is more than adequate! This script could easily be written in any language (I chose Apache/PHP as they are very common, and I happened to be running them locally)
更新:
My hosting provider said that Apache has too many connections to database and my server dieing cause of it
如果这是问题所在,则可以通过在进入休眠前关闭数据库连接来解决(直到有关 PHP 线程的其他问题接管),see this for PDO .
关于php 长轮询 "killing"服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53140063/
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file