Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wcf suddenly hangs (web get operation)

Tags:

c#

wcf

I read lot of articles about fact that client should close connection with client.Close() so WCF default limit does not get exceeded Thing is, I have WCF WebGet operation which basicly just returns an image.

[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);
  }

In this situation client is browser and whatever I do with wcf configuration does not help. maxConnections,maxReceivedMessageSize,maxBytesPerRead and lot of other parameters are maxed out and still no luck.

EDIT : This is additional code: ImageGet method which is called by service:

       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;
    }

The ImagesGetStream method which is called by the above method is :

 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 );
        }
    }

This is relevant part of config:

<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>
like image 804
Vlado Pandžić Avatar asked Nov 02 '16 10:11

Vlado Pandžić


1 Answers

My two cents..check if this helps you:

1) try compressing the image using gzip stream or so, in our project we had to send huge datasets across wire using wcf so we used to compress and then send it across.

2) if the database is the bottleneck then you can make the db call asynchronous and use a queue mechanism to store the results and wcf client request would try and dequeue result at a regular interval.

like image 176
Swetha Avatar answered Oct 26 '22 17:10

Swetha