SOA系统中的Determined Interaction模式

在面向服务的架构(SOA)系统中,处理和传播错误是一个众所周知的问题,已经有一些模式可以解决这个问题。当消费者调用服务时,交互可能会因为请求数据不正确或服务层本身的问题而失败,这使得交互出现故障。然而,在某些业务场景中,如果消费者接受失败的原因,那么交互可能不需要出现故障。这意味着可以覆盖该失败。这种类型的失败被称为警告。Determined Interaction是一种在SOA系统中处理和传播警告的模式。本文将解释如何在WCF服务中实现警告的暴露。

Determined Interaction模式

SOA系统的每个层次都有责任处理警告。以下类图显示了在服务层传达警告所需的核心对象。

在请求和响应消息交换模式的服务中,需要一种媒介来传达交互过程中是否发生了警告。确认(Acknowledgement)充当这种媒介,它传达以下信息:

  • 状态 - 交互的状态,可以是成功或失败。将其定义为整数,并模仿HTTP状态码200(成功)和301(警告)
  • 时间戳 - 结果发生的时间
  • 警告 - 如果有的话,包含警告信息

警告包含:

  • 代码 - 唯一代表警告类型的代码,例如使用了12345表示药物过敏
  • 消息 - 包含警告的描述

CorrelationState包含用于交互完整性所需的数据的哈希值。

该方法的签名如下:

public static WarningElevation AddWarning( int code, string message, DomainBase[] admonishedObjects, object[] otherIntegrities)

前两个参数是自解释的。域对象可能是域层中每个项目级别的相关状态可以传达的地方。因此,声明了一个基类(尽管倾向于使用POCO)DomainBase,如下所示:

[Serializable] public class DomainBase { [NonSerialized] public string[] CorrelationStates; }

可能会惊讶CorrelationStates是一个数组,因为在交互过程中可能会有多个警告。让看看AddWarning()方法的第一部分。

string generatedCorrelationState = null; int eludeCount = 0; int admonishedCount = 0; if (admonishedObjects != null && admonishedObjects.Length > 0) { string[] cstates = admonishedObjects[0].CorrelationStates; bool verifyMode = (cstates != null && cstates.Length > 0 && !string.IsNullOrEmpty(cstates[0])) ? true : false; generatedCorrelationState = new ObjectBytifier(verifyMode, code, admonishedObjects, otherIntegrities).Stringified; admonishedCount = admonishedObjects.Length; eludeCount = admonishedObjects.Count(admonishedObj => { return admonishedObj != null && admonishedObj.CorrelationStates != null && admonishedObj.CorrelationStates.Length > 0 && admonishedObj.CorrelationStates.Contains(generatedCorrelationState); }); }

这部分将在admonishedObjects中至少给出一个对象时执行。如果admonishedObject中的任何一个对象包含CorrelationState,则此交互将被决定为确定性交互。每次都会生成一个相关状态,并使用ObjectBytifier保持在generatedCorrelationState变量中。这将在第一次交互中传达给消费者。在确定性交互期间,这用于验证来自消费者的信息。

eludeCount存储在确定性交互期间包含相关状态的admonishedObjects的数量。让看看AddWarning()的剩余部分。

if (eludeCount == 0 && admonishedCount != eludeCount) { string language = string.Empty; Acknowledgement currentAck = Acknowledgement.Current; if (currentAck.Warnings == null) Acknowledgement.Current.Warnings = new List(); Warning fault = new Warning { Code = code, Message = message, CorrelationState = generatedCorrelationState }; Acknowledgement.Current.Warnings.Add(fault); Acknowledgement.Current.Status = 301; return WarningElevation.Admonish; } else return WarningElevation.Admonish;

如果admonishedObjects中没有相关状态或没有匹配的相关状态,警告已经生成并添加到Acknowledgement中。根据这个,返回了适当的WarningElevation。让看看另一个重要的对象,它生成相关状态。

ObjectBytifier包含设置所有交互完整性元素的属性AdmonishedObjects、OtherIntegrities、UserId和WarningCode。OtherIntegrities是一个占位符,如果想放置除域对象之外的任何东西,例如在示例中,使用它来放置患者ID,这是一个字符串,但需要用于集成完整性。

Bytifier属性将所有交互完整性元素转换为字节数组,Stringified元素将该字节数组转换为固定大小的字符串。这就是所说的CorrelationState。

BytifyBaseObjects()是这里的关键方法。让看看它的初始部分。

string salt = string.Format("{0}{1}{2}", "SALT", UserId, WarningCode); _bytified = ASCIIEncoding.UTF8.GetBytes(salt); if (AdmonishedObjects != null && AdmonishedObjects.Length > 0) { BinaryFormatter serializer = new BinaryFormatter(); MemoryStream memStream = null; for (int i = 0; i < AdmonishedObjects.Length; i++) { if (AdmonishedObjects[i] != null) { using (memStream = new MemoryStream()) { serializer.Serialize(memStream, AdmonishedObjects[i]); _bytified = _bytified.Concat(memStream.ToArray()).ToArray(); memStream.Close(); } } } }

初始字符串已经用盐、用户ID和警告代码形成,随后所有AdmonishedObjects都使用BinaryFormatter序列化并存储到_bytified字段中。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485