Transfert de grandes charges de données (objets sérialisés) à l'aide de wsHttp dans WCF avec sécurité des messages
J'ai un cas où j'ai besoin de transférer de grandes quantités de l'objet sérialisé graphiques (via NetDataContractSerializer) à l'aide de la WCF à l'aide de wsHttp. Je suis en utilisant le message de sécurité et que vous souhaitez continuer à le faire. Avec cette configuration je voudrais transférer objet sérialisé graphique qui peut parfois démarche autour de 300 MO ou si, mais quand j'essaie de le faire, j'ai commencé à voir une exception de type System.InsufficientMemoryException apparaissent.
Après un peu de recherche, il semble que par défaut dans WCF qui suite à un appel de service est contenue dans un seul message par défaut qui contient les données sérialisées et ces données sont mises en mémoire tampon par défaut sur le serveur jusqu'à ce que le message entier est complètement écrit. Ainsi, la mémoire de l'exception qui est causé par le fait que le serveur est en cours d'exécution hors de la mémoire de ressources qu'il est autorisé à allouer parce que le tampon est plein. Les deux principales recommandations que j'ai rencontré sont à utiliser en continu ou de segmentation pour résoudre ce problème, toutefois, il n'est pas clair pour moi ce que cela implique et si une ou l'autre solution est possible avec mon installation actuelle (wsHttp/NetDataContractSerializer/Message de Sécurité). Jusqu'à présent, je comprends que pour utiliser la diffusion de messages de sécurité ne marche pas car le message de chiffrement et de déchiffrement besoin de travailler sur l'ensemble des données et non pas une partie du message. Chunking cependant sonne comme il pourrait être possible, mais il n'est pas clair pour moi comment faire avec les autres contraintes que j'ai énumérés. Si quelqu'un pourrait donner des indications sur ce que sont les solutions disponibles et comment la mettre en œuvre, je vous en serais très reconnaissante.
Je dois ajouter que dans mon cas, je ne suis vraiment pas inquiet à propos de l'interopérabilité avec d'autres clients que nous possédons et de contrôle de chaque côté de la communication et l'utilisation de l'interface partagée modèle pour les données transférées de chaque côté. Donc je suis ouvert à toute idée qui s'adapte à l'intérieur des contraintes de l'utilisation de wsHttp avec le message de sécurité pour le transfert de graphes d'objets sérialisés à l'aide de NetDataContractSerializer et je préfère une solution où je n'ai pas changer mes services existants et les infrastructures environnantes de façon drastique.
Ressources connexes:
- Chunking Canal
- Comment: Activer la diffusion en continu
- Pièces jointes volumineuses sur WCF
- Message Personnalisé Codeur
- Un autre de repérage de InsufficientMemoryException
- Non-Duplex Chunking Canal
- Le Streaming de contenu de grande taille avec WCF et l'exécution différée
Je suis aussi intéressé par tout type de compression qui pourrait être fait de ces données, mais il semble que je serait probablement mieux de faire cela au niveau du transport une fois que je peux transition .NET 4.0 afin que le client sera automatiquement en charge le gzip-têtes si je comprends correctement.
Mise à jour (2010-06-29):
Un peu d'histoire sur la façon dont j'ai tiré à la conclusion que la mémoire tampon de message trop grande était la cause de mon problème. À l'origine, j'ai vu le CommunicationException ci-dessous lors des tests.
La connexion sous-jacente a été fermée: La connexion a été fermée de façon inattendue.
Finalement, après l'exécution de cette et en faisant encore plus de journalisation j'ai trouvé le sous-jacent InsufficientMemoryException exception qui a été à l'origine du problème avec le message spécifié.
N'a pas pu allouer une gestion de la mémoire tampon de 268435456 octets. La quantité de mémoire disponible peut être faible.
À l'origine de la méthode suivante.
Système.ServiceModel.Diagnostics.Utilitaire.AllocateByteArray(taille Int32)
Donc dans otherwords l'échec est venu de l'allocation de la matrice. Lors de l'écriture les mêmes données sérialisées sur le disque, il prend place autour de 146MB et si je l'ai coupé de moitié puis-je arrêter l'obtention de l'erreur cependant, je n'ai pas creusé plus le seuil spécifique qui brise mon tampon et si elle spécifique à mon système ou pas.
Mise à jour (2010-12-06):
Je suppose qu'à ce stade, je suis à la recherche pour certains clarifcation pour la suite. Ma compréhension est que, par défaut, avec WCF wsHttp avec le message de sécurité que l'ensemble d'un message (généralement de l'ensemble de données, je suis de retour) doit être mis en mémoire tampon sur le serveur avant que la réponse est envoyée au client et donc la cause de mes problèmes.
Solutions possibles:
- Limitant la taille des données En utilisant une certaine forme de compression, encodage, ou la limitation des données réelles retournés à l'aide d'une sorte de pagination comme méthode afin d'éviter de consommer de la capacité maximale de la sortie de la mémoire tampon.
- Streaming - Permet de grandes quantités de données pour être envoyé par la WCF en continu de la mode mais ce n'est pas compatible avec wsHttp ou MessageSecurity depuis ces techniques nécessitent la mise en mémoire tampon toutes les données.
- Chunking Canal Permet aux données d'être divisé en plusieurs messages, mais à ce point, je ne suis pas sûr de les contraintes sur le contrat de service de conception et de savoir si je peux encore utiliser wsHttp avec le message de liaison.
De limiter les données que je peux retourner ne fonctionne que jusqu'à un certain point et, comme avec l'option de diffusion de ces options nécessitent le codage d'un lot de la baisse du niveau de travail à l'extérieur de la WCF les appels de service. Donc je suppose que j'ai besoin de savoir, c'est si possible de la mise en œuvre de la segmentation du canal côté les grands problèmes de message en permettant à un ensemble unique de données pour être fractionnée en plusieurs messages sur le serveur et ensuite rassemblés sur le client de telle manière que je n'ai pas à changer l'interface, la forme de contrats de services existants et de façon à ce que le processus est assez bien caché, le client et la partie serveur de chaque service de la mise en œuvre, tout en utilisant la sécurité des messages et wsHttp. Si le chunking-canal va m'obliger à re-écrire ma de contrats de service à exposer les ruisseaux, alors je ne vois pas en quoi cela est vraiment différent de la solution de diffusion. Si quelqu'un peut il vous suffit de répondre à ces questions pour moi, je vais remettre de l'abondance et de la marquer comme réponse.
source d'informationauteur jpierson
Vous devez vous connecter pour publier un commentaire.
protobuf-net a généralement un significative d'économie de l'espace (comme dans: l'ordre de grandeur) sur la plupart des données, et peut s'attacher à la WCF. Malheureusement au moment il ne prend pas en charge complète des graphiques, des arbres. Cependant, j'ai plans là que simplement, je n'ai pas eu le temps de les mettre en œuvre. Je ne peux rien promettre, mais je pourrais essayer de bosse qui travail un peu plus tôt.
Autrement; il y a peut-être des moyens pour modifier votre code existant de travailler avec un arbre au lieu d'un graphe.
Si vous voulez toujours utiliser un Message de Sécurité, je vous recommande d'utiliser MTOM pour optimiser la bande passante du réseau qui doit être utilisée pour transférer les messages, et aussi le chunking canal pour l'utilisation de petites zones de mémoire tampon lorsque la sécurité est appliquée. Sinon, WCF va essayer de charger la totalité du message dans la mémoire pour appliquer la sécurité, et, par conséquent, vous obtiendrez la mémoire Insuffisante exception.
j'ai utilisé pour mettre en œuvre un peu réussissant texte/de la wcf. mon trig est convertir en flux et l'utilisation GZipStream à compresser, puis de l'envoyer comme byte[], heureusement il n'est jamais dépasser 10 MO.
Dans votre cas, je vous recommande de faire de la fragmentation. Convertir objet Sérialisé à byte[] et puis merg et décompresser
psudo
modifier 08 Déc 2010
ok basé sur ma compréhension de la situation du client est de télécharger certains grands sérialiser un objet à travers la WCF.
je n'ai pas particulièrement de test sur cette solution, mais crois que cela devrait fonctionner. La clé est de sauvegarder les objets sérialisés de fichier et utiliser la Réponse de transmettre ce fichier.
WCF est recommandé de ne fichier automatiquement la diffusion et u ne pas avoir à vous soucier objet sérialisé taille puisque nous utilisons le fichier de transmettre. N'oubliez pas de la config de réponse limite.
Quelques légers, mais pas de la garantie des solutions serait de
DataContractSerializer
au lieu puisque vous possédez des deux côtés. Cela ne nécessite pas intégré d'information de type, ce qui est très grand.[DataMember(EmitDefaultValue = false)]
qui est discuté dans une question que j'avais posée de nouveau parce que vous êtes propriétaire des deux côtés; cela permettra de réduire en partie sur la taille du message (la quantité dépend bien sur du nombre de domaines dans le graphique sont les paramètres par défaut).[DataContract(IsReference=true)]
surtout si vous avez répété plusieurs objets de valeur ou des données de référenceCe sont, bien sûr, de compromis, par exemple à la lisibilité.
Puisque personne n'a mis là, peut-être en utilisant Les WebSockets ou le temps d'interrogation techniques peuvent être en mesure de résoudre ce problème. J'ai seulement regardé dans ces solutions brièvement et n'ont pas développé une solution autour d'eux, mais je voulais proposer ces concepts pour l'enregistrement et je vais élargir ma réponse à un moment plus tard, si le temps le permet.
L'idée sous-jacente serait d'arriver à quelque chose de similaire à la façon dont l'idée de la façon dont le ChunkingChannel exemple fonctionne, mais tout en ne nécessitant pas de full duplex canal qui parvient généralement le port 80 basé sur le web de requête/réponse modèle qui est souhaitable pour éviter d'avoir à faire des pare-feu et d'autres configurations pour les clients.
Autres matériels connexes:
Mise à jour: Après des recherches plus sur ce qu'il apparaît qu'en utilisant les WebSockets, qui est connu connu comme NetHttpBinding, que je ferais n'est pas en soi être la résolution de la demande originale, qui consiste à utiliser wsHttp dans WCF avec le message de sécurité. Je vais garder ma réponse ici toutefois que des informations pour d'autres personnes qui peuvent être à la recherche d'une alternative.