10分钟上手!用Temporal Python SDK触发Flink SQL工作流

10分钟上手!用Temporal Python SDK触发Flink SQL工作流

【免费下载链接】sdk-python Temporal Python SDK 【免费下载链接】sdk-python 项目地址: https://gitcode.com/GitHub_Trending/sd/sdk-python

你是否还在为实时数据流处理与任务调度的衔接而烦恼?当Flink SQL的高效计算遇上Temporal的可靠编排,会碰撞出怎样的火花?本文将带你通过一个实际场景,快速掌握如何用Temporal Python SDK触发Flink SQL工作流,解决数据处理中的定时执行、失败重试和状态管理难题。读完本文,你将获得:

  • 一个可直接运行的Flink SQL任务调度示例
  • Temporal Workflow与Activity的核心编码模式
  • 实时数据流处理的状态管理最佳实践

场景痛点:Flink SQL任务的调度困境

假设你负责一个电商平台的实时销售分析系统,需要每天凌晨3点执行Flink SQL任务处理前一天的销售数据,并生成报表。传统解决方案可能会遇到以下问题:

  • 服务器重启导致定时任务丢失
  • 任务失败后无法自动重试或需要人工介入
  • 难以追踪任务执行状态和历史记录
  • 无法灵活调整任务执行时间或依赖关系

Temporal作为一个分布式工作流编排平台,能完美解决这些问题。下面我们将通过代码示例,展示如何用Temporal Python SDK构建一个可靠的Flink SQL任务调度系统。

核心概念:Temporal工作流基础

在开始编码前,我们先了解两个核心概念:

  • Workflow(工作流):定义任务的执行逻辑和状态,是Temporal的基本执行单元。使用@workflow.defn装饰器定义,通过@workflow.run指定入口方法。
  • Activity(活动):工作流中的具体执行步骤,代表一个独立的任务。使用@activity.defn装饰器定义,支持同步和异步执行。

Temporal工作流结构

图1:Temporal工作流与活动关系示意图

实战步骤1:定义Flink SQL执行活动

首先,我们需要创建一个执行Flink SQL的Activity。这个Activity将接收SQL语句和执行参数,调用Flink API执行查询,并返回结果。

# temporalio/flink_activities.py
from temporalio import activity
import pyflink.table as TableEnvironment

@activity.defn(name="execute_flink_sql")
async def execute_flink_sql(sql: str, job_name: str) -> dict:
    """执行Flink SQL查询的Activity"""
    # 创建Flink Table环境
    t_env = TableEnvironment.create(TableEnvironment.EnvironmentSettings.in_streaming_mode())
    
    try:
        # 执行SQL
        result = t_env.execute_sql(sql)
        # 等待作业完成
        job_client = result.get_job_client().result()
        job_execution_result = job_client.get_job_execution_result(result.job_id()).result()
        
        # 返回执行结果
        return {
            "status": "success",
            "job_name": job_name,
            "job_id": str(result.job_id()),
            "metrics": job_execution_result.get_accumulator_results()
        }
    except Exception as e:
        activity.logger.error(f"Flink SQL执行失败: {str(e)}")
        raise activity.ActivityError(f"Flink SQL执行失败: {str(e)}")

这个Activity使用@activity.defn装饰器标记,指定了名称为"execute_flink_sql",接收SQL语句和作业名称两个参数,返回包含执行状态和指标的字典。通过activity.logger可以记录日志,便于问题排查。

实战步骤2:设计工作流逻辑

接下来,我们创建一个Workflow来编排Flink SQL任务的执行流程。这个Workflow将负责:

  1. 接收Flink SQL任务参数
  2. 调用Flink SQL执行Activity
  3. 处理执行结果,更新任务状态
# temporalio/flink_workflows.py
from temporalio import workflow
from datetime import timedelta
from .flink_activities import execute_flink_sql

@workflow.defn
class FlinkSQLWorkflow:
    @workflow.run
    async def run(self, sql: str, job_name: str, schedule_time: str = None) -> dict:
        """Flink SQL工作流入口方法"""
        workflow.logger.info(f"开始执行Flink SQL工作流: {job_name}")
        
        # 设置Activity超时时间
        activity_options = workflow.ActivityOptions(
            start_to_close_timeout=timedelta(minutes=30),
            retry_policy=workflow.RetryPolicy(
                maximum_attempts=3,
                initial_interval=timedelta(seconds=10),
                backoff_coefficient=2.0
            )
        )
        
        # 执行Flink SQL Activity
        result = await workflow.execute_activity(
            execute_flink_sql,
            sql,
            job_name,
            start_to_close_timeout=activity_options.start_to_close_timeout,
            retry_policy=activity_options.retry_policy
        )
        
        # 记录工作流完成状态
        workflow.logger.info(f"Flink SQL工作流完成: {job_name}, 结果: {result}")
        return {
            "workflow_id": workflow.info().workflow_id,
            "run_id": workflow.info().run_id,
            "result": result
        }

在这个Workflow中:

  • 使用@workflow.defn装饰器标记工作流类
  • @workflow.run标记入口方法
  • 通过workflow.execute_activity调用之前定义的Activity
  • 设置了30分钟的Activity超时时间和最多3次的重试策略
  • 使用workflow.logger记录工作流执行日志

实战步骤3:启动工作流并监控执行

最后,我们需要创建一个客户端来启动工作流,并监控其执行状态。

# temporalio/flink_client.py
import asyncio
from temporalio import client
from .flink_workflows import FlinkSQLWorkflow

async def start_flink_workflow(sql: str, job_name: str) -> dict:
    """启动Flink SQL工作流"""
    # 连接Temporal服务
    client = await client.Client.connect("localhost:7233")
    
    # 生成工作流ID
    workflow_id = f"flink-sql-{job_name}-{datetime.now().strftime('%Y%m%d%H%M%S')}"
    
    # 启动工作流
    handle = await client.start_workflow(
        FlinkSQLWorkflow.run,
        sql,
        job_name,
        id=workflow_id,
        task_queue="flink-sql-task-queue"
    )
    
    print(f"工作流已启动: {workflow_id}, run_id: {handle.run_id}")
    
    # 等待工作流完成并返回结果
    result = await handle.result()
    return result

if __name__ == "__main__":
    # 示例SQL:计算每日销售额
    sales_sql = """
        INSERT INTO daily_sales_report
        SELECT 
            DATE_FORMAT(order_time, 'yyyy-MM-dd') as order_date,
            SUM(amount) as total_sales,
            COUNT(DISTINCT order_id) as order_count
        FROM orders
        WHERE order_time >= DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY)
          AND order_time < CURRENT_DATE
        GROUP BY DATE_FORMAT(order_time, 'yyyy-MM-dd')
    """
    
    # 启动工作流
    asyncio.run(start_flink_workflow(sales_sql, "daily_sales_report"))

这个客户端代码负责:

  1. 连接到Temporal服务(默认地址localhost:7233)
  2. 生成唯一的工作流ID
  3. 启动FlinkSQLWorkflow工作流
  4. 等待工作流完成并返回结果

项目结构与依赖

完整的项目结构如下:

temporalio/
├── __init__.py
├── activity.py          # 基础Activity定义
├── client.py            # Temporal客户端
├── workflow.py          # 基础Workflow定义
├── flink_activities.py  # Flink SQL执行Activity
├── flink_workflows.py   # Flink SQL工作流
└── flink_client.py      # 工作流启动客户端

需要的主要依赖包括:

  • temporalio>=1.0.0
  • apache-flink>=1.15.0
  • python-dateutil>=2.8.2

可以通过以下命令安装依赖:

pip install temporalio apache-flink python-dateutil

扩展与最佳实践

1. 状态管理与查询

Temporal提供了查询功能,可以在工作流执行过程中获取当前状态。我们可以为Flink SQL工作流添加一个查询方法:

@workflow.query
def get_status(self) -> str:
    """获取工作流当前状态的查询方法"""
    return self._status

2. 定时执行与调度

如果需要定期执行Flink SQL任务,可以使用Temporal的CronSchedule功能:

await client.start_workflow(
    FlinkSQLWorkflow.run,
    sql,
    job_name,
    id=workflow_id,
    task_queue="flink-sql-task-queue",
    cron_schedule="0 3 * * *"  # 每天凌晨3点执行
)

3. 错误处理与告警

可以通过Temporal的Signal功能实现工作流的外部干预,例如取消执行或更新参数:

@workflow.signal
def cancel_execution(self, reason: str) -> None:
    """取消工作流执行的Signal"""
    self._should_cancel = True
    self._cancel_reason = reason

总结与展望

通过本文的示例,我们展示了如何使用Temporal Python SDK来编排和调度Flink SQL任务。这种方式的优势在于:

  • 可靠性:自动重试和故障恢复,确保任务完成
  • 可观测性:完整的执行历史和状态追踪
  • 灵活性:支持定时执行、依赖编排和外部干预
  • 可扩展性:轻松扩展为多步骤、复杂依赖的工作流

未来,我们可以进一步探索:

  • 集成Flink的状态管理功能
  • 实现更复杂的数据流处理管道
  • 与监控系统集成,实现自动告警

希望本文能帮助你快速上手Temporal Python SDK与Flink的集成,构建更可靠、高效的实时数据处理系统。

项目仓库地址:https://gitcode.com/GitHub_Trending/sd/sdk-python

【免费下载链接】sdk-python Temporal Python SDK 【免费下载链接】sdk-python 项目地址: https://gitcode.com/GitHub_Trending/sd/sdk-python

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值