.NET 3.5、VS2008、使用 BasicHttpBinding 的 WCF 服务
我有一个托管在 Windows 服务中的 WCF 服务。当 Windows 服务因升级、定期维护等原因关闭时,我需要优雅地关闭我的 WCF 服务。WCF 服务的方法最多可能需要几秒钟才能完成,典型的量是每秒 2-5 次方法调用。我需要以允许任何先前调用方法完成的方式关闭 WCF 服务,同时拒绝任何新调用。通过这种方式,我可以在约 5-10 秒内达到安静状态,然后完成我的 Windows 服务的关闭周期。
调用ServiceHost.Close似乎是正确的方法,但它会立即关闭客户端连接,而无需等待任何正在进行的方法完成。我的 WCF 服务完成了它的方法,但是没有人可以发送响应,因为客户端已经断开连接。这是this question建议的解决方案。
以下是事件的顺序:
- 客户端调用服务上的方法,使用 VS 生成的代理类
- 服务开始执行服务方法
- 服务收到关闭请求
- 服务调用 ServiceHost.Close(或 BeginClose)
- 客户端断开连接,并收到 System.ServiceModel.CommunicationException
- 服务完成服务方法。
- 最终服务检测到它没有更多工作要做(通过应用程序逻辑)并终止。
我需要的是让客户端连接保持打开状态,以便客户端知道他们的服务方法已成功完成。现在他们只是得到一个关闭的连接,不知道服务方法是否成功完成。在使用 WCF 之前,我使用的是套接字,并且能够通过直接控制套接字来做到这一点。(即在仍在进行接收和发送的同时停止接受循环)
关闭主机 HTTP 端口很重要,这样上游防火墙可以将流量引导到另一个主机系统,但现有连接保持打开状态以允许完成现有方法调用。
有没有办法在 WCF 中实现这一点?
我尝试过的事情:
- ServiceHost.Close() - 立即关闭客户端
- ServiceHost.ChannelDispatchers - 在每个上调用 Listener.Close() - 似乎没有做任何事情
- ServiceHost.ChannelDispatchers - 在每个上调用 CloseInput() - 立即关闭客户端
- Override ServiceHost.OnClosing() - 让我延迟关闭,直到我决定可以关闭,但在此期间允许新连接
- 使用此处描述的技术删除端点。这抹杀了一切。
- 运行网络嗅探器以观察 ServiceHost.Close()。主机只是关闭连接,没有响应发送。
谢谢
编辑:不幸的是,我无法实现系统正在关闭的应用程序级咨询响应,因为现场的客户端已经部署。(我只控制服务,不控制客户端)
编辑:我使用 Redgate Reflector 来查看 Microsoft 的 ServiceHost.Close 实现。不幸的是,它调用了一些internal
我的代码无法访问的辅助类。
编辑:我还没有找到我正在寻找的完整解决方案,但本杰明建议使用 IMessageDispatchInspector 在进入服务方法之前拒绝请求最接近。