简体   繁体   English

WCF服务超时,然后执行操作?

[英]WCF Service times out, then performs action?

Ok, I have a WCF service, which is behaving in a pretty awkward way. 好的,我有一个WCF服务,它的运行方式很尴尬。 The thing is, when I make the call to the service method, like this: 问题是,当我调用service方法时,如下所示:

using (var wcf = new Wcf<IDroneService>("http://test.group.com/DroneService.svc"))
{
    wcf.Channel.StartLoadTest(scenario);
}

Nothing happens until the request times out after a minute, but then, and only then, after the exception has been thrown, the WCF service (hosted in IIS) starts, that is, actually loads its assemblies, and runs Application_Start, instances the service endpoints on the server side, etc. and it goes on to properly receive the request, and execute it . 直到一分钟后请求超时,什么都没有发生,但是只有在抛出异常之后,WCF服务(托管在IIS中)才会启动,即,实际上加载其程序集并运行Application_Start,该服务实例服务器端等端点,然后继续正确接收请求并执行它 But this only happens AFTER the request has timed out and an exception has been thrown. 但这仅在请求超时并引发异常之后才发生。

This is how I configure both my client and server bindings: 这是我配置客户端和服务器绑定的方式:

public class WcfConfigurator
{
    public Binding GetBinding()
    {
        var basic = new BasicHttpBinding
        {
            MaxBufferSize = int.MaxValue,
            MaxBufferPoolSize = int.MaxValue,
            MaxReceivedMessageSize = int.MaxValue,
            TransferMode = TransferMode.Streamed,
            ReceiveTimeout = TimeSpan.FromSeconds(30),
            ReaderQuotas =
            {
                MaxDepth = int.MaxValue,
                MaxStringContentLength = int.MaxValue,
                MaxArrayLength = int.MaxValue,
                MaxBytesPerRead = int.MaxValue,
                MaxNameTableCharCount = int.MaxValue
            }
        };
        return basic;
    }

    public void ConfigureBehavior(ServiceEndpoint endpoint)
    {
        foreach (OperationDescription op in endpoint.Contract.Operations)
        {
            var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
            if (dataContractBehavior != null)
            {
                dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
            }
        }
    }

    public void ConfigureBehavior(KeyedByTypeCollection<IServiceBehavior> behaviors)
    {
        var serviceDebugBehavior = behaviors.Find<ServiceDebugBehavior>();
        if (serviceDebugBehavior != null)
        {
            serviceDebugBehavior.IncludeExceptionDetailInFaults = Config.Wcf.ExceptionDetails;
        }
    }
}

I use that same programmatic configuration on the server side, to build the endpoints. 我在服务器端使用相同的编程配置来构建端点。 This issue only arises from big envelopes, this is not a problem for smaller envelopes. 此问题仅由较大的信封引起,对于较小的信封则不是问题。

Am I missing something in my configuration of the Wcf channel? 我在Wcf频道的配置中是否缺少某些内容? Wcf<T> is just a wrapper around ChannelFactory.CreateChannel ; Wcf<T>只是ChannelFactory.CreateChannel的包装; on the WCF server I configure it programmatically as well, with the Windsor WcfIntegration facility. 在WCF服务器上,我也使用Windsor WcfIntegration工具以编程方式对其进行配置。 Like this: 像这样:

public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
    ServiceHostBase serviceHost = base.CreateServiceHost(constructorString, baseAddresses);
    return ConfiguredServiceHost(serviceHost);
}

private T ConfiguredServiceHost<T>(T serviceHost) where T : ServiceHostBase
{
    serviceHost.AddDefaultEndpoints();

    wcfConfigurator.ConfigureBehavior(serviceHost.Description.Behaviors);

    foreach (ServiceEndpoint endpoint in serviceHost.Description.Endpoints)
    {
        endpoint.Binding = wcfConfigurator.GetBinding();
        wcfConfigurator.ConfigureBehavior(endpoint);
    }
    return serviceHost;
}

Although I don't believe this to be a server-side problem (at least not so far anyway), because like I said, symbols for the WCF server don't even load if the envelope is too big (until the request times out, and its processed anyways). 尽管我不认为这是服务器端的问题(至少到目前为止还不是这样),但是正如我所说的,如果信封太大,则WCF服务器的符号甚至都不会加载(直到请求超时) ,并且仍进行处理)。

Has anyone come across this weird issue before? 有人遇到过这个奇怪的问题吗?

From my experience with WCF - WCF errors are hard to predict and diagnostic, deep investigation required with extensive logging and WCF tracing enabled in place. 根据我在WCF方面的经验-WCF错误很难预测和诊断,需要进行广泛的日志记录和WCF跟踪才能进行深入研究。 I feel there is some misconfiguration on client/server service timeouts. 我觉得客户端/服务器服务超时有一些配置错误。 SO install latest version of Fiddler, see what is going on, which requests were sent, whether response was sent or not. 因此,请安装Fiddler的最新版本,看看发生了什么,发送了哪些请求,是否发送了响应。 Also enable WCF tracing with switchLevel="All" , in most cases WCF trace log explicitly point you to an issue. 还要使用switchLevel="All"启用WCF跟踪,在大多数情况下,WCF跟踪日志会明确指出您存在问题。

You mentioned 1 minute... 你提到1分钟...

Timeouts in WCF and their default values WCF中的超时及其默认值

These are the most well known timeouts. 这些是最著名的超时。 SendTimeout , ReceiveTimeout , OpenTimeout and CloseTimeout . SendTimeoutReceiveTimeoutOpenTimeoutCloseTimeout They can be set easily either through config or code on the Binding. 可以通过配置或绑定上的代码轻松设置它们。 The default value for those are 1 minute 这些的默认值为1分钟

Try out increasing its values explicitly, but as first thing I would recommend understand what is the issue, why it is appear, because 1 minute to estblish connection is pretty enough. 尝试显式增加其值,但是首先我建议您了解问题的根源,原因,因为建立连接1分钟就足够了。

I have had similar issues before with WCF and it led me to using the ChannelFactory when consuming a service. 在使用WCF之前,我曾遇到过类似的问题,这使我在使用服务时不得不使用ChannelFactory。 I know it doesn't explain your error, but maybe it's worth trying. 我知道它不能解释您的错误,但是也许值得尝试。 Here's how I did it: 这是我的操作方式:

internal static class ServiceObjects
{
    public static ISomeService SomeSVC { get { return GetSomeServiceClient(); }

    private static BasicHttpBinding _Binding = new BasicHttpBinding("SomeBasicHttpBindingEndpoint"); 
    private static EndpointAddress _Endpoint = new EndpointAddress(new Uri("http://test.helloworld.com/SomeService.svc"));

    private static IDocManagerService GetDocServiceClient()
    {
        ChannelFactory<ISomeService> _someSvcFactory = new ChannelFactory<ISomeService>(_Binding, _Endpoint);

        foreach (OperationDescription op in _someSvcFactory.Endpoint.Contract.Operations)
        {
            DataContractSerializerOperationBehavior _dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>() as DataContractSerializerOperationBehavior;

            if (_dataContractBehavior != null)
            {
                _dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
            }
        }

        return _someSvcFactory.CreateChannel();
    }
}

And consume the service: 并使用服务:

ServiceObjects.SomeSVC.SomeMethod()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM