繁体   English   中英

了解mod_proxy和Apache 2以编写彗星服务器

[英]Understanding mod_proxy and Apache 2 for writing a comet-server

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

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

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

我很确定使用mod_proxy会在处理请求时阻塞一个worker。

如果你可以使用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,我可能有另一个解决方案,我正在检查它是否适用于您的情况。

这是一个难题。 即使您遇到了正在遇到的安全问题,您最终还是必须为当前正在查看网页的每个客户端打开TCP连接。 您将无法创建一个线程来处理每个连接,并且您将无法在单个线程的所有连接上“选择”。 之前完成此操作后,我可以告诉你这并不容易。 你可能想看看libeventmemcached使用了类似的结尾。

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

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

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

几年前我遇到了一个问题,我希望客户使用具有专有二进制协议的客户端 - 服务器系统,以便能够访问端口80上的服务器,因为他们在系统使用的自定义端口上不断出现防火墙问题。 我需要的是一个可以在端口80上运行的代理,并将流量引导到Apache或应用服务器,具体取决于客户端遇到的前几个字节。 我找了一个解决方案,发现什么都不合适。 我考虑过编写一个Apache模块,一个DeleGate的插件等,但最终还是通过自己的自定义内容感知代理服务进行了推广。 我认为,这是你想要做的最糟糕的情况。

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

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


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

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

只要你相当熟悉线程(如果你已经表明你正在考虑编写自己的HTTP服务器,你必须这样做,这不应该太复杂 - 在http监听器部分之上:

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

这样,你永远不会阻止Apache超过需要的时间,因为你所做的只是发出“do x”或“给我x的结果”的请求。 您可能希望在几个点上构建一些安全功能 - 例如处理失败的任务,并确保客户端存在超时,以便它不会无限期地等待。

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

三种选择:

  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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM