Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用AmazonSWF在服务器之间进行通信_Python_Linux_Amazon Web Services_Boto_Amazon Swf - Fatal编程技术网

Python 使用AmazonSWF在服务器之间进行通信

Python 使用AmazonSWF在服务器之间进行通信,python,linux,amazon-web-services,boto,amazon-swf,Python,Linux,Amazon Web Services,Boto,Amazon Swf,使用Amazon SWF在服务器之间传递消息 在服务器A上,我想运行脚本A 完成后,我想向服务器B发送一条消息以运行脚本B 如果它成功完成,我希望它从工作流队列中清除作业 我真的很难想出如何结合使用Boto和SWF来做到这一点。我不是在寻找一些完整的代码,但我所追求的是,如果有人可以解释多一点什么是涉及 我实际上如何告诉服务器B检查脚本的完成情况 A 如何确保服务器A不会接收脚本的完成 A并尝试运行脚本B(因为服务器B应该运行此脚本) 如何实际通知SWF脚本完成?你是一面旗子,还是一块石头 信

使用Amazon SWF在服务器之间传递消息

  • 在服务器A上,我想运行脚本A
  • 完成后,我想向服务器B发送一条消息以运行脚本B
  • 如果它成功完成,我希望它从工作流队列中清除作业
  • 我真的很难想出如何结合使用Boto和SWF来做到这一点。我不是在寻找一些完整的代码,但我所追求的是,如果有人可以解释多一点什么是涉及

    • 我实际上如何告诉服务器B检查脚本的完成情况 A
    • 如何确保服务器A不会接收脚本的完成 A并尝试运行脚本B(因为服务器B应该运行此脚本)
    • 如何实际通知SWF脚本完成?你是一面旗子,还是一块石头 信息,还是什么
    我对这一切都很困惑。我应该使用什么设计?

    你可以使用SNS,
    脚本A完成后,它将触发SNS,这将触发对服务器B的通知。我没有任何示例代码可供共享,但您肯定可以使用SWF跨两台服务器协调脚本的执行。其主要思想是创建与SWF对话的三段代码:

    • 一个组件,它知道首先执行哪个脚本,以及执行完第一个脚本后要做什么。这在SWF术语中称为“决策者”
    • 两个组件,每个组件都了解如何执行要在每台机器上运行的特定脚本。在SWF术语中,这些被称为“活动工人”
    第一个组件decider调用两个SWF API:pollfordisionTask和respondDecionTaskCompleted。轮询请求将为决策器组件提供正在执行的工作流的当前历史记录,基本上是脚本运行程序的“我在哪里”状态信息。您可以编写查看这些事件的代码,并确定应该执行哪个脚本。这些执行脚本的“命令”将以活动任务调度的形式出现,该任务作为RespondDecisionTaskCompleted调用的一部分返回

    您编写的第二个组件ActivityWorkers分别调用两个SWFAPI:PollForActivityTask和RespondActivityTaskCompleted。轮询请求将向活动工作者提供一个指示,表明它应该执行它所知道的脚本,即SWF所称的活动任务。从轮询请求返回给SWF的信息可以包括作为活动任务调度的一部分发送给SWF的单个执行特定数据。您的每个服务器都将独立地轮询SWF以获取活动任务,以指示本地脚本在该主机上的执行情况。工作程序执行完脚本后,将通过RespondActivityTaskCompleted API回调SWF

    从ActivityWorker到SWF的回调将导致一个新的历史记录被分发给我已经提到的decider组件。它将查看历史记录,查看第一个脚本是否完成,并计划执行第二个脚本。一旦它看到第二个已经完成,它就可以使用另一种类型的决策“关闭”工作流

    通过调用StartWorkflowExecution API,可以启动在每个主机上执行脚本的整个过程。这将在SWF中创建整个进程的记录,并将第一个历史记录踢出决策器进程,以计划在第一台主机上执行第一个脚本


    希望这能提供更多关于如何使用SWF完成这种类型的工作流的上下文。如果您还没有,我会查看SWF页面上的开发指南以获取更多信息。

    我认为您提出了一些非常好的问题,这些问题突出了SWF作为一项服务的帮助程度。简而言之,您不会告诉服务器协调它们之间的工作。在SWF服务的帮助下,您的决策者为您安排了这一切

    您的工作流程将按如下方式实施:

  • 向服务注册您的工作流及其活动(一次性)
  • 执行决策者和工人
  • 让你的工人和决策者跑吧
  • 启动一个新的工作流
  • 有许多方法可以将凭证输入boto.swf的代码中。出于本练习的目的,我建议在运行以下代码之前将它们导出到环境中:

    export AWS_ACCESS_KEY_ID=<your access key>
    export AWS_SECRET_ACCESS_KEY=<your secret key>
    
    2) 执行并运行决策者和员工

    # ab_decider.py
    import time
    import boto.swf.layer2 as swf
    
    DOMAIN = 'stackoverflow'
    ACTIVITY1 = 'ServerAActivity'
    ACTIVITY2 = 'ServerBActivity'
    VERSION = '1.0'
    
    class ABDecider(swf.Decider):
    
        domain = DOMAIN
        task_list = 'default_tasks'
        version = VERSION
    
        def run(self):
            history = self.poll()
            # Print history to familiarize yourself with its format.
            print history
            if 'events' in history:
                # Get a list of non-decision events to see what event came in last.
                workflow_events = [e for e in history['events']
                                   if not e['eventType'].startswith('Decision')]
                decisions = swf.Layer1Decisions()
                # Record latest non-decision event.
                last_event = workflow_events[-1]
                last_event_type = last_event['eventType']
                if last_event_type == 'WorkflowExecutionStarted':
                    # At the start, get the worker to fetch the first assignment.
                    decisions.schedule_activity_task('%s-%i' % (ACTIVITY1, time.time()),
                       ACTIVITY1, VERSION, task_list='a_tasks')
                elif last_event_type == 'ActivityTaskCompleted':
                    # Take decision based on the name of activity that has just completed.
                    # 1) Get activity's event id.
                    last_event_attrs = last_event['activityTaskCompletedEventAttributes']
                    completed_activity_id = last_event_attrs['scheduledEventId'] - 1
                    # 2) Extract its name.
                    activity_data = history['events'][completed_activity_id]
                    activity_attrs = activity_data['activityTaskScheduledEventAttributes']
                    activity_name = activity_attrs['activityType']['name']
                    # 3) Optionally, get the result from the activity.
                    result = last_event['activityTaskCompletedEventAttributes'].get('result')
    
                    # Take the decision.
                    if activity_name == ACTIVITY1:
                        # Completed ACTIVITY1 just came in. Kick off ACTIVITY2.
                        decisions.schedule_activity_task('%s-%i' % (ACTIVITY2, time.time()),
                            ACTIVITY2, VERSION, task_list='b_tasks', input=result)
                    elif activity_name == ACTIVITY2:
                        # Server B completed activity. We're done.
                        decisions.complete_workflow_execution()
    
                self.complete(decisions=decisions)
                return True
    
    worker要简单得多,如果不想使用继承,就不需要使用继承

    # ab_worker.py
    import os
    import time
    import boto.swf.layer2 as swf
    
    DOMAIN = 'stackoverflow'
    ACTIVITY1 = 'ServerAActivity'
    ACTIVITY2 = 'ServerBActivity'
    VERSION = '1.0'
    
    class MyBaseWorker(swf.ActivityWorker):
    
        domain = DOMAIN
        version = VERSION
        task_list = None
    
        def run(self):
            activity_task = self.poll()
            print activity_task
            if 'activityId' in activity_task:
                # Get input.
                # Get the method for the requested activity.
                try:
                    self.activity(activity_task.get('input'))
                except Exception, error:
                    self.fail(reason=str(error))
                    raise error
    
                return True
    
        def activity(self, activity_input):
            raise NotImplementedError
    
    class WorkerA(MyBaseWorker):
        task_list = 'a_tasks'
    
        def activity(self, activity_input):
            result = str(time.time())
            print 'worker a reporting time: %s' % result
            self.complete(result=result)
    
    class WorkerB(MyBaseWorker):
        task_list = 'b_tasks'
    
        def activity(self, activity_input):
            result = str(os.getpid())
            print 'worker b returning pid: %s' % result
            self.complete(result=result)
    
    3) 运行你的决策者和工人。 您的决策者和工作人员可能从不同的主机运行,或者从同一台机器运行。打开四个终端并运行您的演员:

    首先是你的决定者

    $ python -i ab_decider.py 
    >>> while ABDecider().run(): pass
    ... 
    
    然后工人A,您可以从服务器A执行此操作:

    $ python -i ab_workers.py 
    >>> while WorkerA().run(): pass
    
    然后是worker B,可能来自服务器B,但如果您从笔记本电脑上运行它们,它也可以正常工作:

    $ python -i ab_workers.py 
    >>> while WorkerB().run(): pass
    ... 
    
    4) 最后,启动工作流

    $ python
    Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
    [GCC 4.4.3] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import boto.swf.layer2 as swf
    >>> workflows = swf.Domain(name='stackoverflow').workflows()
    >>> workflows
    [<WorkflowType 'MyWorkflow-1.0' at 0xdeb1d0>]
    >>> execution = workflows[0].start(task_list='default_tasks')
    >>> 
    
    这只是一个连续执行活动的工作流示例,但决策者也可以这样做

    我希望这至少能让你开始。对于一个稍微复杂一点的串行工作流示例,我推荐

    好例子

    此外,如果不想将凭据导出到环境,可以在类内部调用:

    swf.set_default_credentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) 
    

    不幸的是,SNS没有我所需要的功能。非常感谢你,这是一个非常全面的回答。@oozie-回答得很好,非常棒的课程。需要在Boto文档中,谢谢您的回答!很高兴看到它如此具体。但我有一个问题:是什么迫使workerA只执行Activity1任务?是工人阶级的任务清单吗?是的。当工作人员轮询工作时,它会从特定的任务列表中请求任务
    >>> execution.history()
    [{'eventId': 1, 'eventType': 'WorkflowExecutionStarted', 
    'workflowExecutionStartedEventAttributes': {'taskList': {'name': 'default_tasks'}, 
    'parentInitiatedEventId': 0, 'taskStartToCloseTimeout': '300', 'childPolicy': 
    'TERMINATE', 'executionStartToCloseTimeout': '3600', 'workflowType': {'version': 
    '1.0', 'name': 'MyWorkflow'}}, 'eventTimestamp': 1361132267.5810001}, {'eventId': 2, 
    'eventType': 'DecisionTaskScheduled', 'decisionTaskScheduledEventAttributes': 
    {'startToCloseTimeout': '300', 'taskList': {'name': ...
    
    swf.set_default_credentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)