6 votes

Wcf se bloque soudainement (opération web get)

J'ai lu beaucoup d'articles sur le fait que le client devrait fermer la connexion avec client.Close() afin que la limite par défaut de WCF ne soit pas dépassée Le problème est que j'ai une opération WCF WebGet qui renvoie simplement une 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);
  }

Dans cette situation, le client est le navigateur et quoi que je fasse avec la configuration wcf, cela ne sert à rien. maxConnections,maxReceivedMessageSize,maxBytesPerRead et beaucoup d'autres paramètres sont au maximum et toujours pas de chance.

EDIT : Il s'agit d'un code supplémentaire : ImageGet qui est appelée par le 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;
    }

Les ImagesGetStream appelée par la méthode ci-dessus est :

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

Il s'agit d'une partie pertinente de la configuration :

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

1voto

Swetha Points 352

Mes deux cents vérifiez si cela vous aide :

1) Essayez de compresser l'image en utilisant gzip stream ou autre, dans notre projet nous devions envoyer d'énormes ensembles de données à travers le câble en utilisant wcf, nous avions donc l'habitude de les compresser et de les envoyer ensuite à travers le câble.

2) Si la base de données est le goulot d'étranglement, vous pouvez rendre l'appel à la base de données asynchrone et utiliser un mécanisme de file d'attente pour stocker les résultats, et la demande du client wcf essaiera de dé-queuter les résultats à intervalles réguliers.

1voto

zivkan Points 1279

Avant de recycler le pool d'applications, faites une vidange de la mémoire. Si vous avez Visual Studio Enterprise, vous pouvez ouvrir le dump dans une interface graphique agréable et voir la trace de la pile de tous les threads .NET dans le processus. Comme l'application ne répond plus aux demandes, il y a de fortes chances que la plupart des traces de pile se trouvent au même endroit, ce qui vous permettra de savoir où se situe le problème dans le code. Vous saurez alors où concentrer vos efforts.

1voto

CodingYoshi Points 17416

De MSDN :

Par défaut, les transports HTTP, TCP/IP et named pipe utilisent des transferts de messages en mémoire tampon.

Les transferts tamponnés conservent l'intégralité du message dans une mémoire tampon jusqu'à ce que le transfert soit terminé.

Puisque vous n'avez pas spécifié, dans la configuration, l'utilisation de Streaming , il utilise En mémoire tampon comme mode de transfert. Il est donc possible que votre processus manque de mémoire en raison de la présence en mémoire de plusieurs fichiers volumineux (en fonction du nombre de demandes).

Veuillez effectuer les modifications et réessayer. Je pense que cela résoudra le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X