8

我目前尝试为某种彗星技术(长轮询 XHR 请求)实现一个简单的 HTTP 服务器。由于JavaScript对跨域请求非常严格,我有几个问题:

  1. 据我了解,任何 apache 工作人员在服务请求时都会被阻止,因此当所有工作人员都有服务请求时,将“脚本”作为普通网站编写会阻止 apache。--> 不行!
  2. 我想出了一个想法,编写一个自己的简单 HTTP 服务器,仅用于服务这个长轮询请求。该服务器不应阻塞,因此每个工作人员可以同时处理许多请求。由于我的网站还包含内容/图像等,并且我的服务器不需要服务器内容,因此我在另一个端口上启动了他,然后是 80。现在的问题是我无法在我JavaScript的 apache 交付和我运行的彗星服务器之间进行交互由于一些跨域限制,在不同的端口上。--> 不行!
  3. 然后我想出了将mod_proxy我的服务器映射到新子域的想法。我真的不知道它是如何mod_proxy工作的,但我可以想象我知道与我的第一种方法具有相同的效果?

创建这种经典网站和这些长轮询 XHR 请求的组合的最佳方式是什么?我需要自己在我的服务器上实现内容交付吗?

4

5 回答 5

3

我很确定在处理请求时使用 mod_proxy 会阻止工作人员。

如果您可以使用 2 个 IP,则有一个相当简单的解决方案。假设 IP A 是 1.1.1.1,IP B 是 2.2.2.2,假设您的域是 example.com。

这就是它的工作方式:

- 将 Apache 配置为侦听端口 80,但仅在 IP A 上。

- 在端口 80 上启动您的其他服务器,但仅在 IP B 上。

- 将 XHR 请求配置为位于您域的子域上,但使用相同的端口。所以跨域限制并不能阻止它们。因此,您的站点是 example.com,例如,XHR 请求转到 xhr.example.com。

- 配置您的 DNS,以便 example.com 解析为 IP A,而 xhr.example.com 解析为 IP B。

-你完成了。

如果您有 2 台服务器并且每台服务器都有其 IP,则此解决方案将起作用,如果您有一台具有 2 个 IP 的服务器,它也将起作用。

如果您不能使用 2 个 IP,我可能有另一种解决方案,我正在检查它是否适用于您的情况。

于 2009-07-17T06:07:23.887 回答
3

这是一个难题。即使您解决了遇到的安全问题,您最终也将不得不为当前正在查看网页的每个客户端保持打开的 TCP 连接。您将无法创建一个线程来处理每个连接,并且您将无法从单个线程中“选择”所有连接。以前做过这件事,我可以告诉你这并不容易。您可能想查看libeventmemcached使用它来达到类似的目的。

在某种程度上,您可能可以通过设置较长的超时时间并允许 Apache 拥有大量工作人员而侥幸,其中大部分工作人员大部分时间都处于空闲状态。我相信,仔细选择和配置 Apache 工作模块将扩展到成千上万的并发用户。然而,在某些时候,它不会再扩大规模。

我不知道你的基础设施是什么样的,但我们在网络机架中有负载平衡盒,称为 F5s。它们呈现单个外部域,但根据响应时间、请求标头中的 cookie 等将流量重定向到多个内部服务器。它们可以配置为将虚拟域内特定路径的请求发送到特定服务器。因此,您可以将 example.com/xhr/foo 请求映射到特定服务器以处理这些彗星请求。不幸的是,这不是软件解决方案,而是相当昂贵的硬件解决方案。

无论如何,您可能需要某种负载平衡系统(或者您可能已经拥有一个),也许可以将其配置为比 Apache 更好地处理这种情况。

几年前我遇到了一个问题,我希望使用具有专有二进制协议的客户端-服务器系统的客户能够访问我们在端口 80 上的服务器,因为他们在系统使用的自定义端口上不断遇到防火墙问题。我需要的是一个代理,该代理将位于端口 80 上,并根据客户端收到的前几个字节将流量定向到 Apache 或应用服务器。我寻找解决方案,但没有找到合适的解决方案。我考虑过编写一个 Apache 模块、一个用于 DeleGate 的插件等,但最终由自己的自定义内容感应代理服务推出。我认为,对于您正在尝试做的事情,这是最坏的情况。

于 2009-07-19T22:26:31.953 回答
0

要回答有关 mod-proxy 的具体问题:的,您可以设置 mod_proxy 以提供由非面向公众的服务器(或服务)生成的内容(即只能通过内部地址或本地主机获得)。

我已经在生产环境中完成了这项工作,并且效果非常好。Apache 通过 AJP 工作人员将一些请求转发到 Tomcat,而将其他请求通过 mod 代理转发到 GIS 应用程序服务器。正如其他人指出的那样,跨站点安全性可能会阻止您在子域上工作,但没有理由不能代理对 mydomain.com/application 的请求


谈论您的具体问题-我认为您确实陷入了将问题视为“长期请求”的困境-即假设当您提出其中一个请求时,整个过程需要停止。似乎您正试图通过更改系统架构来解决应用程序架构的问题。事实上,您需要做的就是将这些后台请求完全按原样处理;和多线程它:

  • 客户端向远程服务发出请求“使用数据 A、B 和 C 执行任务 X
  • 您的服务接收请求:它将请求传递给调度程序,调度程序为请求发出唯一的票证/令牌。然后服务将此令牌返回给客户端“谢谢,您的任务在令牌 Z 下运行的队列中
  • 客户端然后挂在这个令牌上,显示一个“加载/请等待”框,并设置一个计时器,每秒触发一次参数
  • 当计时器触发时,客户端向远程服务发出另一个请求“你有我的任务的结果吗,它是令牌 Z
  • 然后,您的后台服务可以与您的调度程序进行检查,并且可能会返回一个空文档“不,尚未完成”或结果
  • 当客户端返回结果时,它可以简单地清除计时器并显示它们。

只要您对线程处理相当满意(如果您已经表明您正在考虑编写自己的 HTTP 服务器,那么您必须这样做,这不应该太复杂 - 在 http 侦听器部分之上:

  • 调度程序对象 - 单例对象,实际上只是包装了“先进先出”堆栈。新任务进入堆栈的末尾,作业可以从头开始:只需确保发出作业的代码是线程安全的(更少的两个工作从堆栈中拉出同一个作业)。
  • 工作线程可以非常简单 - 访问调度程序,请求下一个工作:如果有工作则发送结果,否则只需休眠一段时间,重新开始。

这样,您永远不会阻止 Apache 超过需要的时间,因为您所做的只是发出“do x”或“give me results for x”的请求。您可能希望在某些方面构建一些安全功能 - 例如处理失败的任务,并确保客户端有超时,因此它不会无限期地等待。

于 2009-07-21T09:00:07.600 回答
0

对于数字 2:您可以使用 JSONP 绕过跨域限制。

于 2009-11-25T14:58:58.383 回答
0

三种选择:

  1. 使用 nginx。这意味着您运行 3 个服务器:nginx、Apache 和您自己的服务器。
  2. 在自己的端口上运行您的服务器。
  3. 使用 Apache mod_proxy_http(作为您自己的建议)。

我已经确认 mod_proxy_http (Apache 2.2.16) 可以代理在 GlassFish 3.1.1 中运行的 Comet 应用程序(由 Atmosphere 0.7.1 提供支持)。

我的完整源代码测试应用程序在这里:https ://github.com/ceefour/jsfajaxpush

于 2011-04-25T18:30:09.360 回答