我发现自己负责继续开发一个我原本没有设计的系统,并且不能要求原始设计师为什么采取某些设计决策,因为他们不在这里。我是一名设计问题的初级开发人员,因此在开始执行我的第一个SOA/WCF项目的项目时,并不知道该问什么。SOA和WCF设计问题:这是一个不寻常的系统设计吗?
该系统有7个WCF服务,将增长到9个,每个自我托管在一个单独的控制台应用程序/ Windows服务。所有这些都是单实例和单线程的。所有服务都具有相同的OperationContract:它们公开Register()和Send()方法。当客户端服务想要连接到另一个服务时,他们首先调用Register(),然后如果成功,他们会执行全部与Send()的其余通信。我们有一个DataContract,它具有一个枚举MessageType和一个可以包含其他DataContract“有效内容”的Content propety。这个服务对消息的处理是由枚举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可靠地完成这项工作。
在此项目之前,我只在winforms桌面应用上工作了3年,不知道更好。我的怀疑是这个项目过于复杂的事情:我想总结一下,我的问题是:
1)这种思想的图形拓扑消息跳过间接链接异常?为什么不直接将服务直接连接到他们需要访问的服务(实际上我们是这样做的......我不认为我们有任何消息跳跃)?
2)在OperationContract中只公开了2个方法,并使用MessageType枚举来确定消息的用途/用它做些什么异常?不应该有一个WCF服务暴露了许多具有特定目的的方法,而客户端选择了它想调用的方法?
3)正在通过CallbackContracts与客户进行所有通信。当然,同步或异步请求响应更简单。
4)服务是否允许客户端服务连接到它(注册),直到它连接到它的所有服务(它是客户端)为止的声音设计?我认为这是我同意的唯一设计方面,我的意思是DataAccessService在与日志服务连接之前不应该接受客户端。
我有太多的WCF问题,以后会有更多的问题。提前致谢。
Send()方法接受一个ActionMessage DataContract,它具有用于路由到目标的字符串Destination字段,以及对另一个DataContract类型的引用作为有效内容。有效载荷DataContracts全部从具有MessageContentType枚举字段的基本类型继承,正是这种服务用于确定它们是否对通过它们的数据处理感兴趣,然后才将它们路由到该消息。目标字符串可以指定您希望消息通过的服务节点类型。 感谢您的信息。在其他一些答复之后,我将其标记为答案。 – MrLane 2010-02-17 06:52:02
我应该补充一点,我们确实有一个SessionManagerService,它是我们的Silverlight客户端系统的“网关”。最初他们确实通过这个网关(使用它的Send()方法)向后端服务发送消息,该消息将消息路由到正确的后端服务,并将消息路由回到来自这些服务的正确浏览器客户端实例。然而,现在,情况并非如此,在客户端<> SessionManager <> BackEndServices之间使用了单独的消息,因此eveything是单跳。 SessionManager实际上保留了UI状态并将其“推送”给Silverlight客户端。 – MrLane 2010-02-17 07:08:16