Dav*_*lle 11 c# wcf basichttpbinding communicationexception
.NET 3.5,VS2008,使用BasicHttpBinding的WCF服务
我有一个Windows服务托管的WCF服务.当Windows服务因升级,定期维护等原因关闭时,我需要正常关闭我的WCF服务.WCF服务的方法可能需要几秒钟才能完成,而典型的卷每秒会有2-5个方法调用.我需要以允许任何先前调用方法完成的方式关闭WCF服务,同时拒绝任何新调用.通过这种方式,我可以在约5-10秒内达到安静状态,然后完成Windows服务的关闭周期.
调用ServiceHost.Close似乎是正确的方法,但它会立即关闭客户端连接,而无需等待任何正在进行的方法完成.我的WCF服务完成了它的方法,但没有人发送响应,因为客户端已经断开连接.这是此问题提出的解决方案.
以下是事件序列:
我需要的是让客户端连接保持打开,以便客户知道他们的服务方法成功完成.现在他们只是获得了一个封闭的连接,并且不知道服务方法是否成功完成.在使用WCF之前,我使用套接字并且能够通过直接控制Socket来实现.(即在仍然执行接收和发送时停止接受循环)
关闭主机HTTP端口非常重要,以便上游防火墙可以将流量定向到另一个主机系统,但现有连接保持打开状态以允许现有方法调用完成.
有没有办法在WCF中实现这一目标?
我尝试过的事情:
谢谢
编辑:不幸的是,我无法实现系统正在关闭的应用程序级别的建议响应,因为该领域的客户端已经部署.(我只控制服务,而不是客户端)
编辑:我使用Redgate Reflector来查看Microsoft的ServiceHost.Close实现.不幸的是,它调用了internal我的代码无法访问的一些辅助类.
编辑:我还没有找到我想要的完整解决方案,但Benjamin建议在输入服务方法之前使用IMessageDispatchInspector拒绝请求.
猜测:
您是否尝试在运行时(从端点)获取绑定,将其强制转换为BasicHttpBinding并在其中(重新)定义属性?
我最好的猜测:
这些可以根据文档在运行时设置,并且似乎允许所需的行为(阻止新客户端).但这对"上游防火墙/负载均衡器需要重新路由"部分没有帮助.
最后一个猜测:你可以(文件说是,但我不确定后果是什么)根据需要将端点的地址重新定义为本地主机地址?如果它不会杀死所有客户端,它也可以作为防火墙主机的"端口关闭".
编辑:在玩上面的建议和有限的测试时,我开始玩消息检查器/行为组合,现在看起来很有希望:
public class WCFFilter : IServiceBehavior, IDispatchMessageInspector {
private readonly object blockLock = new object();
private bool blockCalls = false;
public bool BlockRequests {
get {
lock (blockLock) {
return blockCalls;
}
}
set {
lock (blockLock) {
blockCalls = !blockCalls;
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) {
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) {
foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints) {
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
}
}
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) {
lock (blockLock) {
if (blockCalls)
request.Close();
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState) {
}
}
Run Code Online (Sandbox Code Playgroud)
忘记糟糕的锁用法等,但是使用这个非常简单的WCF测试(返回一个带有Thread.Sleep的随机数),如下所示:
var sh = new ServiceHost(new WCFTestService(), baseAdresses);
var filter = new WCFFilter();
sh.Description.Behaviors.Add(filter);
Run Code Online (Sandbox Code Playgroud)
然后翻转BlockRequests属性我得到以下行为(再次:这当然是一个非常非常简单的例子,但我希望它可能对你有用):
//我产生3个线程请求一个号码..
请求一个号码..
请求一个号码..
//一个传入请求的服务器端日志
一个号码的传入请求.
//主循环翻转"阻止所有内容"bool
从此处阻止访问.
//之后有3个以上的客户端,为了好的措施
请求号码..
请求号码..
请求号码..
//第一个请求(带服务器端日志,见上文)完成成功
收到1569129641
//所有其他消息从未发出它到服务器然后因故障而死
在块之后产生的客户端请求错误.
块后生成的客户端请求出错.
块后生成的客户端请求出错.
块之前的客户端请求出错.
块之前的客户端请求出错.
| 归档时间: |
|
| 查看次数: |
3176 次 |
| 最近记录: |