【问题标题】:Wcf suddenly hangs (web get operation)wcf突然挂起(web get操作)
【发布时间】:2016-11-02 10:30:12
【问题描述】:

我阅读了很多关于客户端应该关闭与client.Close() 的连接以便不会超过 WCF 默认限制的文章事情是,我有 WCF WebGet 操作,它基本上只返回一个图像。

[ServiceContract(SessionMode = SessionMode.NotAllowed)]
[ValidationBehavior]
public interface IImagesService
{
    [OperationContract(Name = "ImagesGet4")]
    [WebGet(UriTemplate = "/Image/{partner}/{id}/{image}_{width}_{height}.jpg")]
    Stream ImagesGet2(string partner, string id, string image, string width, string height);
  }

在这种情况下,客户端是浏览器,而我对 wcf 配置所做的任何事情都无济于事。 maxConnections,maxReceivedMessageSize,maxBytesPerRead 和许多其他参数都已用尽,但仍然没有运气。

编辑: 这是附加代码: ImageGet被服务调用的方法:

       public Stream ImagesGet(string partner, string id, string image, string      width = null, string height = null)
        {
           WSData.EventLogs.MinimalEventSource.Log.ClientIp("");
           WSData.EventLogs.MinimalEventSource.Log.ServicePath("");
           WSData.EventLogs.MinimalEventSource.Log.Message( DateTime.Now + " | " + partner );


        bool cache;
        var images = new Images();
        var stream = images.ImagesGetStream(out cache, partner, id, image, width, height);

        if (cache)
        {
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "public, max-age=604800");
            WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.Today;
            WebOperationContext.Current.OutgoingResponse.SetETag(id);
        }

        WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";

        OperationContext clientContext = OperationContext.Current;
        clientContext.OperationCompleted += new EventHandler(delegate (object sender, EventArgs args)
        {
            if (stream != null)
                stream.Dispose();
        });


        return stream;
    }

上述方法调用的ImagesGetStream方法是:

 public Stream ImagesGetStream( out bool cache, string partner, string id, string image, string width = null, string height = null, string background = null )
    {

        string PARTNER = partner;
        cache = true;

        try
        {
            EventLogs.MinimalEventSource.Log.Load( 10, "DatabaseCall" );
            var img = ImagesDL.GetImage( PARTNER, new PrimaryKey( id ) );
            EventLogs.MinimalEventSource.Log.Unload( 13 );

            EventLogs.MinimalEventSource.Log.Load( 14, "GettingImageDir" );
            var imagesRoot = Path.Combine( BaseConfiguration.GetDocumentsSharedDirectory( PARTNER ), img.Url );


            var isWatermarked = img.Group.Contains( "WEBES" ) == false && ( partner.ToUpper() == "ZG-ADRIAGATE1" || partner.ToUpper() == "LENIO-ADRIAGATE2" || partner.ToUpper() == "LENIO" );

            EventLogs.MinimalEventSource.Log.Unload( 15 );

            EventLogs.MinimalEventSource.Log.Load( 16, "ImageToStream" );
            var stream = new FileStream( imagesRoot, FileMode.Open, FileAccess.Read, FileShare.Read );
            EventLogs.MinimalEventSource.Log.Unload( 17 );


            if (!string.IsNullOrEmpty(width))
            {
                var isBackground = !string.IsNullOrEmpty(background);

                int widthp = 0;
                int heightp = 0;

                int.TryParse(width, out widthp);
                int.TryParse(height, out heightp);

                return ResizeImage(partner, stream, new Size(widthp, heightp), isBackground, img.Guest, isWatermarked, background);
            }
            else if(img.Group.Contains("WEBES") == false) {

                Image imgToResize = Image.FromStream(stream);

                if(imgToResize.Width > imgToResize.Height && imgToResize.Width > 2048 )
                    return ResizeImage(partner, stream, new Size(2048, 1536), false, img.Guest, isWatermarked, background);

                else if (imgToResize.Width < imgToResize.Height && imgToResize.Height > 2048)
                    return ResizeImage(partner, stream, new Size(1536, 2048), false, img.Guest, isWatermarked, background);

                else if (imgToResize.Width == imgToResize.Height && imgToResize.Height > 2048)
                    return ResizeImage(partner, stream, new Size(2048, 2048), false, img.Guest, isWatermarked, background);
            }

            return isWatermarked ? WatermarkingImage( partner, stream, img.Guest, isWatermarked ) : stream;



        }
        catch ( Exception )
        {
            cache = false;
            return new FileStream( AppPath + @"\App_Resorces\NoImage.jpg", FileMode.Open, FileAccess.Read, FileShare.Read );
        }
    }

这是配置的相关部分:

<service name="WSTraveller.ImagesService" behaviorConfiguration="ServiceBehavior">
    <endpoint address="soap" binding="basicHttpBinding" behaviorConfiguration="soapBehavior" contract="WSTraveller.IImagesService" bindingConfiguration="soapBinding" bindingName="soapBinding" bindingNamespace="http://ws.adriagate.com/TRWS/ImagesService.svc/soap"/>
    <endpoint address="" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="WSTraveller.IImagesService" bindingConfiguration="webBinding" bindingName="webBinding" bindingNamespace="http://ws.adriagate.com/TRWS/ImagesService.svc/pox"/>
  </service>

...

        <basicHttpBinding>
    <binding name="soapBinding" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" messageEncoding="Text">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
      <security mode="None"/>
    </binding>
  </basicHttpBinding>

【问题讨论】:

  • 您是否曾经跟踪过服务器代码并尝试在调试时复制您的问题?
  • 是的,一旦在数据库调用后停止工作,但对我来说,数据库似乎不太可能是问题,因为它是非常简单的查询。从表格图像中选择一个元素。我在星期一之前没有更多详细信息,因为我的同事正在努力解决这个问题。
  • 这个问题即使没有代码的无限赏金也无法回答。似乎您能够重现问题(?)。发布挂起线程的调用堆栈,包括外部代码。
  • 无法手动重现问题或使其挂起。它每天在生产环境中发生几次。我们虽然问题是因为一些图像真的很大,所以我们将大小调整到最大 2400×1800,但这也没有帮助。
  • 至少发布该 ImageGet 的完整代码

标签: c# wcf


【解决方案1】:

我的两分钱..检查这是否对您有帮助:

1) 尝试使用 gzip 流压缩图像,在我们的项目中,我们必须使用 wcf 跨线发送大量数据集,因此我们习惯于压缩然后发送它。

2) 如果数据库是瓶颈,那么您可以使数据库调用异步并使用队列机制来存储结果,wcf 客户端请求将尝试定期将结果出队。

【讨论】:

    【解决方案2】:

    在回收应用程序池之前,进行内存转储。如果您有 Visual Studio Enterprise,您可以在一个漂亮的 gui 中打开转储并查看进程中所有 .NET 线程的堆栈跟踪。由于应用程序不再响应请求,因此大多数堆栈跟踪很有可能位于同一位置,这将告诉您代码中的问题所在。然后你就知道应该把精力放在哪里。

    【讨论】:

      【解决方案3】:

      来自MSDN

      默认情况下,HTTP、TCP/IP 和命名管道传输使用缓冲消息传输。

      缓冲传输将整个消息保存在内存缓冲区中,直到传输完成。

      由于你没有在配置中指定使用Streamed,它使用Buffered作为传输模式。因此,由于内存中保存了多个(取决于数量或请求)大文件,您的进程可能内存不足。

      请进行更改,然后重试。我认为这将解决问题。

      【讨论】:

      • 嗨,我的同事正在研究这个问题,我已经向他推荐了这个解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-22
      • 2010-10-30
      • 2014-12-17
      • 1970-01-01
      • 2013-08-18
      • 1970-01-01
      相关资源
      最近更新 更多