1 - DurableTask介绍

DurableTask介绍和资料收集

1.1 - DurableTask概述

DurableTask概述

durabletask-go github首页的介绍

https://github.com/microsoft/durabletask-go

持久任务框架(Durable Task Framework)是一个轻量级、可嵌入的引擎,用于将持久、容错的业务逻辑(协调)编写成普通代码。该引擎本身是用 Go 语言编写的,旨在嵌入到其他基于 Go 的进程中。它暴露了一个 gRPC 端点,支持用任何语言编写持久流。目前,.NET 和 Java 的 SDK 都能使用该 gRPC 端点,未来还会有更多。也可以直接用 Go 编写协调,并在本地进程中运行。

该项目在很大程度上是对基于.NET 的持久任务框架 的 Go 克隆,微软的多个云服务团队都使用该框架来构建可靠的控制平面和管理基础架构。它还从Go Workflows项目中汲取了灵感,而Go Workflows项目本身也是一个 Go 项目,大量借鉴了 Durable Task Framework 和Temporal。主要区别在于 Durable Task 引擎设计用于 sidecar 架构。

2 - 项目构建

DurableTask 项目构建

2.1 - 项目构建

DurableTask 项目构建

参考: https://github.com/microsoft/durabletask-go#building-the-project

准备工作

clone 仓库

mkdir durabletask
cd durabletask

git clone --recurse-submodules git@github.com:microsoft/durabletask-go.git
cd durabletask-go

如果没有使用 --recurse-submodules 参数就执行了 clone 操作,则需要:

git submodule init
git submodule update

# 或者直接
git submodule update --init --recursive

这个时候 submodules/durabletask-protobuf 目录下就会出现相关的文件。

  • submodules/durabletask-protobuf/protos/orchestrator_service.proto

构建

构建go项目

go mod tidy
go mod vendor

生成 protobuf 文件

使用以下命令重新生成子模块的 protobuf。在更新子模块引用时使用该命令。

 # NOTE: assumes the .proto file defines: option go_package = "/internal/protos"
protoc --go_out=. --go-grpc_out=. -I submodules/durabletask-protobuf/protos orchestrator_service.proto

生成的文件会存放在:

  • internal/protos/orchestrator_service_grpc.pb.go
  • internal/protos/orchestrator_service.pb.go

生成命令执行完成之后,会发现新生成的代码和之前在仓库中提交的代码有很大的不同,这时因为 protoc-gen-go-grpc 和 protoc 版本不同造成的。

仓库中已经提交的版本是:

// - protoc-gen-go-grpc v1.3.0
// - protoc             v3.12.4

而我本地的版本是:

// - protoc-gen-go-grpc v1.2.0
// - protoc             v3.21.12

所以如果真的要生成新的文件并提交,必须使用同样的版本。

重新安装 protobuffer 工具

重新安装 protoc

mkdir -p ~/temp
cd ~/temp

wget https://github.com/protocolbuffers/protobuf/releases/download/v3.12.4/protoc-3.12.4-linux-x86_64.zip
unzip protoc-3.12.4-linux-x86_64.zip

sudo cp -r include/google/ /usr/local/include/
sudo chmod -R 755 /usr/local/include/google
sudo cp bin/protoc /usr/local/bin/
sudo chmod +x /usr/local/bin/protoc

检验:

$ protoc --version
libprotoc 3.12.4

重新安装 protoc-gen-go-grpc

protoc-gen-go-grpc 安装的是 v1.2.0 版本,需要更换为 durabletask 要求的 v1.3.0。执行下面这个命令就可以覆盖之前安装的版本:

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.3.0

重新安装 protoc-gen-go

protoc-gen-go 安装的是 v1.28.1 版本,需要更换为 durabletask 要求的 v1.31.0。执行下面这个命令就可以覆盖之前安装的版本:

go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.31.0

小结

重新安装完成 protobuf 相关的工具后,再次执行 protoc 命令生成代码就没有问题:

protoc --go_out=. --go-grpc_out=. -I submodules/durabletask-protobuf/protos orchestrator_service.proto

建议

由于 durabletask-go 和 durabletask-java 两个项目都需要用到 protoc 来生成 go 和 java 代码,但是他们两个用的 protoc 版本又不一样,因此最好是搭建两套不同的开发环境,分别安装各自要求的 protoc 版本。

暂时我的实现是开了两个虚拟机,dev101 负责 durabletask-java , dev102 负责 durabletask-go。

3 - proto定义

DurableTask proto定义

3.1 - orchestrator service proto定义

orchestrator service 的 proto 定义

背景

internal/protos/orchestrator_service.pb.go

proto文件的地址是:

  • submodules/durabletask-protobuf/protos/orchestrator_service.proto

生成的文件是:

  • internal/protos/orchestrator_service_grpc.pb.go
  • internal/protos/orchestrator_service.pb.go

定义

proto 定义的 service 名为 TaskHubSidecarService:

service TaskHubSidecarService {
......
}

Hello 方法

    // Sends a hello request to the sidecar service.
    rpc Hello(google.protobuf.Empty) returns (google.protobuf.Empty);

StartInstance 方法

    // Starts a new orchestration instance.
    rpc StartInstance(CreateInstanceRequest) returns (CreateInstanceResponse);
}

CreateInstanceRequest 字段

```protobuf
    message CreateInstanceRequest {
    string instanceId = 1;
    string name = 2;
    google.protobuf.StringValue version = 3;
    google.protobuf.StringValue input = 4;
    google.protobuf.Timestamp scheduledStartTimestamp = 5;
    OrchestrationIdReusePolicy orchestrationIdReusePolicy = 6;
}

TBD
- version: 这个 version 是做什么的?和版本控制有什么关系?
- input: 为什么是 string 类型?

CreateInstanceResponse 只有一个 instanceId id 字段:

```protobuf
message CreateInstanceResponse {
    string instanceId = 1;
}

GetInstance 方法

    // Gets the status of an existing orchestration instance.
    rpc GetInstance(GetInstanceRequest) returns (GetInstanceResponse);
message GetInstanceRequest {
    string instanceId = 1;
    bool getInputsAndOutputs = 2;
}

message GetInstanceResponse {
    bool exists = 1;
    OrchestrationState orchestrationState = 2;
}

message OrchestrationState {
    string instanceId = 1;
    string name = 2;
    google.protobuf.StringValue version = 3;
    OrchestrationStatus orchestrationStatus = 4;
    google.protobuf.Timestamp scheduledStartTimestamp = 5;
    google.protobuf.Timestamp createdTimestamp = 6;
    google.protobuf.Timestamp lastUpdatedTimestamp = 7;
    google.protobuf.StringValue input = 8;
    google.protobuf.StringValue output = 9;
    google.protobuf.StringValue customStatus = 10;
    TaskFailureDetails failureDetails = 11;
}

CreateTaskHub 方法

    // Deletes and Creates the necessary resources for the orchestration service and the instance store
    rpc CreateTaskHub(CreateTaskHubRequest) returns (CreateTaskHubResponse);
message CreateTaskHubRequest {
    bool recreateIfExists = 1;
}

message CreateTaskHubResponse {
    //no playload
}