SOA和WCF设计问题:这是一个不寻常的系统设计吗?

时间:2010-02-17 01:11:00

标签: wcf soa

我发现自己有责任继续开发我原本没有设计过的系统,并且无法向原设计师询问为什么会采取某些设计决策,因为它们不再存在。我是设计问题的初级开发人员,所以当我开始这个项目是第一个SOA / WCF项目时,我真的不知道该问什么。

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

Register()和Send()实际上是OneWay和Async ...服务的所有结果都由WCF CallbackContract返回给客户端服务。我相信使用CallbackContracts的共鸣是促进我们正在使用的发布 - 订阅模型。问题不是我们的所有通信都适合发布 - 订阅和使用CallbackContracts意味着我们必须在返回的结果消息中包含源详细信息,以便客户端可以计算出最初返回的结果...再次客户端有一个switch语句来解决如何处理基于MessageType(以及其他嵌入的详细信息)从服务到达的消息。

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

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

我实际上负责这个并编写了路由系统,这很有趣,但是在我可以问为什么它真的需要之前,领先了。据我所知,没有理由不将服务直接连接到他们需要的其他服务。更重要的是我必须在所有内容之上编写可靠性系统,因为要求在系统中的节点之间具有可靠的消息传递,而通过简单的点对点链接,WCF可靠地完成工作。< / p>

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

1)这种图形拓扑的概念是否在间接链接上跳跃的消息不寻常?为什么不直接将服务连接到他们需要访问的服务(实际上我们正在做的事情......我不认为我们有任何消息跳跃)?

2)在OperationContract中只暴露了两个方法,并使用一个MessageType枚举来确定消息的内容/用什么来处理异常?不应该WCF服务公开许多具有特定目的的方法,而客户端选择它想要调用的方法?

3)通过CallbackContracts进行的所有通信都回到了客户端。当然,同步或asyc请求响应更简单。

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

我有很多WCF问题,后面的帖子会有更多问题。提前谢谢。

2 个答案:

答案 0 :(得分:6)

嗯,整个事情似乎有点奇怪,同意。

  

所有这些都是单一实例   单线程。

这肯定会回来并导致巨大的性能问题 - 保证。我不明白为什么有人想要开始编写单例WCF服务(除了少数边缘情况,它确实有意义),如果你有单一的WCF服务,为了获得任何体面的性能,它必须是多线程的(这是一个棘手的编程,这就是为什么我几乎总是建议反对它。)

  

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

这也很奇怪。所以任何人先调用.Register(),然后用不同的参数多次调用.Send()?有趣的设计,真的...... SOA的假设是你将服务设计为你想要暴露给外部世界的一组功能的模型,例如:您的CustomerService可能包含GetCustomerByIDGetAllCustomersByCountry等方法,具体取决于您的需求。

只有一个带有参数的Send()方法,这些参数定义了正在完成的工作,看起来有点......不寻常,不太直观/清晰。

  

这是图拓扑的概念吗?   消息跳过间接链接   异常?

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

  

正在做一切回复   客户通过CallbackContracts异常。

是的,不寻常,脆弱,凌乱 - 如果你能做到没有它 - 去吧。如果你有大多数简单的调用,比如GetCustomerByID - 使那些标准的请求/响应调用 - 客户端请求某些内容(通过提供客户ID)并获取一个Customer对象作为返回值。简单得多!

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

希望有助于您入门!

答案 1 :(得分:5)

  

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

您的设计在某些部分看起来很不寻常,只能进行两次操作。我没有使用过WCF,我们使用Java。但根据我的理解,Web服务的整个目的是揭示您的合作伙伴可以使用的操作 只有两个操作对我来说看起来像奇怪的设计。您通常使用WSDL公开您的API。在这种情况下,除非您有大量文档,否则WSDL不会给合作伙伴带来任何价值。通常,操作名称应该是不言自明的。目前,没有内部知识,合作伙伴不能使用您的系统。

  

通过CallbackContracts进行的所有通信都回到了客户端。当然,同步或asyc请求响应更简单。

同意你的意见。异步应仅用于长时间运行的进程。 Async增加了相关的开销。