目录
0.背景说明:
客户端跟server端交互步骤是:
1.查询待执行任务
2.执行结束后,调用 JobClient#newCompleteCommand(long) 通知server端
1. gateway 暴露的接口
io.camunda.zeebe.gateway.GatewayGrpcService 中定义了一批关键的方法(部分):
activateJobs()
cancelProcessInstance()
completeJob()
createProcessInstance()
createProcessInstanceWithResult()
evaluateDecision()
deployResource()
failJob()
throwError()
publishMessage()
resolveIncident()
updateJobRetries()
modifyProcessInstance()
deleteResource()
broadcastSignal()
从方法名可以看出,关于流程操作的一系列方法都在其中,客户端调用时,就是以这些方法操作流程;这里每一个方法都定义了特定的Request实体类:
创建Request的 facade类 io.camunda.zeebe.gateway.RequestMapper,提供创建各种Request的方法
对应的Response的 facade类为:io.camunda.zeebe.gateway.ResponseMapper
2. client跟gateway的通信
查询待执行任务的动作,客户端是通过 io.camunda.zeebe.gateway.GatewayGrpcService#activateJobs 接口实现的
该接口在server端(gateway中)最终调用的是 RoundRobinActivateJobsHandler#activateJobs(InflightActivateJobsRequestState, ResponseObserverDelegate)
处理response的方法 RoundRobinActivateJobsHandler#handleResponseSuccess
其中有一点需要注意,每次activateJob请求,broker都会返回response到gateway,gateway会根据返回的response是否关联了有效的 jobKeys和jobs进行过滤,若response无效,最后gateway会返回空:
io.camunda.zeebe.gateway.ResponseMapper#toActivateJobsResponse
发送response的方法:io.camunda.zeebe.gateway.impl.job.InflightActivateJobsRequest#tryToSendActivatedJobs
而客户端接收response的方法为:
io.camunda.zeebe.client.impl.worker.JobPoller#onNext
即是通过 grpc的 io.grpc.stub.StreamObserver#onNext 实现通信
3. gateway与zeebe-broker的通信
gateway 发送请求到broker是通过方法: BrokerClientImpl#sendRequest(BrokerRequest)
其内部会调用到 io.camunda.zeebe.transport.impl.AtomixClientTransportAdapter#sendRequestInternal
io.camunda.zeebe.transport.impl.AtomixClientTransportAdapter#tryToSend
底层是依赖netty进行tcp通信
io.atomix.cluster.messaging.impl.RemoteClientConnection#sendAndReceive
broker从netty的连接中接收消息:io.atomix.cluster.messaging.impl.NettyMessagingService.MessageDispatcher#channelRead0
io.atomix.cluster.messaging.impl.AbstractServerConnection#dispatch
handlers是一个handler注册器,其中的handler都是通过方法 NettyMessagingService#registerHandler() 注册的:
注册的handler追加了统一的后置处理;
上述的handler.accept 方法调用的上述的lambda方法(注意debug位置),而其中的handler.apply 方法对应的则是(activateJob流程中)
io.camunda.zeebe.transport.impl.AtomixServerTransport#subscribe 中传递function(下图红框部分)
之后代码的调用
io.camunda.zeebe.transport.impl.AtomixServerTransport#handleAtomixRequest
该方法中的future会在事件处理完成后(状态机中触发),再异步处理,将response的数据塞进去
io.camunda.zeebe.broker.transport.AsyncApiRequestHandler#onRequest
io.camunda.zeebe.broker.transport.AsyncApiRequestHandler#handleRequest
此处也有一个处理response的逻辑(futureMap处也是),其中 CommandApiResponseWriter#tryWriteResponse的实现就是一个空方法(它的处理实际上是写日志,是个异步处理逻辑),猜测是一个用于同步返回,一个用于异步返回。
handleAsync() 方法实现类有多个,以commandApi为例: 处理请求为 CommandApiRequestHandler
其核心方法为:CommandApiRequestHandler#handleExecuteCommandRequest
当broker接收到请求后,解析处request中的关键信息,最后记录在log中
4.broker的command处理逻辑
主节点将request发送至对应的follower方法 LeaderAppender#appendEntries(io.atomix.raft.cluster.impl.RaftMemberContext)
之后调用链为:
LeaderAppender#sendAppendRequest
——> LeaderAppender#handleAppendResponse
——> LeaderAppender#handleAppendResponseOk
——> LeaderAppender#commitEntries
——>RaftContext#setCommitIndex
此时会调用 notifyCommitListeners(commitIndex) 通知所有的listener
最终会通知所有的recordAwaiter ( 核心方法):io.camunda.zeebe.logstreams.impl.log.LogStreamImpl#notifyRecordAwaiters
awaiter的实现就是broker的几个关键流程:
4.1 StreamProcessor异步处理activateJobsCommand
对于activateJobsCommand处理而言,调用的接口为 StreamProcessor#onRecordAvailable
——>ProcessingStateMachine#readNextRecord
——>ProcessingStateMachine#tryToReadNextRecord
——>ProcessingStateMachine#processCommand
——> ProcessingStateMachine#writeRecords
——> ProcessingStateMachine#updateState
——> ProcessingStateMachine#executeSideEffects
实际的response是通过异步的方式塞入到completabelFuture中的:
CommandResponseWriterImpl#tryWriteResponse
4.2 ProcessingStateMachine 处理command
由4.1可知,具体的处理逻辑是委托 ProcessingStateMachine 处理的
io.camunda.zeebe.stream.impl.ProcessingStateMachine#batchProcessing
command类型由 Engine#process 处理:
各种命令的实现:
4.2.1 JobBatchActivateProcessor 激活任务
io.camunda.zeebe.engine.processing.job.JobBatchActivateProcessor#activateJobBatch
——>ResultBuilderBackedEventApplyingStateWriter#appendFollowUpEvent
——>EventAppliers#applyState
选择对应的 eventapplier执行:
eventApplier是jobIntent维度的,每一种job类型都有对应的处理类
JobIntent 的枚举: io.camunda.zeebe.protocol.record.intent.JobIntent
注册对应的实现(部分)可参考:EventAppliers#registerJobIntentEventAppliers
——> JobBatchActivatedApplier#applyState
——> DbJobState#activate
此处就是一些数据库的插入、更新操作(rocksDB)
4.2.2 JobCompleteProcessor完成任务
io.camunda.zeebe.engine.processing.job.JobCompleteProcessor
——> CommandProcessorImpl#processRecord
——>ResultBuilderBackedEventApplyingStateWriter#appendFollowUpEvent
——> EventAppliers#applyState
——> JobCompletedApplier#applyState
JobCompletedApplier 就是 JobIntent.COMPLETED 的处理器
可以看到,当一个job执行完毕后,db中的数据会被删除