以库的形式,给每个function部署ingress和egress控制,实现分布式的串链调度。
Standalone orchestrator是一把双刃剑,一方面确实能够simplify development,但另一方面还会存在以下两个缺点: 一是灵活性不足、不能适用于所有应用;二是expensive to host and use。
为了实现application-level serverless orchestration,一个核心挑战是复杂有状态的orchestration pattern和强的执行保证。 这一点主要依托于scalable、strongly、consistent的数据存储解决。
Background
现有的两种解决办法
- trigger-based
- 不支持fan-n
- 每个function logic都要维护control-flow logic、笨重
- driver function
- 有运行时间限制
- double billing的问题
此外,以上两种orchestrator还需要开发者处理运维关系。
Standalone的问题
- hard
- yet another performance and scalability bottleneck
- expensive
- application-specific optimization
Design
主要是IR、一个ingress、一个egress。
IR支持三种调用
- Invoke
- Map
- FanIN
基于此,还提供以下调用
- Chain & Fan-out
- Map
- Branching
- Aggregation和Fold(这两种在3.4节介绍)
Execution Guarantees Using Checkpoints
最重要的目标是实现exactly-once的执行。 为此,Unum提出了两个insight
- 即使同样的invocation会产生不同的结果,只要保证下游函数总被这些结果中的其中一个触发,这样的执行就是对的
- 即使一个函数被调用多次,只要调用使用的是相同的输入,工作流的输出就是正确的
基于此,Unum提出了checkpoint机制,实现create_if_not_exist函数。 一个函数执行完之后首先会尝试写入,如果已经存在了,该操作就会失败。 总之,后续函数的执行依赖于上游函数的第一个成功的调用。
Fault Tolerance
因为failed functions也会导致反复执行,因此这一个section主要讲了对failed functions的适配过程。 核心是保证a single value is always used to invoke downstream functions。
Fan-in Patterns
Fan-in的挑战是所有branches结束后才能调用。 与其指定一个分支function作为coordinator,不如让所有分支都有权利在所有branch完成后调用函数。 具体操作就是每个branch完成后,都把自己写到一个set里面去,然后检查这个set的大小是否等于branch的个数。 如果等于就调用下游函数。
Garbage Collection
checkpoint和fan-in都维护了一些IR(checkpoints和coordination sets)。
对于checkpoint,垃圾回收机制由下游函数触发,因为它知道上游的checkpoint是不是还被需要。 在非fan-out情况下,一旦它自己生成了自己的checkpoint,就可以把上游的checkpoint删掉了。 在fan-out的情况下,维护一个类似于fan-in的set,每个branch生成了自己的checkpoint就把自己加入这个set里面,只要fan-out的branch个数等于set的大小,上游的checkpoint就可以删掉了。
fan-in类似。
Naming
需要一个确定的命名规则。
对于workflow invocation来说,在第一个函数入口处获取,要么自己生成、要么FaaS平台给。
对于function调用来说,由global function name、a vector of branch indexes和iteration numbers组成。