【问题标题】:SOA and WCF design questions: Is this an unusual system design?SOA 和 WCF 设计问题:这是一个不寻常的系统设计吗?
【发布时间】:2011-01-17 16:08:04
【问题描述】:

我发现自己负责开发一个我最初没有设计的系统,并且不能问最初的设计师为什么做出某些设计决定,因为他们不再在这里。我是一名设计问题的初级开发人员,所以当我开始这个项目时,我真的不知道该问什么,这是我的第一个 SOA/WCF 项目。

系统有 7 个 WCF 服务,将增长到 9 个,每个都自托管在单独的控制台应用程序/Windows 服务中。它们都是单实例和单线程的。所有服务都具有相同的 OperationContract:它们公开了 Register() 和 Send() 方法。当客户端服务想要连接到另一个服务时,它们首先调用 Register(),然后如果成功,它们会全部使用 Send() 进行其余的通信。我们有一个 DataContract,它有一个枚举 MessageType 和一个 Content 属性,它可以包含其他 DataContract “有效负载”。服务对消息的处理由枚举 MessageType 确定...一切都通过 Send() 方法,然后被路由到 switch 语句...我怀疑这是不寻常的

Register() 和 Send() 实际上是 OneWay 和 Async...所有来自服务的结果都由 WCF CallbackContract 返回给客户端服务。我相信使用 CallbackContracts 的原因是为了方便我们使用的 Publish-Subscribe 模型。问题不在于我们的所有通信都适合发布-订阅,并且使用 CallbackContracts 意味着我们必须在返回的结果消息中包含源详细信息,以便客户端可以计算出返回的结果最初是为了什么......再次客户端有一个 switch 语句可以解决如何根据 MessageType(和其他嵌入的详细信息)处理来自服务的消息。

就拓扑而言:服务在图中形成“节点”。每个服务都硬编码了它在启动时必须连接的其他服务的列表,并且不会允许客户端服务向它“注册”,直到它建立了它需要的所有连接。例如,我们有一个 LoggingService 和一个 DataAccessService。 DataAccessService 是 LoggingService 的客户端,因此 DataAccess 服务将在启动时尝试向 LoggingService 注册。在它成功注册之前,DataAccess 服务将不允许任何客户端向它注册。结果是,当系统作为一个整体启动时,服务以级联方式启动。我不认为这是一个问题,但这是否不寻常?

为了让事情变得更复杂,系统要求之一是服务或“节点”不需要相互直接注册才能相互发送消息,而是可以通过间接链接进行通信。例如,假设我们有 3 个服务 A、B 和 C 连接在一条链中,A 可以通过 B...向 C 发送消息通过 2 个跃点。

我实际上负责这个任务并编写了路由系统,这很有趣,但是在我问为什么真的需要它之前,领导就离开了。据我所知,服务没有理由不能直接连接到他们需要的其他服务。更重要的是,我必须在一切之上编写一个可靠性系统,因为要求是在系统中节点有可靠的消息传递,而使用简单的点对点链接 W​​CF 可以可靠地完成这项工作。

在这个项目之前,我只在 winforms 桌面应用程序上工作了 3 年,不知道有什么更好的。我的怀疑是这个项目过于复杂:我想总结一下,我的问题是:

1) 这种消息在间接链接上跳跃的图拓扑的想法是否不寻常?为什么不直接将服务连接到他们需要访问的服务(这实际上是我们所做的……我认为我们没有任何消息跳跃)?

2) 在 OperationContract 中仅公开 2 个方法并使用 MessageType 枚举来确定消息的用途/如何处理它是否异常? WCF 服务不应该公开许多具有特定目的的方法,而客户端选择它想要调用的方法吗?

3) 通过 CallbackContracts 与客户端进行的所有通信都异常。当然同步或异步请求响应更简单。

4) 一个服务在连接到它的所有服务(它是一个客户端)之前不允许客户端服务连接到它(注册)的想法是一个合理的设计吗?我认为这是我唯一同意的设计方面,我的意思是 DataAccessService 在与日志服务建立连接之前不应接受客户端。

我有很多关于 WCF 的问题,更多内容将在后面的主题中提出。提前致谢。

【问题讨论】:

    标签: wcf soa


    【解决方案1】:

    嗯,整个事情看起来有点奇怪,同意。

    它们都是单实例并且 单线程。

    这肯定会再次出现并导致严重的性能问题 - 保证。我不明白为什么有人要开始编写单例 WCF 服务(除了一些边缘情况,它确实有意义),如果您确实有单例 WCF 服务,以获得任何体面的性能,它必须是多线程的(这是一个棘手的编程,这也是我几乎总是反对它的原因)。

    所有服务都有相同的 OperationContract:他们暴露了一个 Register() 和 Send() 方法。

    这也很奇怪。所以任何人调用都会先.Register(),然后用不同的参数调用.Send()几次??有趣的设计,真的.... SOA 假设是您将服务设计为您希望向外部世界公开的一组功能的模型,例如您的 CustomerService 可能有 GetCustomerByIDGetAllCustomersByCountry 等方法 - 取决于您的需要。

    只有一个带有参数的 Send() 方法定义正在执行的操作似乎有点......不寻常且不是很直观/清晰。

    这个图拓扑的想法是 跳过间接链接的消息 不寻常?

    不一定。只向外界公开一个接口,然后使用一些内部后端服务来完成实际工作是有意义的。 .NET 4 实际上会引入一个RoutingService in WCF,这使得这些场景更容易。我不认为这是一个很大的禁忌。

    正在做所有的通信回到一个 客户端通过 CallbackContracts 异常。

    是的,不寻常的、脆弱的、凌乱的——如果你可以没有它——去吧。如果您有大部分简单的调用,例如GetCustomerByID - 将它们设为标准的请求/响应调用 - 客户端请求某些东西(通过提供客户 ID)并返回一个 Customer 对象作为返回值。简单多了!

    如果您确实有长时间运行的服务调用,这可能需要几分钟或更长时间才能完成 - 那么您可能会考虑单向调用,它只是将请求存入队列,然后该请求得到处理。通常,在这里,您可以将答案存入客户端然后检查的响应队列,或者您可以使用两种额外的服务方法来为您提供请求的状态(完成了吗?)和第二种方法来检索该请求的结果。

    希望对您有所帮助!

    【讨论】:

    • Send() 方法采用 ActionMessage DataContract,它有一个用于路由到目的地的字符串 Destination 字段,以及对另一个 DataContract 类型的引用作为有效负载。有效负载 DataContracts 都继承自一个具有 MessageContentType 枚举字段的基本类型,服务用于确定它们是否对在将消息路由之前通过它们的数据处理感兴趣。 Destination 字符串可以指定您希望消息通过的服务节点类型。感谢您的信息。在其他几个回复后我会标记为答案。
    • 我应该补充一点,我们确实有一个 SessionManagerService,它是我们 Silverlight 客户端进入系统的“网关”。最初,他们确实通过这个网关(使用其 Send() 方法)将消息发送到后端服务,该网关将消息路由到正确的后端服务,并将消息从这些服务路由回正确的浏览器客户端实例。然而,现在情况并非如此,在 Clients SessionManager BackEndServices 之间使用单独的消息,所以一切都是单跳的。 SessionManager 实际上保留了 UI 状态并将其“推送”到 Silverlight 客户端。
    【解决方案2】:

    所有服务都有相同的 OperationContract:它们公开了一个 Register() 和 Send() 方法。

    您的设计在某些部分似乎不寻常,特别是仅公开了两个操作。我没有使用 WCF,我们使用 Java。但根据我的理解,Web 服务的全部目的是公开您的合作伙伴可以使用的操作。
    只有两个操作对我来说看起来很奇怪。您通常使用 WSDL 公开您的 API。在这种情况下,除非您有大量文档,否则 WSDL 不会为合作伙伴增加任何价值。通常,操作名称应该是不言自明的。目前,如果没有内部知识,合作伙伴无法使用您的系统。

    通过 CallbackContracts 与客户端进行的所有通信都异常。当然同步或异步请求响应更简单。

    同意你的看法。异步应该只用于长时间运行的进程。异步增加了关联的开销。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 2020-01-10
      • 2020-05-02
      • 1970-01-01
      • 1970-01-01
      • 2012-02-14
      相关资源
      最近更新 更多