
# 使用FunctionGraph函数流对图片进行压缩和打水印
本章节主要介绍如何使用函数流实现流式大文件处理。您可以根据实际业务场景来创建快速函数流实现。
#### 背景与价值
Serverless Workflow由于自身可编排、有状态、持久化、可视化监控、异常处理、云服务集成等特性，适用于很多应用场景，比如：
- 复杂度高需要抽象的业务（订单管理，CRM 等）
- 业务需要自动中断 / 恢复能力，如多个任务之间需要人工干预的场景（人工审批，部署流水线等）
- 业务需要手动中断 / 恢复（数据备份 / 恢复等）
- 需要详细监控任务执行状态的场景
- 流式处理（日志分析，图片 / 视频处理等） 当前大部分 Serverless Workflow 平台更多关注控制流程的编排，忽视了工作流中数据流的编排和高效传输，上述场景[创建函数流触发器](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_0412.html)中，由于数据流相对简单，所以各大平台支持都比较好，但是对于文件转码等存在超大数据流的场景，当前各大平台没有给出很好的解决方案。华为云FunctionGraph函数工作流针对该场景，提出了 Serverless Streaming 的流式处理方案，支持毫秒级响应文件处理。
  
 
#### 技术原理
华为云FunctionGraph函数工作流提出 Serverless Streaming 的流式可编排的文件处理解决方案，步骤与步骤之间通过数据流驱动，更易于用户理解。本章通过图片处理的例子解释该方案的实现机制。
如果需要驱动一个工作流执行，工作流系统需要处理两个部分：
- 控制流：控制工作流的步骤间流转，以及步骤对应的 Serverless 函数的执行。确保步骤与步骤之间有序执行。
- 数据流：控制整个工作流的数据流转，通常来说上一个步骤的输出是下一个步骤的输入，比如上述图片处理工作流中，图片压缩的结果是打水印步骤的输入数据。
在普通的服务编排中，由于需要精准控制各个服务的执行顺序，所以控制流是工作流的核心部分。然而在文件处理等流式处理场景中，对控制流的要求并不高，以上述图片处理场景举例，可以对大图片进行分块处理，图片压缩和加水印的任务不需要严格的先后顺序，图片压缩处理完一个分块可以直接流转到下一个步骤，而不需要等待图片压缩把所有分块处理完再开始加水印的任务。
基于上述理解，华为云FunctionGraph工作流的 Serverless Streaming 方案架构设计如下图所示：
![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002130040202.png "点击放大")
在 Serverless Streaming 的流程中，弱化控制流中步骤之间的先后执行顺序，允许异步同时执行，步骤与步骤之间的交互通过数据流驱动。其中数据流的控制通过 Stream Bridge 组件来实现。同时函数 SDK 增加流式数据返回接口，用户不需要将整个文件内容返回，而是通过 gRPC Stream 的方式将数据写入到 Stream Bridge，Stream Bridge 用来分发数据流到下一个步骤的函数 Pod 中。
#### 操作步骤
1. 创建一个图片压缩的函数，其中代码在处理返回数据通过 ctx.Write() 函数将结果以流式数据的形式返回： 
   ![](https://support.huaweicloud.com/bestpractice-functiongraph/public_sys-resources/note_3.0-zh-cn.png)
   目前只支持go函数！
   ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002130198370.png "点击放大")
   FunctionGraph 通过 ctx.Write() 函数提供了流式返回的能力，对开发者来说，只需要将最终结果通过流的方式返回，而不需要关注网络传输的细节。
   
   
2. 在 FunctionGraph 的函数流控制台完成工作流编排，举例如下。 
   ![](https://support.huaweicloud.com/bestpractice-functiongraph/zh-cn_image_0000002165399697.png "点击放大")
   
   
   
3. 调用工作流的同步执行接口，获取最终结果的文件流，数据将以 chunked 流式返回的方式返回到客户端。
 
