COMET和PHP组合有真正的解决方案吗?基本上,当数据库中有新数据时,我需要定期更新用户主页.据我了解,我需要在我的服务器和客户端浏览器之间建立持久连接,以便在新信息发布后立即更新其主页的内容.虽然没有投入大量资源但我没有找到任何关于这个问题的清楚的事情.我读过很多文章都认为PHP不是实现COMET的好语言.我的Web应用程序完全用PHP编程,我不想学习另一种语言,但如果我被迫,你会建议一个好的语言开始吗?你认为我可以编程一个接口来处理这个问题吗?
提前致谢.
我正在调用已实现CometProcessor接口的servlet,每当我尝试使用get请求调用servlet时,我都会收到上述错误.我可以知道原因吗?
public class ChatServlets
extends HttpServlet implements CometProcessor {
public void event(CometEvent event)
throws IOException, ServletException {
HttpServletRequest request = event.getHttpServletRequest();
HttpServletResponse response = event.getHttpServletResponse();
if (event.getEventType() == CometEvent.EventType.BEGIN) {
response.getWriter().println("Welcome ");
} else if (event.getEventType() == CometEvent.EventType.READ) {
response.getWriter().println("Bye");
}
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个Comet应用程序可能会同时打开许多实例.这意味着许多并发连接.为了克服浏览器并发连接限制,改变连接主机名应该不会太难.我的问题是:平均互联网连接如何公平?我会遇到性能问题吗?
我已经和Django合作了一段时间,并且已经在ubuntu上使用Apache 2 mod_wsgi和PostgreSQL数据库的设置上编写了几个应用程序.
我有一个应用程序,它使用xsendfile通过Django视图从Apache提供文件,并允许用户通过表单上传文件.所有这一切都很好,但我现在想通过允许用户聊天并查看新文件上传时间而不刷新浏览器来提升功能(以及我确定的复杂性).
由于我希望这是可扩展的,我不想连续使用AJAX进行轮询,因为对于大量用户来说这将变得非常沉重.
我已经阅读了更多的帖子,网站和博客,然后我可以指望将彗星功能集成到Django应用程序中,但有很多不同的意见,如何做到这一点,我现在完全困惑.
我应该使用orbited,gevent,iosocket吗?龙卷风在哪里适合这场辩论?
我希望消息也存储在数据库中,因此在写入数据库时是否需要任何特殊配置来阻止我的应用程序阻塞?使用Django运行聊天服务器会对我从Apache提供文件的能力产生什么影响?
我正在一个网站上显示来自DB的一些数据,这些数据经常变化(队列状态和聊天对话).我目前的设置是Apache/PHP/MySQL.当然,我希望避免每x秒轮询一次服务器,因为这不能很好地扩展.我想做反向ajax长轮询,但是,我已经读过Apache不能正常工作,因为它很快就会耗尽工作线程.还有很多其他的Web服务器来解决这个问题:nginx,龙卷风等等.但是,我的问题是,PHP是我所知道的唯一的服务器端脚本语言.此外,我已经编写了一些PHP脚本,所以如果可以,我想保留它们.只要我仍然可以使用PHP,我就可以切换服务器.
但在做一些调查研究后,我读过的人说PHP(PHP-FPM?)还创建的每个请求,这意味着如果我有上百个/千开放连接的过程中,将有数百/千流程,这也是问题所在.
我可以得出结论,使用PHP制作长轮询网站没有很好的可扩展方法吗?我应该放弃PHP并学习另一种服务器脚本语言吗?我可以继续开发使用我的当前设置(阿帕奇/ PHP)长轮询,但现在我不想脚本语言的选择构成任何限制我的系统的可扩展性,当我部署.所以我该怎么做?我对网络编程不是很有经验,所以如果有任何大师可以给我一些指示我会很感激!谢谢!
我试图使用Servlet API 3中定义的异步处理实现COMET聊天.它无法正常工作 - 聊天被阻止,所以我创建了调试servlet来仅测试异步部分.
这是我的doGet方法:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
log.debug("doGet called");
int timeout = 30 + RandomUtils.nextInt(60);
String message = RandomStringUtils.randomAlphanumeric(50 + RandomUtils.nextInt(250));
response.setHeader("Access-Control-Allow-Origin", "*");
final AsyncContext context = request.startAsync();
synchronized(items) {
items.add(new RequestItem(context, message, timeout));
}
log.debug("doGet created request and finished");
}
Run Code Online (Sandbox Code Playgroud)
我将请求项放入队列,并且有一个线程在运行,它将在指定的超时后获取项目并将响应发送到AsyncContext,打印有关它的消息.问题是,线程被阻塞,直到AsyncContext得到响应.这是在浏览器中请求4页加载后在我的日志中可见的内容:
2011-12-08 13:56:36,923 DEBUG [my.servlet.TestAsyncServlet] doGet called
2011-12-08 13:56:36,952 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished
2011-12-08 13:57:39,934 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [context=org.apache.catalina.core.AsyncContextImpl@175870a, message=zEQpATavzwFl6qIbBKve4OzIY9UUuZBwbqN1TC5KpU3i8LM9B6ChgUqaRmcT2yF, timeout=0]
2011-12-08 13:57:39,962 …Run Code Online (Sandbox Code Playgroud) 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>
Run Code Online (Sandbox Code Playgroud)
PHP的:
public function chatting()
{
while(true)
{
if(memcache_get(new_message))
return new_message;
sleep(0.5);
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个比设置setInterval更好的解决方案,它连接到PHP方法,如果每1秒钟就会返回一条消息(1秒增加+0.25每5秒让我们说)?
如果我使用第一个解决方案,我可能会使用sleep(0.5)它会立即给我消息,因为php循环很便宜,不是吗?
那么,什么解决方案更好(更重要的是,它需要更少的资源?).因为这样会有数以百计的聊天记录.
另外,可以先解决问题吗?假设我会重新加载一个页面,否则我会每30秒停止一次执行,所以我不会得到502 Bad Gateway.
编辑:我相信第二个解决方案更好,所以我将重新实现我的网站,但我只是好奇,如果这可能会给用户带来问题?可以预期会发生什么吗?我注意到的第一个问题是,在至少有一条新消息之前,您无法转到其他页面.
我想使用Google Chart创建一个实时更新的条形图.当用户加载页面时,我想显示当前结果.但是,一旦我的数据库中的数据发生变化,我想将这些更改推送到客户端并更新图表.
以下是Google Charts页面中的条形图示例:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Year');
data.addColumn('number', 'Sales');
data.addColumn('number', 'Expenses');
data.addRows([
['2004', 1000, 400],
['2005', 1170, 460],
['2006', 660, 1120],
['2007', 1030, 540]
]);
var options = {
title: 'Company Performance',
vAxis: {title: 'Year', titleTextStyle: {color: 'red'}}
};
var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
Run Code Online (Sandbox Code Playgroud)
我想我可以使用Ajax-Request每隔几秒钟拉一次数据并重绘图表.但也许在Google Charts中有一些我错过的inbuild-Method.我也读了很多关于Comet的内容,但我从未实现过这个概念.
还有其他人遇到过这个问题吗?
所以,我遇到了一个奇怪的问题,我希望有一些IE专家能够对这种行为有所了解.我的公司运行一个实时的Lift应用程序.我们使用彗星模型在浏览器和服务器之间进行实时通信,这是Lift的标准配置.另外值得注意的是:如果彗星与服务器不同步(由于连接问题或服务器重启,任何会导致服务器上的会话中断的事情)服务器响应该彗星请求,document.location.reload();并重新加载页面,启动一个新的会话,等等.
现在,为了确保注销按预期发生,我们有一个特殊的URL(/ session/logout),可以完成所有与会话相关的清理,然后将您踢回我们的主页.这可以通过单击该URL的锚点来触发,或者如果您尝试执行需要注销的操作,服务器可能会向您发出302该URL.很简单吧?在大多数浏览器中,这很有用,因为工作流看起来像这样:
但是,在IE中我们看到以下行为:
document.location.reload();从服务器接收a ,因为它们从未被IE关闭,主页的加载被中止,并且当前页面在没有用户登录的情况下重新加载.这是完全不合需要的,因为我们需要加载/ session/logout的正确结果 - 特别是在用户尝试执行他们登录时无法执行的操作的情况下(在这种情况下,302从注销将指向他们最初试图去的地方).
以前有没有人遇到过这种问题?关于如何处理这个问题的任何建议?
下面是我最终使用成功的彗星实现的代码.
$lastmodif = isset($this->params['form']['timestamp']) ? $this->params['form']['timestamp'] : 0;
$currentmodif = $already_updated[0]['Update']['lastmodified'];
while ($currentmodif <= $lastmodif)
{
usleep(5000000);
clearstatcache();
$already_updated_new = $this->Update->find('all',array
(
'conditions' => array
(
'Update.receiver_id' => $this->Auth->user('id'),
'Update.table_name' => "request_responses"
)
));
$currentmodif = $already_updated_new[0]['Update']['lastmodified'];
}Run Code Online (Sandbox Code Playgroud)
$already_updated[0]['Update']['lastmodified'] 获取表的最后更新时间戳的查询结果.
在上面的代码中,$ lastmodif和$ currentmodif是每次成功的彗星响应后传递的时间戳.
但现在的问题是,当我点击同一页面上的其他链接时,没有任何反应,但在等待这么长时间后重定向.
我认为usleep阻止了其他HTTP请求.
我正在使用mysql和cakephp请大家指导我该怎么办才能解决这个问题.
我已经尝试在调用页面时刷新,但它显示无法修改标头错误,因为已经发送了输出.
谢谢.
comet ×10
php ×4
java ×2
javascript ×2
mysql ×2
tomcat ×2
apache ×1
asynchronous ×1
cakephp ×1
concurrency ×1
django ×1
gevent ×1
jquery ×1
lift ×1
long-polling ×1
memcached ×1
postgresql ×1
python ×1
reverse-ajax ×1
servlet-3.0 ×1
servlets ×1