我有这种情况..。一台服务器和数以万计的客户端之间由客户端发起的SOAP 1.1通信。客户端是外部的,通过我们的防火墙进入,通过证书、https等进行身份验证。它们可以在任何地方,并且通常有自己的防火墙、NAT路由器等。他们是真正的外部,而不仅仅是远程公司办公室。它们可能位于公司/园区网络、DSL/电缆,甚至拨号网络中。
客户端使用Delphi (2005 +2007年的SOAP修复),服务器是C#,但从架构/设计的角度来看,这并不重要。
目前,客户端将新数据推送到服务器,并在15分钟的轮询循环中从服务器拉取新数据。服务器当前不推送数据-客户端点击"messagecount“方法,以查看是否有新的数据需要拉取。如果为0,它将再休眠15分钟,然后再次检查。
我们试着把这个时间缩短到7秒。
如果这是一个内部应用程序,只有一个或几十个客户端,我们将编写一个客户端“侦听器”soap服务,并将数据推送到该服务。但由于它们位于外部,位于自己的防火墙后面,有时还位于NAT路由器后面的专用网络中,因此这是不切实际的。
因此,我们只剩下更快的循环轮询。每10秒检查一次消息计数的10K客户端将是每秒1000条消息,这将主要浪费带宽、服务器、防火墙和身份验证器资源。
因此,我正在尝试设计一些比自己造成的DoS攻击更好的东西。
我认为让服务器向客户端(推送)发送soap消息是不切实际的,因为这需要在客户端进行太多的配置。但我认为还有其他我不知道的选择。例如:
1)客户端有没有办法通过SOAP1.1请求GetMessageCount(),并获得响应,然后可能“保持在线”5-10分钟,以便在新数据到达时获得额外的响应?也就是说,服务器说"0",然后一分钟后响应某个SQL触发器(服务器是Sql Server上的C#,顺便说一下),知道这个客户端仍然“在线”,并发送更新后的消息计数"5"?
2)有没有其他协议可以用来"ping“客户端,使用从客户端上次GetMessageCount()请求中收集的信息?
3)我甚至不知道。我猜我正在寻找一些神奇的协议,客户端可以发送一个GetMessageCount()请求,其中将包含“哦,顺便说一下,如果答案在下一个小时内发生变化,请在这个地址ping我……”的信息。
此外,我假设这些“保持线路开放”方案中的任何一个都会严重影响服务器规模,因为它需要同时保持数千个连接打开。我想,这可能也会影响到防火墙。
外面有没有这样的东西?或者,我是不是被投票所困住了?
蒂娅
克里斯
更新4/30/2010:
在证明了7秒通知既不容易也不便宜,特别是在不超出HTTPS/SOAP/防火墙的公司标准的情况下,我们可能会提出一个两阶段的解决方案。Phase1将让客户端“按需”轮询通过SOAP执行的GetMessageCount,这里没什么特别的。将有一个“刷新”按钮来拉取新数据(这在这里是合理的,因为用户通常有理由怀疑新数据已经准备好了,即他们刚刚更改了在线系统中的织物颜色,所以他们知道在查看桌面上的发货清单之前单击“刷新”,现在他们在描述中看到了颜色。)(这不是一个真正的服装/时尚应用程序,但你明白了)。使用这里讨论的技术,让两个aps始终与主机推送的实时更新保持同步的概念仍然存在。但我预计它将被推迟到另一个版本,因为我们可以提供85%的功能,而不必这样做。然而,我希望我们能做一个概念证明,并能证明它是可行的。我会回来并发布未来的更新。感谢大家在这方面的帮助。
发布于 2010-04-21 03:49:08
Delphi中多层开发的两大派别是components4developers (在Mark Robinson的回答中描述了他们的kbmMW产品)和RemObjects (他们有一个很好的例子,可能与您想要的类似:Push notifications for iPhone)。
在您的复杂环境中,多播UDP可能无法解决问题,但从开销的角度来看,它是无与伦比的。
如果连接是打开的,则可以以双向方式使用它(这也被.NET远程处理和WCF使用),但有额外的开销。
您需要在保持连接活动(锁定资源)和创建新连接(耗费时间和延迟)之间找到平衡。
--jeroen
发布于 2010-04-21 18:43:09
考虑一下“玩”一下HTTP协议,以获得您想要的东西,同时仍然能够遍历客户端上可能具有的所有代理、NAT和防火墙。
让每个客户端以一种禁止任何类型的缓存的方式对消息计数执行一个普通的HTTP请求(例如: GET http://yourserver.org/getcount/nodeid/timeofday/sequence)。在HTTP服务器的服务器端实现中,如果"count“与以前相同,则延迟提供答案(即:没有新消息)。
我为一个在浏览器中运行的Ajax风格的应用程序这样做过,它的行为有点像聊天应用程序,但是您的解决方案可以更快。我使用TIdHttp服务器实现了服务器端的东西,这使得我可以通过在它的线程中简单地使用-ing()来延迟提供客户端东西的答案。从客户端来看,它看起来像一个服务器,有时给出答案的速度真的很慢。
服务器端的伪代码:
function ClientHasMessages(ClientID:Integer; MaxWait:TDateTime):Boolean;
var MaxTime:TDateTime;
begin
if ClientActuallyHasMessage(ClientID) then Result := True
else
begin
MaxTime := Now + MaxWait;
while Now < MaxTime do
begin
if ClientActuallyHasMessage(ClientID) then
begin
Result := True;
Exit;
end
else
Sleep(1000);
end;
Result := False; // TimeOut
end;
end;这段代码背后的想法是:它在您自己的服务器上的线程中运行,在那里它可以测试消息计数,大概只需要很少的成本:
<
这将是服务器上的需求,但我想说它们是可行的:
服务器的/IP实现需要跟踪相当多的同步连接(每个客户端都将始终有一个活动的
发布于 2010-04-20 23:11:54
我会去看看kbmMW
我可能会使用类似于MS Exchange的方法-通过tcp/ip连接和身份验证,然后通过udp将更新通知从服务器发送到客户端,然后客户端接收udp请求并通过tcp/ip下载更新。
(至少我是这样理解MS Exchange的工作原理的)
https://stackoverflow.com/questions/2675793
复制相似问题