Temporal微服务编排器是时间平台的关键组成部分,在微服务相互交互以完成复杂的工作流程时,它们提供了协调和管理。乐队提供了诸如任务管理,错误处理,重试和补偿等功能,以确保即使面对失败或意外事件,也可以准确,一致地执行工作流程。
在应用程序开发中使用时间段可以帮助简化复杂的,时间敏感的工作流程的开发,并提高应用程序的可靠性和可扩展性。通过使用临时协调员,开发人员可以专注于实施其业务逻辑,并将基础微服务的协调和管理放在平台上。
插图
微服务体系结构在XYZ公司中使用。微服务方法的软件开发方法可以帮助他们的团队更快地部署,但它带来了一些问题,其中之一就是数据一致性。如何将微服务的数据变化传播到微服务B和C?通过活动发送吗?
是的,这有效,但是如果B更新自身并且C有打ic,并且无法进行更新?
那么这意味着我们需要有一种机制,使我们能够处理此类失败,进行重试以及还有什么?上面描述的几个情况需要我们写失败和重试逻辑?
因此,将暂时性用作微服务编排器有助于我们解决上述问题。
先决条件
本教程的先决条件正在Go和Docker安装和配置。
通过打开命令提示符并键入以下命令
来验证您已安装了已安装的操作
go version
它应该返回类似于此的东西
go version go1.19.3 darwin/amd64
此外,还安装了
的验证码头
docker --version
#Docker version 20.10.22, build 3a2c30b
选择
暂时性可以在您的项目目录内外使用,只要您的应用程序可以访问它即可。您的个人需求和项目的基础架构将决定您的选择。
如果您决定在项目目录内执行时间内执行时间内执行时间,则维护项目的依赖项和设置可能会更简单。但是,在项目目录之外运行时间段可能会提高关注程度的分离程度,并使管理共享单个时间实例的众多项目变得更加简单。
但是,在本指南中,我们将运行项目目录内的临时服务器。
Hello-workflow
我们将使用简单的Hello-Workflow来编排分布式系统中的任务。入门者和工人是使分布式系统运行的两个主要组件,在本指南中,我们将实施起动器和工人。
这是我们的项目目录的外观。
├── dynamicconfig
│ ├── development-cass.yaml
│ └── development-sql.yaml
| └── docker.yaml
|
├── src
│ ├── helloworkflow
| | └── workflow.go
│ ├── starter
| | └── main.go
| └── worker
| └── main.go
├── .env
├── docker-compose.yml
您创建一个新的GO项目,例如TutorialGuide和CD,然后在文本编辑器上打开目录。您可以在项目的根目录中创建DynamicConfig文件夹,并添加3个YAML文件。这些文件需要使临时服务器上升。
# development-cass.yaml
system.forceSearchAttributesCacheRefreshOnRead:
- value: true # Dev setup only. Please don't turn this on in production.
constraints: {}
# development-sql.yaml
limit.maxIDLength:
- value: 255
constraints: {}
system.forceSearchAttributesCacheRefreshOnRead:
- value: true # Dev setup only. Please don't turn this on in production.
constraints: {}
# docker.yaml
apiVersion: v1
clusters:
- cluster:
certificate-authority: path-to-your-ca.rt #e.g/System/Volumes/Data/Users/<name>/.minikube/ca.crt
server: https://192.168.99.100:8443
name: minikube
contexts:
- context:
cluster: minikube
user: minikube
name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
user:
client-certificate: path-to-proxy-client-ca.key #e.g/System/Volumes/Data/Users/<name>/.minikube/proxy-client-ca.key
client-key: path-to-proxy-client-ca.key #e.g/System/Volumes/Data/Users/<name>/.minikube/proxy-client-ca.key
使用docker.yaml
文件覆盖默认的动态配置值(创建服务配置时将指定它们)。有关docker.yaml文件以及如何使用它的更多信息[https://github.com/temporalio/docker-compose/tree/main/dynamicconfig]
# docker-compose.yaml
version: '3.5'
services:
elasticsearch:
container_name: temporal-elasticsearch
environment:
- cluster.routing.allocation.disk.threshold_enabled=true
- cluster.routing.allocation.disk.watermark.low=512mb
- cluster.routing.allocation.disk.watermark.high=256mb
- cluster.routing.allocation.disk.watermark.flood_stage=128mb
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms256m -Xmx256m
- xpack.security.enabled=false
image: elasticsearch:${ELASTICSEARCH_VERSION}
networks:
- temporal-network
expose:
- 9200
volumes:
- /var/lib/elasticsearch/data
postgresql:
container_name: temporal-postgresql
environment:
POSTGRES_PASSWORD: temporal
POSTGRES_USER: temporal
image: postgres:${POSTGRESQL_VERSION}
networks:
- temporal-network
expose:
- 5432
volumes:
- /var/lib/postgresql/data
temporal:
container_name: temporal
depends_on:
- postgresql
- elasticsearch
environment:
- DB=postgresql
- DB_PORT=5432
- POSTGRES_USER=temporal
- POSTGRES_PWD=temporal
- POSTGRES_SEEDS=postgresql
- DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development-sql.yaml
- ENABLE_ES=true
- ES_SEEDS=elasticsearch
- ES_VERSION=v7
image: temporalio/auto-setup:${TEMPORAL_VERSION}
networks:
- temporal-network
ports:
- 7233:7233
labels:
kompose.volume.type: configMap
volumes:
- ./dynamicconfig:/etc/temporal/config/dynamicconfig
temporal-admin-tools:
container_name: temporal-admin-tools
depends_on:
- temporal
environment:
- TEMPORAL_CLI_ADDRESS=temporal:7233
image: temporalio/admin-tools:${TEMPORAL_VERSION}
networks:
- temporal-network
stdin_open: true
tty: true
temporal-ui:
container_name: temporal-ui
depends_on:
- temporal
environment:
- TEMPORAL_ADDRESS=temporal:7233
- TEMPORAL_CORS_ORIGINS=http://localhost:3000
image: temporalio/ui:${TEMPORAL_UI_VERSION}
networks:
- temporal-network
ports:
- 8080:8080
networks:
temporal-network:
driver: bridge
name: temporal-network
添加docker-compose.yaml文件所需的环境变量。
# .env
COMPOSE_PROJECT_NAME=temporal
CASSANDRA_VERSION=3.11.9
ELASTICSEARCH_VERSION=7.16.2
MYSQL_VERSION=8
POSTGRESQL_VERSION=13
TEMPORAL_VERSION=1.19.1
TEMPORAL_UI_VERSION=2.9.1
时间服务器运行的工作流的源代码位于workflow.go文件中。它负责生成活动,监视其完成并控制工作流程。它指定了工作流程必须采取的每个动作,并且是由事件开始的,例如队列中的消息或在系统中添加新数据项。
// workflow.go
package helloworkflow
import (
"context"
"time"
"go.temporal.io/sdk/workflow"
)
func Workflow(ctx workflow.Context, name string) (string, error) {
ao := workflow.ActivityOptions{
ScheduleToStartTimeout: time.Minute,
StartToCloseTimeout: time.Minute,
}
ctx = workflow.WithActivityOptions(ctx, ao)
logger := workflow.GetLogger(ctx)
var result string
err := workflow.ExecuteActivity(ctx, Activity, name).Get(ctx, &result)
if err != nil {
logger.Error("Activity failed", "Error", err)
}
return result, nil
}
func Activity(ctx context.Context, name string) (string, error) {
return "Hello " + name, nil
}
启动器负责协调系统内的工作流执行。它负责安排执行任务并使任务状态保持最新。启动器还充当用户通过其API与系统进行交互的网关。
现在,我们将它们添加到我们的主。
// starter/main.go
package main
import (
"context"
"log"
"github.com/theifedayo/hello-workflow/src/helloworkflow"
"go.temporal.io/sdk/client"
)
func main() {
c, err := client.NewClient(client.Options{
})
if err != nil {
log.Fatalln("Unable to make client", err)
}
defer c.Close()
workflowOptions := client.StartWorkflowOptions{
ID: "hello_world_workflowID",
TaskQueue: "hello-world",
}
we, err := c.ExecuteWorkflow(context.Background(), workflowOptions, helloworkflow.Workflow, "ifedayo")
if err != nil {
log.Fatalln("Unable to execute workflow", err)
}
var result string
// store the result of the run
err = we.Get(context.Background(), &result)
if err != nil {
log.Fatalln("Unable to get workflow result", err)
}
log.Println("workflow result:", result)
}
工人负责执行任务。这些工人部署在系统中的不同节点上,他们的工作是从入门者那里接收任务并执行它们。工人还负责将结果发送回入门者。工人可以根据工作量来缩放或向下缩放。
// worker/main.go
package main
import (
"log"
"github.com/theifedayo/hello-workflow/src/helloworkflow"
"go.temporal.io/sdk/client"
"go.temporal.io/sdk/worker"
)
func main() {
c, err := client.NewClient(client.Options{})
if err != nil {
log.Fatalln("Unable to make client", err)
}
defer c.Close()
w := worker.New(c, "hello-world", worker.Options{})
w.RegisterWorkflow(helloworkflow.Workflow)
w.RegisterActivity(helloworkflow.Activity)
err = w.Run(worker.InterruptCh())
if err != nil {
log.Fatalln("Unable to start workflow", err)
}
}
开始一切
要启动我们的工作流程,我们需要临时服务器。转到您的终端和CD到您的项目目录并运行
docker-compose up
这将在我们的Docker-Compose.yaml中启动所有服务。
接下来,我们开始我们的工人。
通常,您应该在入门者之前开始工人,因为起动器通常取决于工人可以执行其任务。这意味着在开始者开始协调其活动之前,应启动和初始化工人。
go run src/worker/main.go
2023/02/16 14:03:42 INFO No logger configured for temporal client. Created default one.
2023/02/16 14:03:43 INFO Started Worker Namespace default TaskQueue hello-world WorkerID 4465@Ifedayos-MacBook-Pro.local@
最后,我们开始工作流程
go run src/starter/main.go
2023/02/16 14:05:52 INFO No logger configured for temporal client. Created default one.
2023/02/16 14:05:52 workflow result: Hello ifedayo
查看工作流程
在Localhost上导航到浏览器:8080,我们有一个UI,提供了有关工作流程的更多信息
Perimal还提供了一个CLI工具,用于与时间服务器TCTL进行交互,该工具还执行各种管理任务,例如启动和停止工作流程,查询工作流程信息以及管理工作流程执行。
tctl workflow list
WORKFLOW TYPE | WORKFLOW ID | RUN ID | TASK QUEUE | START TIME | EXECUTION TIME | END TIME
Workflow | hello_world_workflowID | 0454098f-cdd9-4f64-af8b-ab77a6f86c35 | hello-world | 13:05:52 | 13:05:52 | 13:05:52
结论
在撰写本文中,我们已经了解了什么时间,为什么使用它,在公司中使用它的说明,设置时间服务器的选择,如何在GO项目中启动服务器,运行Workflow和工人,最后在UI或CLI中查看您的工作流程。
欢呼ð¥!您更接近使用暂时性构建更可靠的应用程序的一步。