Microsoft Graph 连接器 SDK 最佳做法
本文提供了使用 Microsoft Graph 连接器 SDK 实现自定义连接器时要遵循的最佳做法。
使用爬网进度标记
爬网进度标记充当由平台上次处理的连接器发送的特定项目的标识符。 可以实现两种类型的爬网:定期完全爬网和增量爬网。
定期完全爬网获取数据源中的所有项,并仅引入索引中已修改或不存在的项。 如果找不到项,则会将其从索引中删除。
增量爬网获取自上次增量爬网以来添加或修改的项。 连接器还可以发送要在此爬网过程中删除的项目。 对于第一次增量爬网,还会发送最后一次完全爬网的开始时间。 连接器可以选择使用此爬网来提取仅在上次完全爬网之后更改的项目。
定期完全爬网和增量爬网都有其爬网进度标记。
在定期完全爬网期间使用爬网进度标记
如果由于 Microsoft Graph 连接器代理在定期完全爬网期间处于脱机状态,上一次爬网崩溃或错过了计划的爬网,则 SDK 会发送爬网进度标记。
如果上一次爬网未崩溃,则必须从头开始对数据源进行爬网。
增量爬网期间爬网进度标记的用法
在一次增量爬网期间,连接器会将爬网进度标记发送到连接器平台,并且将继续为下一次增量爬网执行此操作。 连接器可以使用此爬网在此标记之后提取添加或修改的项目。
构造泛型类型
内容项的属性值可以具有一系列数据类型。 由于 gRPC 没有泛型对象的构造,因此 SDK 包含一个 GenericType 结构,该结构可以容纳任何受支持的数据类型。 GenericType 具有以下结构:
// Represents a generic type that can hold any supported value
message GenericType {
// Value of the Generic type
oneof value {
// String type value
string stringValue = 1;
// Long value
int64 intValue = 2;
// Double value
double doubleValue = 3;
// DateTime value
google.protobuf.Timestamp dateTimeValue = 4;
// Boolean value
bool boolValue = 5;
// String collection value
StringCollectionType stringCollectionValue = 6;
// Long collection value
IntCollectionType intCollectionValue = 7;
// Double collection value
DoubleCollectionType doubleCollectionValue = 8;
// DateTime collection value
TimestampCollectionType dateTimeCollectionValue = 9;
}
}
// Collection of string
message StringCollectionType {
// Value of string collection
repeated string values = 1;
}
// Collection of long
message IntCollectionType {
// Value of long collection
repeated int64 values = 1;
}
// Collection of double
message DoubleCollectionType {
// Value of double collection
repeated double values = 1;
}
// Collection of DateTime
message TimestampCollectionType {
// Value of DateTime collection
repeated google.protobuf.Timestamp values = 1;
}
GenericType 可以具有以下类型之一:string、int64、double、DateTime 和 Boolean 类型或字符串集合(int64、double 和 DateTime)。 下面是如何设置这些类型的示例:
// Setting string value in generic type
GenericType stringType = new GenericType
{
StringValue = "Hello"
};
// Setting int64 value in generic type
GenericType int64Type = new GenericType
{
IntValue = 1000
};
// Setting double value in generic type
GenericType doubleType = new GenericType
{
DoubleValue = 12.54
};
// Setting dateTime value in generic type
GenericType dateTimeType = new GenericType
{
DateTimeValue = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow)
};
// Setting Boolean value in generic type
GenericType boolType = new GenericType
{
BoolValue = true
};
// Setting string collection value in generic type - Initialize the string collection first, add the values to the string collection and then set it in the generic type
StringCollectionType stringCollection = new StringCollectionType();
stringCollection.Values.Add("Value1");
stringCollection.Values.Add("Value2");
GenericType stringCollectionType = new GenericType
{
StringCollectionValue = stringCollection
};
// Setting int64 collection value in generic type - Initialize the int64 collection first, add the values to the int64 collection and then set it in the generic type
IntCollectionType intCollection = new IntCollectionType();
intCollection.Values.Add(1234);
intCollection.Values.Add(5436);
GenericType intCollectionType = new GenericType
{
IntCollectionValue = intCollection
};
// Setting double collection value in generic type - Initialize the double collection first, add the values to the double collection and then set it in the generic type
DoubleCollectionType doubleCollection = new DoubleCollectionType();
doubleCollection.Values.Add(12.54);
doubleCollection.Values.Add(34.213);
GenericType doubleCollectionType = new GenericType
{
DoubleCollectionValue = doubleCollection
};
// Setting datetime collection value in generic type - Initialize the datetime collection first, add the values to the datetime collection and then set it in the generic type
TimestampCollectionType dateTimeCollection = new TimestampCollectionType();
dateTimeCollection.Values.Add(Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow));
dateTimeCollection.Values.Add(Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow.AddDays(-1)));
GenericType dateTimeCollectionType = new GenericType
{
DateTimeCollectionValue = dateTimeCollection
};
生成搜索架构
连接器架构具有以下限制:
- 属性名称:属性的名称最多可以包含 32 个字符,并且只允许使用字母数字字符。
-
搜索批注:
- 只能搜索 String 或 StringCollection 类型的属性。
- 只有 类型为 String 的属性才能是内容属性。
- 内容属性必须可搜索。
- 内容属性无法查询或检索。
- 可精简属性不应可搜索。
- 可精简属性应可查询且可检索。
- 布尔属性不可精简。
- 别名:属性的一组别名或友好名称最多可以包含 32 个字符,并且只允许使用字母数字字符。
在爬网期间提取项
GetCrawlStream 方法是服务器流式处理方法。 它在爬网期间将数据源中的每个项转换为 CrawlStreamBit ,并通过响应流发送它。
为了获得良好的吞吐量,连接器应从数据源检索一批项,将每个项转换为 CrawlStreamBit,并通过响应流发送它们。 批大小取决于数据源。 建议使用 25 作为最佳大小,以保持流中的项目连续流。
连接器代码中的异常处理
来自 gRPC 调用的所有响应都有 一个 OperationStatus ,指示操作是成功还是失败、失败原因和重试详细信息(如果有失败)。 建议将整个代码包装在 try-catch 块中。 连接器应记录所有异常,并向平台发送正确的操作状态。
连接管理流使用Microsoft 365 管理中心中显示的 StatusMessage 发送响应。 发送有意义的消息可以更轻松地调试用户界面上的错误,并避免留下未经处理的异常。
超时
ConnectionManagementService 中的所有方法都应在 30 秒内完成并返回;否则,平台将返回请求的超时错误消息。
将错误从连接器发送回平台
所有响应在响应结构中使用 OperationStatus 。 如果发生任何错误,连接器应使用 OperationStatus 将失败原因和重试信息发送回平台。 如果发生用于访问数据源的凭据过期等连接级错误,请使用 OperationStatus 设置爬网期间的错误。
OperationStatus 结构有三个字段,可用于表示任何错误。
OperationResult
OperationResult 是一个枚举,可以保存失败原因。
StatusMessage
StatusMessage 是 OperationStatus 的一个属性,它可以存储自定义消息,以在连接设置过程中向管理员显示失败原因。 例如,如果在使用 ValidateAuthentication 方法进行验证期间凭据不正确,则可以将 result 属性设置为 AuthenticationIssue,statusMessage 属性可以设置为提供的凭据不正确。 调用 ValidateAuthentication 方法时,将向搜索管理员显示此 statusMessage 。在爬网期间,此方案会将连接移动到失败状态,向管理员显示身份验证错误,并提示管理员更新凭据以访问数据源。
RetryDetails
RetryDetails 允许连接器向平台重新发送有关爬网期间暂时性错误的信息,并使用它来重复该操作。
重试可以是标准或指数退避。 连接器可以设置暂停时间、退让率和回退系数,并发送回去。 例如,如果数据源在爬网期间受到限制,连接器可以将 OperationResult 设置为 DatasourceError ,并根据数据源的响应标头中的重试标头发送重试详细信息。
OperationResult 的错误映射
以下错误会将连接移动到失败状态:
OperationResult.AuthenticationIssue
OperationResult.ValidationFailure
其他操作代码将被视为暂时性故障,并将在后续爬网中重试。