none
WCF服务端和客户端通信的问题 RRS feed

  • 问题

  • 经常有一种情景:
    一台server,若干client,server从第三方(硬件数据、另外一个系统、也可能是自己的client)获取消息,然后转发给所有的client。很简单,很常见的一个场景,大家来讨论我的思路、方法是否合理,是否还有其他方法可参考。先谢谢各位能参与讨论。

    我的思路是:
    只能通过发布-订阅来实现。

    实现方法:

    两种常用方法:临时订阅、持久化订阅。

    在这描述下实际应用中,我的使用感受及碰到的问题。

    临时订阅:就是采用大家都在说的回调机制,服务器端启动服务,客户端去调用,建立连接,服务器通过保持该连接,主动发消息给客户端。【此方法经我测试发现有个很严重的问题:如果服务器端长时间没有通过该通道回调(主动发数据)给客户端数据,最长时间大概最多可以设置为20小时多点,采用‘心跳’方式貌似可解决,就是服务器端定期给客户端发送数据,只是客户端不处理】。本人感觉这种方式很猫腻。

    持久化订阅:就是在客户端和服务器端各建立自己的服务,首先客户端在启动的时候会去连接服务端(此时将自己的服务地址告诉服务端,服务端会将其持久化),同时启动自己的服务。这样一来,服务器端一旦有新的消息,就可以通过从持久化的数据中读出所有需要通知的客户端,然后通过访问客户端的服务发送消息给客户端。在这里,所谓的服务端和客户端是相对的,在客户端启动,发起订阅的时候,客户端是客户端,服务端是服务端;在服务端收到消息,转发消息给客户端时,客户端就是服务端,服务端就是客户端。本人觉得此方式更合理,但在使用过程中还是一些实际操作的困难性。比如:客户端正常退出时,要去 unsubscribe,ok。但是,如果客户端非正常退出时,它的地址并不会被服务器端从持久化的地方删除,所以服务器端还会继续往这个并不存在的服务地址发送消息,虽然我采用的是异步发送(即针对每一个客户端建立自己的连接,并且各自不影响),当数据量稍微达到一个数量级时,server会提示忙碌而不能处理所有的消息,直到超时。在这,我加了个处理,就是当捕获ExceptionNotFound时(可考虑重发几次),然后就从server清理掉该客户端地址,但还有个小问题,就是我的异步感觉没起到作用,即,当一个地址不存在时,理论上其他的地址不受任何影响,然而实际是:其他的地址发送会变的很慢,直到ExceptionNotFound后清理掉该地址后的一段时间,才能恢复正常。一直没解决此问题,也没看其他人有此问题,故提出求大家帮忙解决。如需关键代码,我之后贴上来。
    2010年3月15日 9:23

答案

  • 和你一起讨论一下。
    不好意思,没来得及回复你的帖子。
    你的两种方法 都可以实现。
    方法1,心跳确实可以解决这个问题,但是通道最长连接时间20小时,这个有点太久了,而且一旦中间网络出问题,基本连接不可用。
    方法2,倒是许多大型的中间件平台的做法,但是你这里单线程处理的时候,即使是异步模式执行,当异步执行的方法过多的时候也会出现线程阻塞的问题。建议使用多线程,也就是独立的线程来负责发送消息到客户端,而且使用异步模式。
    另外记得及时释放你使用的网络连接。最好c#语法使用Using语句。


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    • 已标记为答案 Mog Liang 2010年3月19日 9:05
    2010年3月16日 15:52
    版主