stackstorm 24. 源码分析之----stackstorm的rulesengine服务分析---1

本文深入探讨了StackStorm的RulesEngine服务,主要关注`st2reactor`模块的`rulesengine`服务。从主入口点`_setup`和`_run_worker`开始,分析了如何启动`TriggerInstanceDispatcher`工作线程,以及`St2Timer`的`start`方法,详细阐述了定时任务的注册和调度过程,涉及`APScheduler`的使用,以及触发器类型的注册和处理流程。
摘要由CSDN通过智能技术生成

目标:
弄清楚st2rulesengine服务原理


1 总入口
st2/st2reactor/st2reactor/cmd/rulesengine.py
def main():
    try:
        _setup()
        return _run_worker()
    except SystemExit as exit_code:
        sys.exit(exit_code)
    except:
        LOG.exception('(PID=%s) RulesEngine quit due to exception.', os.getpid())
        return 1
    finally:
        _teardown()

1.1 进入_setup
def _setup():
    common_setup(service='rulesengine', config=config, setup_db=True, register_mq_exchanges=True,
                 register_signal_handlers=True)

1.2 进入_run_worker
def _run_worker():
    LOG.info('(PID=%s) RulesEngine started.', os.getpid())

    timer = None
    rules_engine_worker = worker.get_worker()

    try:
        timer_thread = None
        if cfg.CONF.timer.enable:
            timer = St2Timer(local_timezone=cfg.CONF.timer.local_timezone)
            timer_thread = eventlet.spawn(_kickoff_timer, timer)
            LOG.info(TIMER_ENABLED_LOG_LINE)
        else:
            LOG.info(TIMER_DISABLED_LOG_LINE)
        rules_engine_worker.start()
        if timer:
            return timer_thread.wait() and rules_engine_worker.wait()
        else:
            return rules_engine_worker.wait()
    except (KeyboardInterrupt, SystemExit):
        LOG.info('(PID=%s) RulesEngine stopped.', os.getpid())
        rules_engine_worker.shutdown()
    except:
        LOG.exception('(PID:%s) RulesEngine quit due to exception.', os.getpid())
        return 1
    finally:
        if timer:
            timer.cleanup()

    return 0


分析:
1.2.1 分析
rules_engine_worker = worker.get_worker()

进入:
/opt/stackstorm/st2/lib/python2.7/site-packages/st2reactor/rules/worker.py(111)get_worker()
    
(Pdb) p rules_engine_worker
<st2reactor.rules.worker.TriggerInstanceDispatcher object at 0x2fe3a10>
(Pdb) p rules_engine_worker.__dict__
{'_consumer_thread': None, '_queue_consumer': <st2common.transport.consumers.StagedQueueConsumer object at 0x2fe3f90>, 'rules_engine': <st2reactor.rules.engine.RulesEngine object at 0x1642450>}
(Pdb) p type(rules_engine_worker)
<class 'st2reactor.rules.worker.TriggerInstanceDispatcher'>

分析:
这里的rules_engine_worker实际上是消息处理类,是st2reactor.rules.worker.TriggerInstanceDispatcher对象。
TriggerInstanceDispatcher的基类是
st2/st2common/st2common/transport/consumers.py的MessageHandler类,这个类包含
_queue_consumer对象,这个对象包含处理消息的对象,即MessageHandler类的子类对象,每个继承自
MessageHandler类的子类必须实现process(message)方法用于处理消息。

1.2.2 分析
timer = St2Timer(local_timezone=cfg.CONF.timer.local_timezone)
......
timer_thread = eventlet.spawn(_kickoff_timer, timer)
具体参见 2 的分析


1.2.3 分析
rules_engine_worker = worker.get_worker()
......
rules_engine_worker.start()
具体参见3的分析


2 分析St2Timer类的start方法
timer = St2Timer(local_timezone=cfg.CONF.timer.local_timezone)
......
timer_thread = eventlet.spawn(_kickoff_timer, timer)
其中:
def _kickoff_timer(timer):
    timer.start()

2.1 分析
class St2Timer(object):
    """
    A timer interface that uses APScheduler 3.0.
    """
    def __init__(self, local_timezone=None):
        self._timezone = local_timezone
        self._scheduler = BlockingScheduler(timezone=self._timezone)
        self._jobs = {}
        self._trigger_types = TIMER_TRIGGER_TYPES.keys()
        self._trigger_watcher = TriggerWatcher(create_handler=self._handle_create_trigger,
                                               update_handler=self._handle_update_trigger,
                                               delete_handler=self._handle_delete_trigger,
                                               trigger_types=self._trigger_types,
                                               queue_suffix=self.__class__.__name__,
                                               exclusive=True)
        self._trigger_dispatcher = TriggerDispatcher(LOG)

    def start(self):
        self._register_timer_trigger_types()
        self._trigger_watcher.start()
        self._scheduler.start()

2.2)分析 
self._register_timer_trigger_types()
进入:
    def _register_timer_trigger_types(self):
        return trigger_services.add_trigger_models(TIMER_TRIGGER_TYPES.values())
分析:
_register_timer_trigger_types(self)调用add_trigger_models(trigger_types):

2.2.1) 分析
进入: st2/st2common/st2common/services/triggers.py
def add_trigger_models(trigger_types):
    """
    Register trigger types.

    :param trigger_types: A list of triggers to register.
    :type trigger_types: ``list`` of ``dict``

    :rtype: ``list`` of ``tuple`` (trigger_type, trigger)
    """
    [r for r in (_validate_trigger_type(trigger_type)
     for trigger_type in trigger_types) if r is not None]

    result = []
    for trigger_type in trigger_types:
        item = _add_trigger_models(trigger_type=trigger_type)

        if item:
            result.append(item)

    return result

分析:
add_trigger_models(trigger_types):
1 根据输入参数,形如:
(Pdb) p trigger_types
[{'payload_schema': {'type': 'object', 'properties': {'executed_at': {'default': '2014-07-30 05:04:24.578325', 'type': 'string', 'format': 'date-time'}, 'schedule': {'default': {'units': 'seconds', 'delta': 30}, 'type': 'object'}}}, 'description': 'Triggers on specified intervals. e.g. every 30s, 1week etc.', 'parameters_schema': {'additionalProperties': False, 'type': 'object', 'properties': {'timezone': {'type': 'string'}, 'unit': {'enum': ['weeks', 'days', 'hours', 'minutes', 'seconds'], 'required': True}, 'delta': {'required': True, 'type': 'integer'}}}, 'name': 'st2.IntervalTimer', 'pack': 'core'}, {'payload_schema': {'type': 'object', 'properties': {'executed_at': {'default': '2014-07-30 05:04:24.578325', 'type': 'string', 'format': 'date-time'}, 'schedule': {'default': {'units': 'seconds', 'delta': 30}, 'type': 'object'}}}, 'description': 'Triggers exactly once when the current time matches the specified time. e.g. timezone:UTC date:2014-12-31 23:59:59.', 'parameters_schema': {'additionalProperties': False, 'type': 'object', 'properties': {'date': {'required': True, 'type': 'string', 'format': 'date-time'}, 'timezone': {'type': 'string'}}}, 'name': 'st2.DateTimer', 'pack': 'core'}, {'payload_schema': {'type': 'object', 'properties': {'executed_at': {'default': '2014-07-30 05:04:24.578325', 'type': 'string', 'format': 'date-time'}, 'schedule': {'default': {'units': 'seconds', 'delta': 30}, 'type': 'object'}}}, 'description': 'Triggers whenever current time matches the specified time constaints like a UNIX cron scheduler.', 'parameters_schema': {'additionalProperties': False, 'type': 'object', 'properties': {'week': {'minimum': 1, 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'maximum': 53}, 'end_date': {'type': 'string', 'format': 'date-time'}, 'month': {'minimum': 1, 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'maximum': 12}, 'second': {'minimum': 0, 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'maximum': 59}, 'year': {'anyOf': [{'type': 'string'}, {'type': 'integer'}]}, 'timezone': {'type': 'string'}, 'day': {'minimum': 1, 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'maximum': 31}, 'minute': {'minimum': 0, 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'maximum': 59}, 'hour': {'minimum': 0, 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'maximum': 23}, 'day_of_week': {'minimum': 0, 'anyOf': [{'type': 'string'}, {'type': 'integer'}], 'maximum': 6}, 'start_date': {'type': 'string', 'format': 'date-time'}}}, 'name': 'st2.CronTimer', 'pack': 'core'}]
2 遍历trigger_types列表,,每个trigger_type,调用_add_trigger_models(trigger_type)

2.2.2) 分析_add_trigger_models方法
def _add_trigger_models(trigger_type):
    pack = trigger_type['pack']
    description = trigger_type['description'] if 'description' in trigger_type else ''
    payload_schema = trigger_type['payload_schema'] if 'payload_schema' in trigger_type else {}
    parameters_schema = trigger_type['parameters_schema'] \
        if 'parameters_schema' in trigger_type else {}
    tags = trigger_type.get('tags', [])

    trigger_type = _create_trigger_type(
        pack=pack,
        name=trigger_type['name'],
        description=description,
        payload_schema=payload_schema,
        parameters_schema=parameters_schema,
        tags=tags
    )
    trigger = _create_trigger(trigger_type=trigger_type)
    return (trigger_type, trigger)

分析:
_add_trigger_models(trigger_type):
1 根据输入参数,形如:
(Pdb) p trigger_type
{'payload_schema': {'type': 'object', 'properties': {'executed_at': {'default': '2014-07-30 05:04:24.578325', 'type': 'string', 'format': 'date-time'}, 'schedule': {'default': {'units': 'seconds', 'delta': 3

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: StackStorm是一个开源自动化工具,用于创建、管理和执行工作流和自动化任务。Docker Compose是一个工具,用于定义和运行多个Docker容器的应用程序。StackStorm提供了一个Docker Compose配置文件(docker-compose.yaml),用于快速部署StackStorm服务。 这个docker-compose.yaml文件中包含了StackStorm的各个组件的配置信息。首先,它定义了要使用的基础镜像,如StackStorm工作者(worker)和队列服务(rabbitmq)。然后,它指定了各个容器的名称、端口映射和网络配置。 在docker-compose.yaml文件中,还定义了stackstorm服务容器的环境变量,用于指定配置参数,如数据库连接、日志级别等。此外,还可以定义其他容器的环境变量,以满足不同组件的需求。 通过运行docker-compose命令,可以根据这个配置文件来创建和启动StackStorm服务容器。Docker Compose会自动解析和处理配置文件中的依赖关系,并按照定义的顺序启动容器。这可以让我们快速部署和管理StackStorm服务,并且方便地进行扩展和升级。 总之,StackStorm的docker-compose.yaml文件是用来定义和管理StackStorm服务容器的配置文件。它提供了一种简便的方式来部署和管理StackStorm,使得自动化工作流和任务的创建和执行更加方便和高效。 ### 回答2: StackStorm 是一个开源自动化平台,可以用于自动化各类任务和流程。Docker Compose 是一个用于定义和运行多个 Docker 容器的工具。一般来说,使用 Docker Compose 可以轻松地将 StackStorm 部署到 Docker 容器中。 stackstorm docker-compose.yaml 是一个用于在 Docker Compose 中定义 StackStorm 的配置文件。这个文件包含了 StackStorm 中的各个组件以及它们的配置。在编写这个文件时,我们可以指定 StackStorm 需要运行的容器数量、容器之间的依赖关系等。 通常,stackstorm docker-compose.yaml 包含以下几个部分: 1. Services 部分:这里定义了 StackStorm 中的各个组件的容器。比如,可以指定一个容器运行 StackStorm Web UI,另一个容器运行 StackStorm 后台服务,还可以有其他的容器用于运行 StackStorm 的数据库、消息队列等。 2. Networks 部分:这里定义了容器之间的网络连接方式。可以指定容器使用的网络模式,如桥接模式或者主机模式,以及容器之间的连接关系。 3. Volumes 部分:这里定义了容器中的数据卷。可以将 StackStorm 需要的数据持久化保存到宿主机上的指定目录,以便容器重启后能够恢复数据。 通过编写 stackstorm docker-compose.yaml 文件,并使用 Docker Compose 工具进行部署,可以快速搭建 StackStorm 环境,并保证该环境的可复制性和可移植性。同时,使用 Docker Compose 也方便了 StackStorm 的管理和维护工作,简化了容器之间的依赖关系管理。 ### 回答3: StackStorm是一个开源的自动化平台,它允许用户将不同的任务组织成工作流,并通过事件触发来自动化执行。Docker Compose是一个用于定义和运行多容器Docker应用程序的工具。 在StackStorm中使用Docker Compose,可以帮助我们更方便地部署和管理StackStorm的相关容器和服务。通过编写docker-compose.yaml文件,我们可以定义StackStorm容器的配置和依赖关系。 Docker Compose使用一种声明性的语法来定义应用程序的配置。在docker-compose.yaml文件中,我们可以指定StackStorm容器的镜像、环境变量、端口映射等配置。我们还可以定义其他依赖容器,例如数据库容器,用于支持StackStorm的运行。 以下是一个示例的docker-compose.yaml文件的片段: ``` version: '3.8' services: stackstorm: image: stackstorm/stackstorm:3.3.0 ports: - 443:443 - 80:80 environment: - ST2_VERSION=3.3.0 - ST2_AUTH_USERNAME=admin - ST2_AUTH_PASSWORD=MyPassword depends_on: - postgres postgres: image: postgres:12 environment: - POSTGRES_USER=stackstorm - POSTGRES_PASSWORD=stackstorm ``` 在这个示例中,我们定义了两个服务stackstorm和postgres。stackstorm服务使用了stackstorm/stackstorm:3.3.0镜像,将443端口和80端口映射到宿主机。我们还指定了一些环境变量,用于配置StackStorm的版本和管理员账号密码。在depends_on部分,我们指定了stackstorm服务依赖于postgres服务。 通过运行docker-compose up命令,Docker Compose将会根据docker-compose.yaml文件创建并启动相应的容器。这样,我们就能够方便地使用Docker Compose来部署和管理StackStorm的相关容器和服务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值