命令中心服务 - Nebula.Fides
使用场景
这里涉及3个对象:
- 命令的发布者:【云端】的各个应用程序
- 命令的执行者:【云下】的客户端程序
- 二端的协调者:用于连接各个应用程序和云下客户端。
执行流程介绍:
- 客户端,以死循环的方式执行下面步骤:
- (1)使用HTTP协议调用Fides拉取命令
- (4)在获取到命令后,交给后台线程来执行,然后上传命令的执行结果(5)
- (_)重新执行 (1) 步骤
- Fides,监听HTTP端口,接收命令的发布和上传结果
- (3)当接收到命令发布时,Fides会立即将命令返回给客户端
- 如果没有收到命令,Fides则将客户端的请求挂起,直到命令出现或者达到超时
- 应用程序
- (2)根据业务需要,使用HTTP协议给Fides发布命令,并等待执行结果(6)
Fides的价值:
- 简化【云端应用程序】调用【云下客户端】的过程
- 对于【云端应用程序】来说,只需要对Fides发起一次HTTP调用即可得到结果
API调用
应用程序--发布命令--并等待--执行结果
POST http://hostxxxxxx/v20/api/fides/cmd/publish HTTP/1.1
Content-Type: application/json
x-token: .......jwt-token.................
{
"ActionName": "actionx",
"ClientId": "Client-3",
"Caller": "Caller-111"
}
响应示例:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"ServerId": "e0e194b0bbc84db98f8eac6dff15e126",
"CallbackId": "5459a6fe9b7541d59b9af53358044da8",
"TenantId": "FISHDEV-WIN10",
"ClientId": "Client-3",
"ClientReceiveTime": "2022-07-13T18:51:34.9975544+08:00",
"ClientStartTime": "2022-07-13T18:51:34.9975544+08:00",
"ClientEndTime": "2022-07-13T18:51:34.9975544+08:00",
"ServerReceiveTime": "2022-07-13T18:51:35.0918622+08:00",
"ResponseResult": "FISHDEV-WIN10#Client-3 execute actionx OK!",
"ClientAddition": "addition is ..xxx..",
"RequestId": "92eeaf0008e543a6846748d6a0615892"
}
请求体的数据结构如下:
public sealed class PublishArgs
{
/// 要执行命令的客户端Id
[Required]
public string ClientId { get; set; }
/// 命令名称
[Required]
public string ActionName { get; set; }
/// 命令的调用参数
public string Args { get; set; }
/// 命令的发布者
public string Sender { get; set; }
/// 发布命令的功能场景
public string Caller { get; set; }
/// 命令是单向的,不需要等待执行结果
public int IsOneWay { get; set; }
/// 服务端的最大等待时间
public int ServerWaitSecond { get; set; }
/// 客户端的最大等待时间
public int ClientWaitSecond { get; set; }
/// 客户端执行命令时,如果发生异常,最大的允许多少次重试
public int MaxExecuteRetryCount { get; set; }
/// 客户端上传结果时,如果发生异常,最大的允许多少次重试
public int MaxUploadRetryCount { get; set; }
/// 客户端遇到异常做重试时,中间间隔多少秒
public int ErrorWaitSecond { get; set; }
}
响应体的数据结构如下:
public sealed class CommandResult
{
/// 服务端节点Id
public string ServerId { get; set; }
/// 服务端当前请求ID
public string RequestId { get; set; }
/// 引用 ClientCommand.CallbackId
public string CallbackId { get; set; }
public string TenantId { get; set; }
public string ClientId { get; set; }
public DateTime ClientReceiveTime { get; set; }
public DateTime ClientStartTime { get; set; }
public DateTime ClientEndTime { get; set; }
public DateTime ServerReceiveTime { get; set; }
/// 客户端的响应结果
public string ResponseResult { get; set; }
/// 客户端的结果响应类型,,可参考HTTP的 Content-Type 响应头
public string ResponseContentType { get; set; }
/// 客户端的结果响应的编码方式,可参考HTTP的 Content-Encoding 响应头
public string ResponseContentEncoding { get; set; }
/// 客户端的一些附加描述信息
public string ClientAddition { get; set; }
/// 客户端引发的异常类型
public string ExecptionType { get; set; }
/// 客户端引发的异常描述
public string ExecptionText { get; set; }
}
客户端--拉取命令
GET http://hostxxxxxx/v20/api/fides/cmd/pull HTTP/1.1
x-token: .......jwt-token.................
x-expect-count: 1
x-client-timeoutms: 110000
请求头说明:
- x-expect-count 明确告诉服务端:一次只返回一个ClientCommand对象。
如果不指定,则以数组形式返回(也只有一个对象)
这个参数主要是为了解决兼容性问题,建议指定,且 value 只能设置为 1 - x-client-timeoutms 告诉服务端:客户端的超时时间
如果不指定此参数,请求在服务端挂起的时间由服务端决定,此时客户端的超时时间必须大于服务端的挂起时间。
响应示例:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"CommandGuid": "ddcd19465244410cb8030701e029bf97",
"CreateTime": "2022-07-13T19:06:55.8980434+08:00",
"ServerId": "e0e194b0bbc84db98f8eac6dff15e126",
"CallbackId": "f5e12ca3a8f642f8a2945009461e6769",
"ActionName": "actionx",
"Caller": "Caller-111",
"IsOneWay": 0,
"UserId": "11111",
"UserType": "admin",
"TenantId": "FISHDEV-WIN10",
"ClientId": "Client-3",
"ClientWaitSecond": 0,
"ServerWaitSecond": 20,
"MaxExecuteRetryCount": 0,
"MaxUploadRetryCount": 0,
"ErrorWaitSecond": 0
}
响应体的数据结构如下:
public sealed class ClientCommand
{
/// 服务端创建时间
public DateTime CreateTime { get; set; }
/// 服务端节点Id
public string ServerId { get; set; }
/// 客户端上传结果后的回调通知ID,【始终应该使用这个字段来做唯一ID】
public string CallbackId { get; set; }
public string ActionName { get; set; }
public string Args { get; set; }
public string Caller { get; set; }
/// 命令是单向的,不需要等待执行结果
public int IsOneWay { get; set; }
public string UserId { get; set; }
public string UserType { get; set; }
public string TenantId { get; set; }
public string ClientId { get; set; }
public int ClientWaitSecond { get; set; }
public int ServerWaitSecond { get; set; }
public int MaxExecuteRetryCount { get; set; }
public int MaxUploadRetryCount { get; set; }
public int ErrorWaitSecond { get; set; }
}
客户端--上传--命令执行结果
POST http://hostxxxxxx/v20/api/fides/cmd/upload HTTP/1.1
Content-Type: application/json
x-token: .......jwt-token.................
{
"CallbackId": "..............",
"ClientStatus": 200,
"ResponseResult": ".............."
}
响应示例:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"CallbackId": "5459a6fe9b7541d59b9af53358044da8"
}
请求体的数据结构如下:
public sealed class UploadArgs
{
/// 引用 ClientCommand.CallbackId
[Required]
public string CallbackId { get; set; }
public DateTime ClientReceiveTime { get; set; }
public DateTime ClientStartTime { get; set; }
public DateTime ClientEndTime { get; set; }
/// 客户端对于执行结果的状态码表示
public int ClientStatus { get; set; }
/// 客户端的响应结果
public string ResponseResult { get; set; }
/// 客户端的结果响应类型
public string ResponseContentType { get; set; }
/// 客户端的结果响应的编码方式,可参考HTTP的 Content-Encoding 响应头
public string ResponseContentEncoding { get; set; }
/// 客户端的一些附加描述信息
public string ClientAddition { get; set; }
/// 客户端引发的异常类型
public string ExecptionType { get; set; }
/// 客户端引发的异常描述
public string ExecptionText { get; set; }
}
日志&问题排查
发布命令时,Fides会记录一些重要数据到Oprlog日志中,可以在Venus/Kibana中查看:
日志字段含意
- bizId: CallbackId
- bizName: ActionName
- text2: TenantId
- text3: ClientId
其中 CallbackId 贯穿了 publish/pull/upload 3个阶段,可以根据此数据来查询对应的日志: