PHP中无状态Web应用程序中的持久性多节点事件

时间:2015-02-16 01:06:16

标签: php events rabbitmq distributed

我正在构建一个将在多个节点上运行的OO PHP应用程序,并且本质上将是相对无状态的,我需要实现正确的发布者 - 订阅者(http://en.wikipedia.org/wiki/Observer_pattern / http://sourcemaking.com/design_patterns/Observer/php)样式事件。

我的问题是,我该如何处理事件?

在我的应用程序中,我们使用的是Cassandra,Redis,Mongo和RabbitMQ等技术。

我知道PHP有一个事件EXTENSION可用,但从我可以说它坚持状态 - 或者如果利用memcached之类的东西它可以在该节点内使用...但我的应用程序将被分发跨多个节点。

让我们看一个例子: 在节点1上,更新度量(度量标准ID 37),并且需要更新订阅该度量的任何内容。这会在更新时发布更改和更改。

我订阅了正在更新的度量标准ID 37,例如度量标准38,可能需要在度量标准37的值更改时自行重新计算。

度量标准38当前已实例化并在进程ID 1011中的节点2上使用...度量标准37如何告知节点2上的度量标准38(在这种情况下为进程ID 1011)以运行预订函数?

Metric 39订阅正在更新的Metric 38,但未在任何地方实例化...当度量标准38完成更新时,Metric 39如何更新?

我在考虑使用RabbitMQ作为我的事件队列管理器,并且在每个节点上都有一个守护进程样式的事件消费者'读取事件队列中事件的应用程序(为了负载平衡/分配工作)。

然后消费者看到"指标:38:更新"它会检查像Redis这样的东西,以便订阅任何东西"公制:38:更新"并获取值(" What:Function:Values")并执行类似call_user_func_array(array($ what,$ function),$ values); ....但这似乎可能会导致开销和某种程度的同步问题......

我使用Doctrine MongoDB ODM来保存我的对象......为了处理同步问题,我想到了这样的事情: 对象可以有版本号...(版本= 1.0) 并且redis可用于维护对象的最新版本的快速引用(ObjectVersion:ObjectType:ObjectId)= 1.1 当在一个标记为@critical的对象属性上调用getter(像isDeleted,货币余额等)时,它可以检查实例的版本ID是否等于redis中的版本#并更新其值mongo如果需要...

备用设置使用amphp/amphttp://amphp.org/docs/amp/reactor-concepts.html)和某种形式的RPC来同步节点

由于我对网络开发(从c#转移)和无状态,以及分发...相当陌生。我认为向社群询问是否有人有更好的建议是个好主意?

2 个答案:

答案 0 :(得分:1)

  

我的问题是,我该如何处理事件?

如果您想使用事件循环实现,可以有多种选择:

您可以使用Redis提供的PubSub系统:http://redis.io/topics/pubsub。 Amp提供package for Redis,其他事件库可能已经有可用的实现。

Redis将向所有已连接和正在侦听的客户端发送事件通知。您可能不希望这样,因为您希望同步计算并仅执行一次。

您可以将实际数据推送到Redis列表,并仅在事件系统中使用事件系统进行轮询,以便工作人员可以睡觉。更好的解决方案可能是使用阻止列表操作,阻止Redis连接,直到Redis列表中有新数据可用。当该事件发生时,您可以重新计算该值并将更新推送到事件。

这基本上是用Redis构建一个消息队列,但实际上你只想查看不同消息队列实现的功能,看看它们是否适合你的需求。如果您想使用任何事件循环库,您可能还需要查看可用的客户端以及您需要的其他功能,因为它们通常不兼容(尚未)。

答案 1 :(得分:0)

可能需要一个中间件,比如http://redis.io/topics/pubsub或其他类似的消息队列可以支持你的应用程序