在本教程中,您将学习在Go应用程序中使用Go客户机与Zeebe交互。
将指导您完成以下步骤:
- Set up a project
- Model a workflow
- Deploy a workflow
- Create a workflow instance
- Work on a task
- Open a topic subscription
先决条件
- Go v1.11+ environment installed
- Zeebe distribution
- Zeebe Modeler
- Zeebe Monitor
在开始设置项目之前,请启动broker,即通过在分发中运行启动脚本bin/broker或bin/broker.bat。默认情况下,代理绑定到地址localhost:26500。
Set up a project
首先,我们需要一个新的GO项目。使用您的IDE创建一个新项目,或创建新的Go模块:
mkdir -p $GOPATH/src/github.com/{{your username}}/zb-example
cd $GOPATH/src/github.com/{{your username}}/zb-example
安装Zeebe Go客户端库:
go get github.com/zeebe-io/zeebe/clients/go
在模块内创建main.go文件,并添加以下行以引导Zeebe客户端:
package main
import (
"fmt"
"github.com/zeebe-io/zeebe/clients/go/zbc"
"github.com/zeebe-io/zeebe/clients/go/pb"
)
const BrokerAddr = "0.0.0.0:26500"
func main() {
zbClient, err := zbc.NewZBClient(BrokerAddr)
if err != nil {
panic(err)
}
topology, err := zbClient.NewTopologyCommand().Send()
if err != nil {
panic(err)
}
for _, broker := range topology.Brokers {
fmt.Println("Broker", broker.Host, ":", broker.Port)
for _, partition := range broker.Partitions {
fmt.Println(" Partition", partition.PartitionId, ":", roleToString(partition.Role))
}
}
}
func roleToString(role pb.Partition_PartitionBrokerRole) string {
switch role {
case pb.Partition_LEADER:
return "Leader"
case pb.Partition_FOLLOWER:
return "Follower"
default:
return "Unknown"
}
}
运行程序。
go run main.go
您应该看到类似的输出:
Broker 0.0.0.0 : 26501
Partition 0 : Leader
Model a workflow
现在,我们需要一个可以部署的第一个工作流。稍后,我们将使用更多功能扩展工作流。
打开Zeebe Modeler并创建新的BPMN图。将开始事件和结束事件添加到图表中并连接这些事件。
将ID设置为订单流程(即BPMN流程ID),并将图表标记为可执行。将图表保存在项目的源文件夹中。
Deploy a workflow
接下来,我们要将建模的工作流部署到broker。broker将工作流存储在其bpmn流程ID下,并分配一个版本(即修订版)。
package main
import (
"fmt"
"github.com/zeebe-io/zeebe/clients/go/zbc"
)
const brokerAddr = "0.0.0.0:26500"
func main() {
zbClient, err := zbc.NewZBClient(brokerAddr)
if err != nil {
panic(err)
}
response, err := zbClient.NewDeployWorkflowCommand().AddResourceFile("order-process.bpmn").Send()
if err != nil {
panic(err)
}
fmt.Println(response.String())
}
运行程序并验证工作流是否已成功部署。您应该看到类似的输出:
key:1 workflows:<bpmnProcessId:"order-process" version:1 workflowKey:1 resourceName:"order-process.bpmn" >
Create a workflow instance
最后,我们准备创建已部署工作流的第一个实例。工作流实例是由特定版本的工作流创建的,可以在创建时进行设置。
package main
import (
"fmt"
"github.com/zeebe-io/zeebe/clients/go/zbc"
)
const brokerAddr = "0.0.0.0:26500"
func main() {
client, err := zbc.NewZBClient(brokerAddr)
if err != nil {
panic(err)
}
// After the workflow is deployed.
payload := make(map[string]interface{})
payload["orderId"] = "31243"
request, err := client.NewCreateInstanceCommand().BPMNProcessId("order-process").LatestVersion().VariablesFromMap(payload)
if err != nil {
panic(err)
}
msg, err := request.Send()
if err != nil {
panic(err)
}
fmt.Println(msg.String())
}
运行程序并验证是否创建了工作流实例。您应该看到输出:
workflowKey:1 bpmnProcessId:"order-process" version:1 workflowInstanceKey:6
你做到了!要查看工作流实例的执行方式吗?
使用java -jar zeebe-simple-monitor-app-*.jar
启动ZEEBE监视器。
打开Web浏览器并转到http://localhost:8080/。
在这里,您可以看到工作流实例的当前状态。
Work on a task
现在我们想在您的工作流程中做一些工作。首先,在BPMN图中添加一些服务任务,并设置所需的属性。然后扩展main.go文件并激活在工作流实例到达服务任务时创建的作业。
在Zeebe Modeler中打开BPMN图。在开始和结束事件之间插入一些服务任务。
您需要设置每个任务的类型,它标识要执行的工作的性质。将第一个任务的类型设置为“付款服务”。
添加以下行以重新部署修改后的流程,然后激活并完成第一个任务类型的作业:
package main
import (
"fmt"
"github.com/zeebe-io/zeebe/clients/go/entities"
"github.com/zeebe-io/zeebe/clients/go/worker"
"github.com/zeebe-io/zeebe/clients/go/zbc"
"log"
)
const brokerAddr = "0.0.0.0:26500"
func main() {
client, err := zbc.NewZBClient(brokerAddr)
if err != nil {
panic(err)
}
// deploy workflow
response, err := client.NewDeployWorkflowCommand().AddResourceFile("order-process.bpmn").Send()
if err != nil {
panic(err)
}
fmt.Println(response.String())
// create a new workflow instance
payload := make(map[string]interface{})
payload["orderId"] = "31243"
request, err := client.NewCreateInstanceCommand().BPMNProcessId("order-process").LatestVersion().VariablesFromMap(payload)
if err != nil {
panic(err)
}
result, err := request.Send()
if err != nil {
panic(err)
}
fmt.Println(result.String())
jobWorker := client.NewJobWorker().JobType("payment-service").Handler(handleJob).Open()
defer jobWorker.Close()
jobWorker.AwaitClose()
}
func handleJob(client worker.JobClient, job entities.Job) {
jobKey := job.GetKey()
headers, err := job.GetCustomHeadersAsMap()
if err != nil {
// failed to handle job as we require the custom job headers
failJob(client, job)
return
}
variables, err := job.GetVariablesAsMap()
if err != nil {
// failed to handle job as we require the variables
failJob(client, job)
return
}
variables["totalPrice"] = 46.50;
request, err := client.NewCompleteJobCommand().JobKey(jobKey).VariablesFromMap(variables)
if err != nil {
// failed to set the updated variables
failJob(client, job)
return
}
log.Println("Complete job", jobKey, "of type", job.Type)
log.Println("Processing order:", variables["orderId"])
log.Println("Collect money using payment method:", headers["method"])
request.Send()
}
func failJob(client worker.JobClient, job entities.Job) {
log.Println("Failed to complete job", job.GetKey())
client.NewFailJobCommand().JobKey(job.GetKey()).Retries(job.Retries - 1).Send()
}
在这个例子中,我们为类型为Payment Service的工作打开一个工作人员。工作人员将重复轮询类型付款服务的新工作,并随后激活它们。然后将每个激活的作业传递给作业处理程序,该处理程序实现作业工人的业务逻辑。然后,处理程序将用其结果完成作业,或者在处理作业时遇到问题时使作业失败。
当您查看Zeebe监视器时,可以看到工作流实例从第一个服务任务移动到下一个服务任务:
当您运行上述示例时,您应该看到类似的输出:
key:26 workflows:<bpmnProcessId:"order-process" version:2 workflowKey:2 resourceName:"order-process.bpmn" >
workflowKey:2 bpmnProcessId:"order-process" version:2 workflowInstanceKey:31
2018/11/02 11:39:50 Complete job 2 of type payment-service
2018/11/02 11:39:50 Processing order: 31243
2018/11/02 11:39:50 Collect money using payment method: VISA
zeebe qq交流群群号:856546010