Condividi tramite


Dati e streaming di grandi dimensioni

Windows Communication Foundation (WCF) è un'infrastruttura di comunicazione basata su XML. Poiché i dati XML vengono comunemente codificati nel formato di testo standard definito nella specifica XML 1.0, gli sviluppatori di sistemi connessi e gli architetti sono in genere preoccupati per il footprint di filo (o le dimensioni) dei messaggi inviati in rete e la codifica basata su testo di XML pone sfide speciali per il trasferimento efficiente dei dati binari.

Considerazioni di base

Per fornire informazioni di base sulle informazioni seguenti per WCF, in questa sezione vengono evidenziati alcuni aspetti generali e considerazioni per le codifiche, i dati binari e lo streaming che in genere si applicano alle infrastrutture di sistemi connessi.

Dati di codifica: testo e binario

Le preoccupazioni degli sviluppatori comunemente espresse includono la percezione che XML abbia un sovraccarico significativo rispetto ai formati binari a causa della natura ripetitiva dei tag di inizio e dei tag finali, che la codifica dei valori numerici è considerata significativamente più grande perché sono espressi in valori di testo e che i dati binari non possono essere espressi in modo efficiente perché devono essere codificati appositamente per l'incorporamento in un formato di testo.

Anche se molti di questi problemi e simili sono validi, la differenza effettiva tra i messaggi con codifica XML in un ambiente di servizi Web XML e i messaggi con codifica binaria in un ambiente RPC (Remote Procedure Call) legacy è spesso molto meno significativo della considerazione iniziale.

Anche se i messaggi con codifica XML sono trasparenti e "leggibili", i messaggi binari sono spesso piuttosto oscuri rispetto e difficili da decodificare senza strumenti. Questa differenza di leggibilità porta a ignorare che i messaggi binari spesso contengono metadati inline nel payload, che comportano un sovraccarico proprio come con i messaggi di testo XML. Questo vale in particolare per i formati binari che mirano a fornire funzionalità di accoppiamento libero e chiamate dinamiche.

Tuttavia, i formati binari in genere contengono tali informazioni descrittive sui metadati in un'intestazione, che dichiara anche il layout dei dati per i record di dati seguenti. Il payload segue quindi questa dichiarazione comune del blocco di metadati con un sovraccarico minimo. Al contrario, XML racchiude ogni elemento di dati in un elemento o un attributo in modo che i metadati di inclusione vengano inclusi ripetitivamente per ogni oggetto payload serializzato. Di conseguenza, le dimensioni di un singolo oggetto payload serializzato sono simili quando si confronta il testo con le rappresentazioni binarie come alcuni metadati descrittivi devono essere espressi per entrambi, ma il formato binario trae vantaggio dalla descrizione dei metadati condivisi con ogni oggetto payload aggiuntivo trasferito a causa del sovraccarico complessivo inferiore.

Tuttavia, per determinati tipi di dati, ad esempio numeri, potrebbe esserci uno svantaggio nell'uso di rappresentazioni numeriche binarie a dimensione fissa, ad esempio un tipo decimale a 128 bit anziché testo normale, poiché la rappresentazione di testo normale potrebbe essere più piccola di diversi byte. I dati di testo possono anche avere vantaggi dalle scelte di codifica più flessibili tipiche del testo XML, mentre alcuni formati binari potrebbero essere predefiniti a 16 bit o addirittura a 32 bit Unicode, il che non si applica al formato .NET Binary XML.

Di conseguenza, decidere tra testo o binario non è abbastanza facile come supponendo che i messaggi binari siano sempre più piccoli dei messaggi di testo XML.

Un chiaro vantaggio dei messaggi XML-text è che sono basati su standard e offrono la scelta più ampia di opzioni di interoperabilità e supporto della piattaforma. Per altre informazioni, vedere la sezione "Codifiche" più avanti in questo argomento.

Contenuto binario

Un'area in cui le codifiche binarie sono superiori alle codifiche basate su testo in termini di dimensioni dei messaggi risultanti sono elementi di dati binari di grandi dimensioni, ad esempio immagini, video, clip audio o qualsiasi altra forma di dati binari opachi che devono essere scambiati tra i servizi e i relativi consumer. Per adattare questi tipi di dati in testo XML, l'approccio comune consiste nel codificarli usando la codifica Base64.

In una stringa codificata in Base64, ogni carattere rappresenta 6 bit dei dati originali a 8 bit, con un rapporto di sovraccarico di codifica di 4:3 per Base64, non contando i caratteri di formattazione aggiuntivi (ritorno a capo/avanzamento riga) che sono comunemente aggiunti per convenzione. Anche se il significato delle differenze tra le codifiche XML e binarie dipende in genere dallo scenario, un aumento delle dimensioni di oltre 33% durante la trasmissione di un payload di 500 MB non è in genere accettabile.

Per evitare questo sovraccarico di codifica, lo standard MTOM (Message Transmission Optimization Mechanism) consente di esternalizzare elementi di dati di grandi dimensioni contenuti in un messaggio e di trasportarli con il messaggio come dati binari senza alcuna codifica speciale. Con MTOM, i messaggi vengono scambiati in modo simile ai messaggi di posta elettronica SMTP (Simple Mail Transfer Protocol) con allegati o contenuti incorporati (immagini e altro contenuto incorporato); I messaggi MTOM vengono inseriti in un pacchetto come sequenze MIME multipart/correlate con la parte radice che rappresenta il messaggio SOAP effettivo.

Un messaggio SOAP MTOM viene modificato dalla versione non codificata in modo che i tag di elemento speciali che fanno riferimento alle rispettive parti MIME prendano il posto degli elementi originali nel messaggio che contiene dati binari. Di conseguenza, il messaggio SOAP fa riferimento al contenuto binario puntando alle parti MIME inviate con esso, ma in caso contrario contiene solo dati di testo XML. Poiché questo modello è strettamente allineato al modello SMTP ben consolidato, è disponibile un ampio supporto per codificare e decodificare i messaggi MTOM in molte piattaforme, che lo rende una scelta estremamente interoperabile.

Tuttavia, come con Base64, MTOM comporta anche un sovraccarico necessario per il formato MIME, in modo che i vantaggi dell'uso di MTOM vengano visualizzati solo quando le dimensioni di un elemento dati binario superano circa 1 KB. A causa del sovraccarico, i messaggi con codifica MTOM potrebbero essere maggiori dei messaggi che usano la codifica Base64 per i dati binari, se il payload binario rimane inferiore a tale soglia. Per altre informazioni, vedere la sezione "Codifiche" più avanti in questo argomento.

Contenuto di dati di grandi dimensioni

Oltre all'impronta dei fili, un payload di 500 MB già menzionato rappresenta anche una grande sfida a livello locale per il servizio e il cliente. Per impostazione predefinita, WCF elabora i messaggi in modalità memorizzata nel buffer. Ciò significa che l'intero contenuto di un messaggio è presente in memoria prima dell'invio o dopo la ricezione. Sebbene si tratti di una buona strategia per la maggior parte degli scenari e necessaria per le funzionalità di messaggistica, ad esempio firme digitali e recapito affidabile, i messaggi di grandi dimensioni potrebbero esaurire le risorse di un sistema.

La strategia per gestire payload di grandi dimensioni è lo streaming. Mentre i messaggi, in particolare quelli espressi in XML, sono comunemente considerati pacchetti di dati relativamente compatti, un messaggio potrebbe essere di dimensioni di svariati gigabyte e assomigliare più a un flusso di dati continuo che a un pacchetto di dati. Quando i dati vengono trasferiti in modalità di streaming anziché in modalità memorizzata nel buffer, il mittente rende il contenuto del corpo del messaggio disponibile per il destinatario sotto forma di flusso e l'infrastruttura dei messaggi inoltra continuamente i dati dal mittente al destinatario non appena diventa disponibile.

Lo scenario più comune in cui si verificano trasferimenti di contenuto di dati di grandi dimensioni sono i trasferimenti di oggetti dati binari che:

  • Non è possibile suddividere facilmente in una sequenza di messaggi.

  • Deve essere consegnato in modo tempestivo.

  • Non sono disponibili nel loro complesso quando viene avviato il trasferimento.

Per i dati che non hanno questi vincoli, in genere è preferibile inviare sequenze di messaggi nell'ambito di una sessione rispetto a un messaggio di grandi dimensioni. Per altre informazioni, vedere la sezione "Streaming data" più avanti in questo argomento.

Quando si inviano grandi quantità di dati, è necessario impostare l'impostazione maxAllowedContentLength IIS (per altre informazioni, vedere Configurazione dei limiti delle richieste IIS) e l'impostazione maxReceivedMessageSize di associazione ( ad esempio System.ServiceModel.BasicHttpBinding.MaxReceivedMessageSize o MaxReceivedMessageSize). La proprietà maxAllowedContentLength è impostata per impostazione predefinita a 28,6 MB e la proprietà maxReceivedMessageSize è impostata per impostazione predefinita a 64 KB.

Codifiche

Una codifica definisce un set di regole su come presentare i messaggi in transito. Un codificatore implementa tale codifica ed è responsabile, sul lato mittente, di trasformare un in memoria Message in un flusso di byte o un buffer di byte che può essere inviato attraverso la rete. Sul lato ricevitore, il codificatore trasforma una sequenza di byte in un messaggio in memoria.

WCF include tre codificatori e consente di scrivere e collegare codificatori personalizzati, se necessario.

Ognuna delle associazioni standard include un codificatore preconfigurato, in base al quale le associazioni con il prefisso Net* usano il codificatore binario (includendo la BinaryMessageEncodingBindingElement classe ) mentre le BasicHttpBinding classi e WSHttpBinding usano il codificatore di messaggi di testo (tramite la TextMessageEncodingBindingElement classe ) per impostazione predefinita.

Elemento di associazione del codificatore Descrizione
TextMessageEncodingBindingElement Il codificatore di messaggi di testo è il codificatore predefinito per tutte le associazioni basate su HTTP e la scelta appropriata per tutte le associazioni personalizzate in cui l'interoperabilità rappresenta il problema più elevato. Questo codificatore legge e scrive messaggi di testo SOAP 1.1/SOAP 1.2 standard senza alcuna gestione speciale per i dati binari. Se la System.ServiceModel.Channels.MessageVersion proprietà di un messaggio è impostata su MessageVersion.None, il wrapper della busta SOAP viene omesso dall'output e viene serializzato solo il contenuto del corpo del messaggio.
MtomMessageEncodingBindingElement Il codificatore di messaggi MTOM è un codificatore di testo che implementa una gestione speciale per i dati binari e non viene usato di default in nessuna delle associazioni standard perché è strettamente un'utilità di ottimizzazione caso per caso. Se il messaggio contiene dati binari che superano una soglia in cui la codifica MTOM produce un vantaggio, i dati vengono esterni in una parte MIME che segue la busta del messaggio. Consultare l'abilitazione della funzione MTOM nella sezione successiva.
BinaryMessageEncodingBindingElement Il codificatore di messaggi binari è il codificatore predefinito per le associazioni Net* e la scelta appropriata ogni volta che entrambe le parti di comunicazione si basano su WCF. Il codificatore di messaggi binari usa il formato XML binario .NET, una rappresentazione binaria specifica di Microsoft per i set di informazioni XML (Infoset) che in genere produce un footprint inferiore rispetto alla rappresentazione XML 1.0 equivalente e codifica i dati binari come flusso di byte.

La codifica dei messaggi di testo è in genere la scelta migliore per qualsiasi percorso di comunicazione che richiede l'interoperabilità, mentre la codifica dei messaggi binari è la scelta migliore per qualsiasi altro percorso di comunicazione. La codifica binaria dei messaggi restituisce in genere dimensioni dei messaggi inferiori rispetto al testo per un singolo messaggio e dimensioni dei messaggi progressivamente ancora più piccole per tutta la durata di una sessione di comunicazione. A differenza della codifica del testo, la codifica binaria non deve usare una gestione speciale per i dati binari, ad esempio l'uso di Base64, ma rappresenta i byte come byte.

Se la soluzione non richiede l'interoperabilità, ma si vuole comunque usare il trasporto HTTP, è possibile comporre un'associazione BinaryMessageEncodingBindingElement personalizzata che usa la classe HttpTransportBindingElement per il trasporto. Se un numero di client nel servizio richiede l'interoperabilità, è consigliabile esporre endpoint paralleli con le opzioni di trasporto e codifica appropriate per i rispettivi client abilitati.

Abilitazione di MTOM

Quando è richiesta l'interoperabilità e devono essere inviati dati binari di grandi dimensioni, la codifica dei messaggi MTOM rappresenta una strategia di codifica alternativa, che si può abilitare sui binding standard BasicHttpBinding impostando la rispettiva proprietà WSHttpBinding su MessageEncoding o componendo il Mtom in un MtomMessageEncodingBindingElement. Il codice di esempio seguente, estratto dall'esempio di codifica MTOM , illustra come abilitare MTOM nella configurazione.

<system.serviceModel>  
     …  
    <bindings>  
      <wsHttpBinding>  
        <binding name="ExampleBinding" messageEncoding="Mtom"/>  
      </wsHttpBinding>  
    </bindings>  
     …  
</system.serviceModel>  

Come accennato in precedenza, la decisione di usare la codifica MTOM dipende dal volume di dati inviato. Inoltre, poiché MTOM è abilitato a livello di associazione, l'abilitazione di MTOM influisce su tutte le operazioni in un determinato endpoint.

Poiché il codificatore MTOM genera sempre un messaggio MIME/in più parti con codifica MTOM indipendentemente dal fatto che i dati binari vengano esternizzati, in genere è consigliabile abilitare MTOM solo per gli endpoint che scambiano messaggi con più di 1 KB di dati binari. Inoltre, i contratti di servizio progettati per l'uso con endpoint abilitati per MTOM devono, quando possibile, essere vincolati a specificare tali operazioni di trasferimento dei dati. La funzionalità di controllo correlata deve risiedere in un contratto separato. Questa regola "solo MTOM" si applica solo ai messaggi inviati tramite un endpoint abilitato per MTOM; il codificatore MTOM può decodificare e analizzare anche i messaggi non MTOM in ingresso.

L'uso del codificatore MTOM è conforme a tutte le altre funzionalità WCF. Si noti che potrebbe non essere possibile osservare questa regola in tutti i casi, ad esempio quando è necessario il supporto della sessione.

Modello di programmazione

Indipendentemente da quale dei tre codificatori predefiniti usati nell'applicazione, l'esperienza di programmazione è identica per quanto riguarda il trasferimento di dati binari. La differenza consiste nel modo in cui WCF gestisce i dati in base ai relativi tipi di dati.

[DataContract]  
class MyData  
{  
    [DataMember]  
    byte[] binaryBuffer;  
    [DataMember]  
    string someStringData;  
}

Quando si usa MTOM, il contratto dati precedente viene serializzato in base alle regole seguenti:

  • Se binaryBuffer non è null e ciascuno di essi contiene dati sufficienti per giustificare l'overhead dell'esternalizzazione MTOM (intestazioni MIME e così via) rispetto alla codifica Base64, i dati vengono esternalizzati e trasportati assieme al messaggio come parte binaria MIME. Se la soglia non viene superata, i dati vengono codificati come Base64.

  • La stringa (e tutti gli altri tipi non binari) sono sempre rappresentati come stringa all'interno del corpo del messaggio, indipendentemente dalle dimensioni.

L'effetto sulla codifica MTOM è lo stesso se si usa un contratto dati esplicito, come illustrato nell'esempio precedente, utilizzare un elenco di parametri in un'operazione, avere contratti dati annidati o trasferire un oggetto contratto dati all'interno di una raccolta. Le matrici di byte sono sempre candidate per l'ottimizzazione e sono ottimizzate se vengono soddisfatte le soglie di ottimizzazione.

Annotazioni

Non dovresti usare System.IO.Stream tipi derivati all'interno dei contratti di dati. I dati di flusso devono essere comunicati usando il modello di streaming, come illustrato nella sezione "Streaming data" seguente.

Flusso di dati

Quando si dispone di una grande quantità di dati da trasferire, la modalità di trasferimento del flusso in WCF è un'alternativa fattibile al comportamento predefinito del buffering e dell'elaborazione dei messaggi in memoria nella loro interezza.

Come accennato in precedenza, abilitare lo streaming solo per messaggi di grandi dimensioni (con testo o contenuto binario) se i dati non possono essere segmentati, se il messaggio deve essere recapitato in modo tempestivo o se i dati non sono ancora completamente disponibili all'avvio del trasferimento.

Restrizioni

Non è possibile usare un numero significativo di funzionalità WCF quando lo streaming è abilitato:

  • Non è possibile eseguire firme digitali per il corpo del messaggio perché richiedono il calcolo di un hash sull'intero contenuto del messaggio. Con lo streaming, il contenuto non è completamente disponibile quando le intestazioni del messaggio vengono costruite e inviate e pertanto non è possibile calcolare una firma digitale.

  • La crittografia dipende dalle firme digitali per verificare che i dati siano stati ricostruiti correttamente.

  • Le sessioni affidabili devono memorizzare nel buffer i messaggi inviati sul client per ritrasmetterli se un messaggio viene perso durante il trasferimento e devono trattenere i messaggi sul servizio prima di consegnarli all'implementazione del servizio per preservare l'ordine dei messaggi nel caso vengano ricevuti fuori sequenza.

A causa di questi vincoli funzionali, è possibile usare solo le opzioni di sicurezza a livello di trasporto per lo streaming e non è possibile attivare sessioni affidabili. Lo streaming è disponibile solo con le associazioni definite dal sistema seguenti:

Poiché i trasporti sottostanti di NetTcpBinding e NetNamedPipeBinding hanno un supporto intrinseco per la consegna affidabile e per sessioni basate su connessione, a differenza di HTTP, queste due associazioni sono solo minimamente influenzate da questi vincoli, in pratica.

Lo streaming non è disponibile con il trasporto di Accodamento Messaggi (MSMQ) e pertanto non può essere usato con NetMsmqBinding o MsmqIntegrationBinding classe. Il trasporto Message Queuing supporta solo trasferimenti di dati bufferizzati con una dimensione del messaggio limitata, mentre tutti gli altri trasporti non hanno alcun limite pratico per la maggior parte degli scenari.

Lo streaming non è disponibile neanche quando si utilizza il trasporto del canale peer, quindi non è disponibile con il NetPeerTcpBinding.

Streaming e sessioni

È possibile che si verifichi un comportamento imprevisto durante le chiamate di streaming con un'associazione basata su sessione. Tutte le chiamate di streaming vengono effettuate tramite un singolo canale (il canale del datagramma) che non supporta le sessioni anche se l'associazione utilizzata è configurata per l'uso delle sessioni. Se più client effettuano chiamate di streaming allo stesso oggetto servizio tramite un'associazione basata su sessione e la modalità di concorrenza dell'oggetto servizio è impostata su single e la modalità di contesto dell'istanza è impostata su PerSession, tutte le chiamate devono passare attraverso il canale del datagram e quindi viene elaborata una sola chiamata alla volta. Uno o più client potrebbero quindi andare in timeout. È possibile risolvere questo problema impostando la modalità del contesto dell'istanza dell'oggetto servizio su "PerCall" o la concorrenza su "Multiple".

Annotazioni

MaxConcurrentSessions non ha alcun effetto in questo caso perché è disponibile una sola "sessione".

Abilitazione dello streaming

È possibile abilitare lo streaming nei modi seguenti:

  • Inviare e accettare richieste in modalità di streaming e accettare e restituire risposte in modalità memorizzata nel buffer (StreamedRequest).

  • Invia e accetta le richieste in modalità bufferizzata e accetta e restituisci risposte in modalità streaming (StreamedResponse).

  • Invia e ricevi richieste e risposte in modalità streaming in entrambe le direzioni. (Streamed)

È possibile disabilitare lo streaming impostando la modalità di trasferimento su Buffered, ovvero l'impostazione predefinita in tutte le associazioni. Il codice seguente illustra come impostare la modalità di trasferimento nella configurazione.

<system.serviceModel>  
     …  
    <bindings>  
      <basicHttpBinding>  
        <binding name="ExampleBinding" transferMode="Streamed"/>  
      </basicHttpBinding>  
    </bindings>  
     …  
</system.serviceModel>  

Quando si crea un'istanza dell'associazione nel codice, è necessario impostare la rispettiva TransferMode proprietà dell'associazione (o l'elemento di associazione di trasporto se si compone un'associazione personalizzata) su uno dei valori indicati in precedenza.

È possibile attivare lo streaming per le richieste e le risposte o per entrambe le direzioni indipendentemente da entrambi i lati delle parti di comunicazione senza influire sulle funzionalità. Tuttavia, è sempre consigliabile presupporre che le dimensioni dei dati trasferite siano così significative che l'abilitazione del flusso sia giustificata tra gli endpoint di un collegamento di comunicazione. Per la comunicazione multipiattaforma in cui uno degli endpoint non è implementato con WCF, la possibilità di usare lo streaming dipende dalle funzionalità di streaming della piattaforma. Un'altra rara eccezione potrebbe essere uno scenario basato sul consumo di memoria in cui un client o un servizio deve ridurre al minimo il set di lavoro e può consentire solo piccole dimensioni del buffer.

Abilitazione del flusso asincrono

Per abilitare il flusso asincrono, aggiungere il comportamento dell'endpoint DispatcherSynchronizationBehavior all'host del servizio e impostare la relativa proprietà AsynchronousSendEnabled su true. È stata anche aggiunta la funzionalità di true streaming asincrono sul lato di invio. Ciò migliora la scalabilità del servizio negli scenari in cui esegue lo streaming di messaggi a più client, alcuni dei quali sono lenti nella lettura probabilmente a causa della congestione della rete o non stanno leggendo affatto. In questi scenari, attualmente, non blocchiamo singoli thread nel servizio per ogni cliente. In questo modo si assicura che il servizio possa elaborare molti più client, migliorando pertanto la scalabilità del servizio.

Modello di programmazione per i trasferimenti in streaming

Il modello di programmazione per lo streaming è semplice. Per la ricezione di dati trasmessi, specificare un contratto di operazione con un singolo Stream parametro di input tipizzato. Per la restituzione di dati trasmessi, restituire un Stream riferimento.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]  
public interface IStreamedService  
{  
    [OperationContract]  
    Stream Echo(Stream data);  
    [OperationContract]  
    Stream RequestInfo(string query);  
    [OperationContract(OneWay=true)]  
    void ProvideInfo(Stream data);  
}  

L'operazione Echo nell'esempio precedente riceve e restituisce un flusso e deve quindi essere usata in un'associazione con Streamed. Per l'operazione RequestInfo, StreamedResponse è più adatto, perché restituisce solo un oggetto Stream. L'operazione unidirezionale è più adatta per StreamedRequest.

Si noti che l'aggiunta di un secondo parametro alle operazioni Echo o ProvideInfo seguendo determina che il modello di servizio ritorni a una strategia con memoria buffer, utilizzando la rappresentazione di serializzazione a run-time del flusso. Solo le operazioni con un singolo parametro del flusso di input sono compatibili con lo streaming di richieste end-to-end.

Questa regola si applica in modo analogo ai contratti di messaggio. Come illustrato nel contratto di messaggio seguente, è possibile avere un solo membro del corpo nel contratto di messaggio che è un flusso. Se si desidera comunicare informazioni aggiuntive con il flusso, queste informazioni devono essere riportate nelle intestazioni dei messaggi. Il corpo del messaggio è riservato esclusivamente al contenuto del flusso.

[MessageContract]  
public class UploadStreamMessage  
{  
   [MessageHeader]  
   public string appRef;  
   [MessageBodyMember]  
   public Stream data;  
}

I trasferimenti trasmessi terminano e il messaggio viene chiuso quando il flusso raggiunge la fine del file (EOF). Quando si invia un messaggio (restituendo un valore o richiamando un'operazione), è possibile passare un oggetto FileStream e l'infrastruttura WCF successivamente estrae tutti i dati da quel flusso fino a quando il flusso è stato completamente letto e si raggiunge EOF. Per trasferire i dati in streaming per una sorgente per cui non esiste una classe derivata predefinita Stream, costruisci una tale classe, sovrapponila alla tua sorgente di flusso e utilizzala come argomento o valore restituito.

Quando si riceve un messaggio, WCF costruisce un flusso sul contenuto del corpo del messaggio con codifica Base64 (o la rispettiva parte MIME se si usa MTOM) e il flusso raggiunge EOF quando il contenuto è stato letto.

Lo streaming a livello di trasporto funziona anche con qualsiasi altro tipo di contratto messaggio (elenchi di parametri, argomenti del contratto dati e contratto di messaggio esplicito), ma poiché la serializzazione e la deserializzazione di tali messaggi tipizzato richiede il buffering da parte del serializzatore, l'uso di tali varianti di contratto non è consigliabile.

Considerazioni speciali sulla sicurezza per dati di grandi dimensioni

Tutti i binding consentono di limitare le dimensioni dei messaggi in ingresso per impedire attacchi Denial-of-Service. L'oggetto BasicHttpBinding, ad esempio, espone una proprietà System.ServiceModel.BasicHttpBinding.MaxReceivedMessageSize che delimita le dimensioni del messaggio in arrivo e quindi delimita anche la quantità massima di memoria a cui si accede durante l'elaborazione del messaggio. Questa unità viene impostata in byte con un valore predefinito di 65.536 byte.

Una minaccia di sicurezza specifica per lo scenario di streaming di dati di grandi dimensioni provoca un attacco DoS causando il buffering dei dati quando il ricevitore si aspetta che venga trasmesso in streaming. Ad esempio, WCF memorizza sempre nel buffer le intestazioni SOAP di un messaggio e quindi un utente malintenzionato può costruire un messaggio dannoso di grandi dimensioni costituito interamente da intestazioni per forzare il buffer dei dati. Quando lo streaming è abilitato, può MaxReceivedMessageSize essere impostato su un valore estremamente grande, perché il ricevitore non prevede mai che l'intero messaggio venga memorizzato nel buffer in memoria contemporaneamente. Se WCF è costretto a memorizzare nel buffer il messaggio, si verifica un overflow di memoria.

Pertanto, la limitazione delle dimensioni massime dei messaggi in arrivo non è sufficiente in questo caso. La MaxBufferSize proprietà è necessaria per vincolare la memoria memorizzata nel buffer WCF. È importante impostare questo valore su un valore sicuro (o mantenerlo al valore predefinito) durante lo streaming. Si supponga, ad esempio, che il servizio debba ricevere file di dimensioni fino a 4 GB e archiviarli nel disco locale. Si supponga anche che la memoria sia vincolata in modo da poter memorizzare nel buffer solo 64 KB di dati alla volta. Impostare quindi MaxReceivedMessageSize su 4 GB e MaxBufferSize su 64 KB. Inoltre, nell'implementazione del servizio, è necessario assicurarsi di leggere solo dal flusso in ingresso in blocchi da 64 KB e di non leggere il blocco successivo prima che quello precedente sia stato scritto su disco e rimosso dalla memoria.

È anche importante comprendere che questa quota limita solo il buffering eseguito da WCF e non può proteggere l'utente da eventuali buffering eseguite nel proprio servizio o implementazione client. Per altre informazioni sulle considerazioni aggiuntive sulla sicurezza, vedere Considerazioni sulla sicurezza per i dati.

Annotazioni

La scelta di utilizzare trasferimenti memorizzati nel buffer o in flussi è una decisione specifica dell'endpoint. Per i trasporti HTTP, la modalità di trasferimento non viene propagata tra una connessione o i server proxy e altri intermediari. L'impostazione della modalità di trasferimento non si riflette nella descrizione dell'interfaccia del servizio. Dopo aver generato un client WCF in un servizio, è necessario modificare il file di configurazione per i servizi da usare con i trasferimenti trasmessi per impostare la modalità. Per i trasporti TCP e named pipe, la modalità di trasferimento viene propagata come asserzione di criteri.

Vedere anche