我目前正在开发一个从许多IMAP邮箱中提取邮件的应用程序.似乎赛璐珞对于这部分来说是一个合适的选择,但我不确定如何雇佣演员.
该应用程序将以分布式方式运行.有x个邮箱可以轮询,y个进程将被分割.因此,每个进程都有一个他们必须轮询的邮箱列表,这个列表会不时地改变.这意味着每个进程维护的连接池是动态的.
我最大的问题是:我应该为每个邮箱生成一个单独的ImapConnection actor,还是应该创建一个内部管理所有连接的ImapListener actor?
我目前的设计采用前一种解决方案.有一个中央协调员演员,它保持一组演员,每个演员管理一个imap连接.添加一个简单的新连接:
@connections << ImapConnection.supervise(account_info)
ImapConnection定期轮询IMAP服务器,或维持IDLE连接.如果协调器想要停止轮询邮箱,它会在@connections数组中查找并正确处理它.
这对我来说似乎是一种合乎逻辑的方法,可以产生Celluloid的许多好处(例如自动重启崩溃的演员),但我很难找到使用这种方法的其他软件的例子.以这种方式产生100个演员正确使用演员模型还是应该使用不同的方法?
很高兴听到你正在使用Celluloid
.好问题.
不确定如何创建连接并维护它们,无论是否TCPSocket
具有管理能力.如果你有管理能力的TCPSocket
直接,你应该使用Celluloid::IO
以及Celluloid
本身.我也不知道你从IMAP连接中提取信息的位置.这两件事影响了你的策略.
你的方法并不差,但是 - 可以通过添加一些东西来完成你的繁重工作,投票工作人员; 另一个account_info
只持有; 以及触发工作和/或维持IDLE状态的最终演员.所以你最终得到ImapWorker
(一个游泳池)ImapMaintainer
,和ImapRegistry
.就在这里,我想知道,既然你是民意调查,你是否需要保持开放的连接,而不是允许推送信息.如果您打算进行民意调查并仍然保持连接打开,那么这三个角色将会做什么:
ImapRegistry
握着你account_info
的Hash
.这将对它的方法,如add
,get
和remove
.我推荐一个Hash
,@credentials
所以你可以在ImapMaintainer
和之间使用相同的ID ImapRegistry
; 一个在其中保存实时连接@connections
,一个account_info
在其中保存实例@credentials
.二者@connections
并@credentials
用相同的ID访问,但是一个保持挥发性连接,而另一只具有可用来重新创建如果必要的连接的静态数据.通过这种方式,您的重型升降机可能会死亡,重生,整个系统可以自行再生.
ImapMaintainer
将存在实际@connections
内容,并在其中every( interval ) { }
内置任务,添加到account_info
存储时ImapRegistry
.我看到有两个任务,具体取决于您计划轮询的频率.一种可能是简单地触摸IMAP连接以维护它,另一种可能是用IMT服务器轮询ImapWorker
.ImapWorker
将被保存在一个池中ImapMaintainer
的发言权@worker
.因此它有@connections
,@worker
,#polling
,和#keepalive
.polling
可能是一种@connections.each
情况,或者您可以在创建连接时添加每个连接的计时器.
ImapWorker
有两种方法......一种是#touch
保持连接活着.主要是#poll
,它接受您维护的连接,并在其上运行轮询过程.该方法返回信息甚至更好地存储它,然后工作者返回@worker
池.这将使您获得使轮询过程在单独的线程中发生而不仅仅是单独的光纤的好处,并且还允许在最强大但最不知道的类型的actor中保留最棘手的方面.
落后的工作,如果ImapRegistry
收到#add
,它存储account_info
并给出了给ImapMaintainer
它创建的连接,以及定时器(但它忘记了account_info
,只产生S上的连接和定时器()或刚创建的连接,让一个大计时器保持连接与@worker
这是一个pool.ImapMaintainer
不可避免地命中一个计时器,所以在它的计时器的开始和结束时它可以检查它的连接.如果由于某种原因连接已经消失,它可以用@registry.get
信息重新创建它.在它的计时器提示任务中,它可以运行@worker.poll
或@worker.alive
.
这说明了上述要求,显示了初始化程序如何将actor系统组合在一起,并且具有不完整的方法框架.
WORKERS = 9 #de arbitrarily chosen class ImapRegistry include Celluloid def initialize @maintainer = ImapMaintainer.supervise @credentials = {} end def add( account_info ) ... end def get( id ) ... end def remove( id ) ... end end class ImapMaintainer include Celluloid def initialize @worker = ImapWorker.pool size: WORKERS @connections = {} end def add( id, credential ) ... end def remove( id ) ... end #de These exist if there is one big timer: def polling ... end def keepalive ... end end class ImapWorker include Celluloid def initialize #de Nothing needed. end def poll( connection ) ... end def touch( connection ) ... end end registry = ImapRegistry.supervise
我喜欢Celluloid
并希望你能获得很多成功.请询问您是否需要澄清任何内容,但这至少是您需要考虑的另一种策略.