28

我有一个问题让我很难找到理想的解决方案,为了更好地解释它,我将在这里公开我的场景。

我有一个服务器,它将接收来自多个客户的订单。每个客户端将提交一组应在某些指定时间间隔执行的重复任务,例如:客户端 A 提交应在 2009-12-31 和 2010-12-31 之间每分钟执行一次的任务 AA;所以如果我的数学是正确的,那就是一年大约有 525 600 次操作,考虑到更多的客户端和任务 ,让服务器处理所有这些任务是不可行的,所以我想出了工作机器的想法。服务器将在 PHP 上开发。

工人机器只是 我将在家里或工作场所托管的基于 Windows 的普通计算机,每个工人都将拥有一个专用的 Internet 连接(具有动态 IP)和一个 UPS,以避免停电。每个工作人员还将每 30 秒左右通过 Web 服务调用查询服务器,获取下一个待处理的作业并处理它。作业完成后,工作人员将向服务器提交输出并请求新作业,以此类推。如果需要扩展系统,我应该设置一个新的工人,整个事情应该无缝运行。worker 客户端将使用 PHP 或 Python 开发。

在任何给定时间,我的客户都应该能够登录到服务器并检查他们订购的任务的状态。

现在这里是棘手的部分:

  • 如果由于某种原因服务器出现故障,我必须能够重建已经处理的任务。
  • 工作人员不是特定于客户的,一名工作人员应该为任何给定数量的客户处理工作。

我对一般数据库设计和使用哪些技术有一些疑问。

最初我想使用几个SQLite数据库并将它们全部连接到服务器上,但我不知道如何按客户端分组以生成作业报告

我从未真正使用过以下任何技术:memcachedCouchDBHadoop等,但我想知道这些技术中的任何一个是否适合我的问题,如果是,你推荐给新手的是像我一样的“分布式计算”(或者这是并行的?)。请记住,工作人员具有动态 IP。

就像我之前说的那样,我在一般数据库设计方面也遇到了麻烦,部分原因是我还没有选择任何特定的 R(D)DBMS,但是我有一个问题,我认为它与我选择的 DBMS 无关到排队系统...我应该预先计算特定作业的所有绝对时间戳并拥有大量时间戳,按升序执行并将它们标记为完整,还是应该有一个更聪明的系统,例如“当时间戳模数 60 = = 0 -> 执行“。这种“聪明”系统的问题在于,一些工作不会按应有的顺序执行,因为一些工作人员可能在等待无所事事,而另一些工作人员则超载。你有什么建议?

PS:我不确定这个问题的标题和标签是否正确反映了我的问题以及我正在尝试做的事情;如果不是,请相应地编辑。

感谢您的输入!

@timdev:

  1. 输入将是一个非常小的 JSON 编码字符串,输出也将是一个 JSON 编码字符串,但稍大一些(大约 1-5 KB)。
  2. 输出将使用来自 Web 的几个可用资源进行计算,因此主要瓶颈可能是带宽。数据库写入也可能是一个 - 取决于 R(D)DBMS。
4

7 回答 7

15

看起来你正处于重建Gearman的边缘。以下是 Gearman 的介绍:

Gearman 提供了一个通用的应用程序框架,将工作外包给其他更适合完成工作的机器或进程。它允许您并行工作、负载平衡处理以及在语言之间调用函数。它可用于各种应用程序,从高可用性网站到数据库复制事件的传输。换句话说,它是分布式处理如何通信的神经系统。

您可以用 PHP 编写客户端和后端工作人员代码。


关于为 Windows 编译的 Gearman 服务器的问题:我不认为它在为 Windows 预构建的整洁包中可用。Gearman 仍然是一个相当年轻的项目,他们可能还没有成熟到为 Windows 生产可立即运行的发行版的地步。

Sun/MySQL 员工 Eric Day 和 Brian Aker于 2009 年 7 月在 OSCON 上为 Gearman提供了教程,但他们的幻灯片只提到了 Linux 软件包。

这是 Perl CPAN Testers 项目的链接,它表明 Gearman-Server 可以使用 Microsoft C 编译器 ( cl.exe) 在 Win32 上构建,并且它通过了测试: http://www.nntp.perl.org/group/perl。 cpan.testers/2009/10/msg5521569.html 但我猜你必须下载源代码并自己构建它。

于 2009-10-05T00:20:35.740 回答
4

Gearman似乎是这种场景的完美候选者,您甚至可能希望根据您需要多少计算能力,将您的 windows 机器虚拟化到每台机器的多个工作节点。

此外,gearman 中的持久队列系统可防止工作人员或 gearman 服务器崩溃时丢失作业。服务重新启动后,队列在崩溃/重新启动之前停止的地方继续,您不必在应用程序中处理所有这些,这是一个很大的优势,可以节省大量时间/代码

制定一个自定义解决方案可能会奏效,但在我看来,gearman 的优势,尤其是持久队列,这很可能是目前最适合您的解决方案。我不知道用于 Gearman 的 Windows 二进制文件,但我认为它应该是可能的。

于 2009-10-13T23:58:48.270 回答
3

在您的情况下,主服务器和多个工作人员的设置看起来很合适。

在主服务器上,我会在主主复制中安装 MySQL(Percona InnoDB 版本稳定且快速),这样您就不会出现单点故障。主服务器将托管一个 API,工作人员将每 N 秒拉一次。master 将检查是否有可用的作业,如果有,它必须标记该作业已分配给 worker X 并将适当的输入返回给 worker(所有这些都通过 HTTP)。此外,在这里您可以存储工人的所有脚本文件。

在 workers上,我强烈建议你安装一个 Linux 发行版。在 Linux 上,设置计划任务更容易,总的来说,我认为它更适合这项工作。使用 Linux,您甚至可以使用完美配置的 worker 创建一个 live cd 或 iso 映像,并在您想要的所有机器上快速轻松地安装它。然后设置一个 cron 作业,它将与主服务器进行 RSync 以更新/修改脚本。这样,您将只在一个地方(主服务器)更改文件,所有工作人员都将获得更新。

在此配置中,您不需要关心 IP 或工作人员的数量,因为工作人员正在连接到主服务器,反之亦然。

工作人员的工作非常简单:向 API 请求工作,执行,然后通过 API 发回结果。冲洗并重复:-)

于 2009-10-17T04:20:54.730 回答
3

我会避免使用 sqlite 来完成这类任务,虽然它是一个非常适合小型应用程序的数据库,但它不能很好地处理并发性,它只有一个锁定策略,即锁定整个数据库并保持锁定直到单个事务已经完成。

考虑 Postgres,它具有工业级的并发和锁管理,可以很好地处理多个同时事务。

这听起来像是排队的工作!如果您在 Java 世界中,我会为您的解决方案推荐基于 JMS 的架构。有一个“dropr”项目可以在 php 中做类似的事情,但它都是相当新的,所以它可能不适合你的项目。

无论您使用哪种技术,您都应该寻求“自由市场”解决方案,其中工作线程尽可能快地消耗可用的“工作”,而不是中央进程将任务分配给选定工作人员的“命令经济”。

于 2009-10-15T01:56:51.760 回答
3

一个更简单的解决方案是连接多个 php 节点的单个数据库。如果您使用适当的 RDBMS(MSql + InnoDB 就可以),您可以让一个表充当队列。然后,每个工作人员将从其中提取任务以进行处理,并在完成后将其写回数据库,使用事务和锁定进行同步。这在一定程度上取决于输入/输出数据的大小。如果它很大,这可能不是最好的方案。

于 2009-10-05T07:00:22.723 回答
3

您可以使用像RabbitMQActiveMQ这样的消息传递系统作为系统的核心,而不是通过 SQL 重新发明排队轮。这些系统中的每一个都提供 AMQP 协议并具有硬盘支持的队列。在服务器上,您有一个应用程序根据您的日程安排将新作业推送到“工作”队列中,另一个应用程序将“结果”队列中的结果写入数据库(或以其他方式对其进行操作)。

所有工作人员都连接到 RabbitMQ 或 ActiveMQ。他们将工作从工作队列中弹出,完成工作并将响应放入另一个队列。在他们完成之后,他们确认原始的工作请求说“它完成了”。如果一个工作人员断开其连接,则该作业将恢复到队列中,以便另一个工作人员可以执行此操作。

除了队列(工作描述、客户详细信息、已完成的工作)之外的所有内容都可以存储在数据库中。但是任何实时的东西都应该放在其他地方。在我自己的工作中,我正在流式传输实时电力使用数据,并且让很多人访问数据库来轮询它是一个坏主意。我写过关于我系统中的实时数据的文章

于 2009-10-19T03:06:18.493 回答
1

我认为您与主要的工作分配器和工人一起朝着正确的方向前进。我会让他们通过 HTTP 进行通信。

我会选择 C、C++ 或 Java 作为客户端,因为它们具有运行脚本的能力(C 中的 execvp,Java 中的 System.Desktop.something)。Jobs 可能只是脚本的名称和该脚本的参数。您可以让客户端返回作业的状态。如果作业失败,您可以重试它们。您可以让客户端每分钟(或每 x 秒轮询一次作业并让服务器整理作业)

PHP 将适用于服务器。

MySQL 可以很好地用于数据库。我只会制作两个时间戳:开始和结束。在服务器上,我会寻找 WHEN SECONDS==0

于 2009-10-04T18:43:11.457 回答