2009-05-07 9 views
26

Ho un'app client/server WCF che comunica tramite HTTP utilizzando WSHttpBinding.WCF Richieste simultanee di accumulo sul server quando si utilizza WSHttpBinding

Impostazione server: self-hosting, utilizzando lo standard WCF ServiceHost. La mia classe servizio attuale viene attribuito come:

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

Client Setup: (. proxy.call_server_method blocchi, fino al momento in cui il server ha risposto in pieno) usando un proxy client generato visual-studio utilizzando chiamate di servizio sincrone

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

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

Problema:
Se devo configurare l'applicazione per utilizzare WSHttpBinding, allora questo metodo di chiamata a lunga fa sì che le richieste HTTP a 'back up'. Ho verificato questo comportamento sia dall'ispezione dei miei registri, sia dal debug delle richieste HTTP usando il violinista.

Esempio:

  • client avvia 20-seconda richiesta a lungo su un thread in background
  • client avvia richiesta B e C sul thread in primo piano
  • Richieste B e C ottenere inviato al server, che doesn 't loro trattamento fino a quando non è fatto con il 20-seconda richiesta lungo

Ma a volte:

  • Le richieste B e C non vengono inviate (non appaiono nemmeno nel violinista) finché non viene restituita la richiesta di 20 secondi (questo è raro).
    • Nota: l'impostazione <add address="*" maxconnection="100"/> nell'app.config del client ha impedito l'esecuzione di questo (sembra).
  • Richiesta B viene inviato e riceve subito una risposta, mentre la richiesta di C è trattenuto fino a quando il 20-seconda completa (questo è raro)

Ecco una cronologia dal violinista dimostrare il problema: (clicca per la versione più grande)

Come si può vedere, le richieste sono tutti sempre eseguito il backup sul server. Una volta che la richiesta di 20 secondi è stata completata, le risposte vengono tutte inondate, ma si noti che ci sono alcune richieste che non rappresentano in attesa ...

Quindi, Domande:

  • Che diamine sta succedendo qui? Perché funziona correttamente utilizzando NetTcpBinding e non funziona utilizzando WSHttpBinding?
  • Perché il comportamento incoerente?
  • Cosa posso fare per risolverlo?

Note:

  • Non è bloccaggio sul server. Ho impostato i punti di interruzione e utilizzato !syncblk e segnala costantemente che non vengono bloccati blocchi.
  • non è il mio threading (NetTcpBinding dovrebbe non funzionare in altro modo)
  • ho <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" /> set nel app.config del server
  • Il 20-seconda chiamata è solo in attesa su un timer, non è thrashing la CPU o del disco o rete
  • Preferirei una soluzione che non prevedesse la re-architettura dell'applicazione per l'utilizzo di chiamate asincrone ... è un grosso gruppo di codice legacy e non voglio davvero fare scherzi con cose che non faccio t capire.
+0

+1 Eccellente il layout della questione. –

+1

Hai mai risolto questo problema? Se sì, come lo hai risolto? – DivisionByZorro

+0

Aggiunto un auto-risposta che descrive la nostra "soluzione" finale –

risposta

2

[Auto-risposta per mostrare altri utenti ciò che il nostro eventuale soluzione era]

Alla fine, non sono mai riuscito a risolvere questo problema.
La nostra soluzione finale era di passare la nostra app da WSHttpBinding e su NetTcpBinding in produzione - avevamo comunque intenzione di farlo in ogni caso per motivi di prestazioni.

Questo è piuttosto spiacevole, in quanto lascia un segno nero su WSHttpBinding che può o non può essere garantito. Se qualcuno dovesse mai trovare una soluzione che non implicasse l'ammaraggio WSHttpBinding, mi piacerebbe saperlo

+1

Penso che non dovresti rispondere autonomamente come effettivamente non abbiamo una risposta. Hai provato a postare bug su connect.microsoft.com? – Shrike

+0

Ora che ho imparato un po 'di più su come funzionano le cose, penso che potrebbe essere stato correlato a sovraccaricare il ThreadPool. Se si accodano molte operazioni a lungo termine al threadpool, si ottiene un comportamento simile a questo esattamente –

+0

Ho esattamente lo stesso problema con WSHttpBinding e non penso che sia dovuto a un pool di thread sovraccarico. Ho usato NetTcpBinding e improvvisamente funziona perfettamente. Posso ottenere ciò che descrivi semplicemente rendendo la mia prima chiamata al servizio e dormendo mentre prova a visualizzare un'altra chiamata in parallelo da un altro server. Nient'altro può contattare il servizio indipendentemente da come è stato impostato il comportamento del servizio e la limitazione del servizio. – Mike737

10

C'è un po 'di acceleratore al di fuori di WCF (un nodo .Net o Windows) che per impostazione predefinita consente solo un massimo di due connessioni HTTP in uscita simultanee. Purtroppo non riesco a ricordare per la vita di me il nome della cosa (e cosa avresti messo in app.config o nella tua app per sovrascriverlo). Dato che non stai vedendo le richieste lasciare il client, e che è solo HTTP, penso che stai colpendo "quella cosa". Continuerò a cercare il suo nome.

Aggiornamento: trovato - provate questo sul client (ma cambiare il '2' a un numero più grande):

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

Purtroppo questo non lo risolve ... Ha cambiato il comportamento in qualche modo, ma ora tutte le richieste sembrano fare il backup sul server –

+0

Aggiornato la mia domanda con un grafico temporale da il violinista che dovrebbe sperare di aiutare –

0

dimentico - Potrebbe essere l'ordinazione? Penso che RM su http conservi l'ordine ma forse le sessioni Tcp non lo fanno (a meno che tu non lo richieda esplicitamente)? Esiste un attributo nel Contratto di servizio che descrive sessioni ordinate/non ordinate (non ricordo).

+0

C'è che ha un attributo ordinato ... L'ho impostato su

1

Se si passa a BasicHttpBinding, funziona?

È così, suona come this is your problem, rallentamento della sessione, qualcosa che mi ha morso nel culo.

1

Considerare l'utilizzo di ConcurrencyMode.Multiple su servizi di chiamata per consentire chiamate simultanee .

4

Abbiamo visto 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 WCF. Abbiamo dovuto disabilitare lo stato della sessione (a livello dell'applicazione) per ottenere i metodi WCF simultanei.

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

Si prega di notare che il nostro servizio utilizza webHttpBinding, non WSHttpBinding. Quindi, non sono sicuro che questo risolva anche il problema di Orione.

2

penso che si colpisce il limite di protocollo e di lavorare intorno ad esso è necessario modificare le impostazioni standard sulla macchina client:

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

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

immagino WSHttpBinding utilizza le impostazioni WININET al momento del rilascio le richieste.

+0

Sembra probabile, ma ho perso da tempo il codice originale. Grazie comunque! –

Problemi correlati