10分钟上手!用Temporal Python SDK触发Flink SQL工作流
【免费下载链接】sdk-python Temporal Python SDK 项目地址: 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装饰器定义,支持同步和异步执行。
图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将负责:
- 接收Flink SQL任务参数
- 调用Flink SQL执行Activity
- 处理执行结果,更新任务状态
# 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"))
这个客户端代码负责:
- 连接到Temporal服务(默认地址localhost:7233)
- 生成唯一的工作流ID
- 启动FlinkSQLWorkflow工作流
- 等待工作流完成并返回结果
项目结构与依赖
完整的项目结构如下:
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 项目地址: https://gitcode.com/GitHub_Trending/sd/sdk-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



