Domanda

Ho un'app client / server WCF che comunica su HTTP utilizzando WSHttpBinding.

Impostazione server : self-hosting, utilizzando il WCF standard ServiceHost. La mia classe di servizio effettiva è attribuita come:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, 
 InstanceContextMode = InstanceContextMode.PerSession, 
 UseSynchronizationContext = false)]

Impostazione client : utilizzando un proxy client generato da Visual Studio utilizzando le chiamate di servizio sincrone (proxy.call_server_method blocchi fino a quando il server non ha risposto completamente.)

Scenario : Ho una particolare chiamata di metodo che richiede 20 secondi per essere eseguita sul server. Il client chiama questo metodo in un thread separato, quindi non viene trattenuto e ConcurrencyMode.Multiple significa che WCF dovrebbe eseguirlo anche in un thread separato sul server.

Questa teoria è supportata dal fatto che quando configuro la mia app per usare NetTcpBinding, tutto funziona bene.

problema :
Se configuro l'app per utilizzare WSHttpBinding, questa lunga chiamata di metodo fa sì che le richieste http vengano "salvate". Ho verificato questo comportamento sia ispezionando i miei registri, sia eseguendo il debug delle richieste HTTP utilizzando il violinista.

Esempio:

  • Il client avvia una richiesta di 20 secondi su un thread in background
  • Il client avvia la richiesta B e C sul thread in primo piano
  • Le richieste B e C vengono inviate al server, che non le elabora fino a quando non viene eseguita con la richiesta di 20 secondi

Ma a volte:

  • Le richieste B e C non vengono inviate (non compaiono nemmeno nel violinista) fino a quando non viene restituita la richiesta di 20 secondi (questo è raro).
    • Nota: l'impostazione <add address="*" maxconnection="100"/> in app.config del client ha fatto sì che questo (sembra) smetta di accadere.
  • La richiesta B viene inviata e riceve immediatamente una risposta, mentre la richiesta C viene trattenuta fino al completamento di quella di 20 secondi (questo è raro)

Ecco una sequenza temporale di violinista che dimostra il problema: (fai clic per una versione più grande)

Come puoi vedere, viene eseguito il backup di tutte le richieste sul server. Una volta completata la richiesta di 20 secondi, tutte le risposte arrivano inondando, ma nota che ci sono alcune richieste che non sono trattenute ...

Quindi, Domande :

  • Che diamine sta succedendo qui? Perché funziona bene usando !syncblk e non funziona usando <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" />?
  • Perché il comportamento incoerente?
  • Cosa posso fare per risolverlo?

Note:

  • Non si sta bloccando sul server. Ho impostato i punti di interruzione e utilizzato <=> e segnala costantemente che non vengono mantenuti blocchi.
  • Non è il mio threading (NetTcpBinding non dovrebbe funzionare diversamente)
  • Ho <=> impostato nell'app.config del server
  • La chiamata di 20 secondi è solo in attesa di un timer, non sta schiacciando la CPU o il disco o la rete
  • Preferirei una soluzione che non comportasse la riprogettazione dell'architettura per l'uso di chiamate asincrone ... è un grosso mucchio di codice legacy e non voglio davvero fare confusione con cose che non capisco .
È stato utile?

Soluzione 3

[Risposta automatica per mostrare agli altri utenti quale fosse la nostra eventuale soluzione]

Alla fine, non sono mai riuscito a risolverlo.
La nostra soluzione finale era quella di spostare la nostra app da WSHttpBinding a NetTcpBinding in produzione - avevamo pianificato di farlo alla fine comunque per motivi di prestazioni.

Questo è piuttosto sfortunato, poiché lascia un segno nero su <=> che può o non può essere garantito. Se qualcuno dovesse mai trovare una soluzione che non comporta l'abbandono <=>, mi piacerebbe saperlo

Altri suggerimenti

Esiste una limitazione al di fuori di WCF (una cosa .Net o Windows) che per impostazione predefinita consente solo un massimo di due connessioni HTTP in uscita simultanee. Sfortunatamente non ricordo per me il nome della cosa (e cosa avresti messo in app.config o nella tua app per sovrascriverlo). Dato che non vedi che le richieste escono dal client e che è solo HTTP, penso che stai colpendo & Quot; quella cosa & Quot ;. Continuerò a cercare il suo nome.

Aggiornamento: trovato - prova questo sul client (ma cambia '2' con un numero maggiore):

<configuration>
  <system.net>
    <connectionManagement>
      <add address = "*" maxconnection = "2" />
    </connectionManagement>
  </system.net>
</configuration>

Abbiamo riscontrato esattamente gli stessi sintomi con un servizio JSON ospitato in IIS / ASP.NET.

La causa principale è stata la sincronizzazione di ASP.NET delle richieste, non di WCF. Abbiamo dovuto disabilitare lo stato della sessione (a livello di applicazione) per ottenere metodi WCF simultanei.

web.config: <system.web> <sessionState mode="Off" /> </system.web>

Nota che il nostro servizio utilizza webHttpBinding, non wsHttpBinding. Quindi, non sono sicuro che questo risolva anche il problema di Orione.

Penso che tu abbia raggiunto il limite del protocollo e per aggirare il problema devi modificare le impostazioni standard sul computer client:

http://support.microsoft.com/kb/183110

http://support.microsoft.com/kb/282402

Suppongo che WSHttpBinding utilizzi le impostazioni di WinINET durante l'emissione delle richieste.

Se passi a BasicHttpBinding, funziona?

È così, sembra questo è il tuo problema , limitazione della sessione, qualcosa che mi ha morso nel culo.

Prendi in considerazione l'utilizzo di ConcurrencyMode.Multiple sui servizi per chiamata per consentire la concorrenza chiamate.

Dimentico: potrebbe essere un ordine? Penso che forse RM su http preservi l'ordine ma forse le sessioni Tcp no (a meno che non lo richiediate esplicitamente)? Nel contratto di servizio è presente un attributo che descrive le sessioni ordinate / non ordinate (che dimentico).

Non sono sicuro, ma a volte il problema con le chiamate simultanee dall'applicazione Silverlight è legato alla gestione della connessione del browser. Per me la soluzione è stata quella di inserire questo nel nostro metodo App.xaml.cs, Application_Startup come descritto qui: http://weblogs.asp.net/olakarlsson/simultaneously-calling-multiple-methods-on-a-wcf-service-from-silverlight

WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top