Oracle Data Provider for .NET: demande de Connexion timed out
Nous avons un C# WCF service web hébergé sur Windows 2008 SP2/IIS 7 accès à une base de données Oracle. Généralement, l'accès aux données fonctionne bien, mais pendant les tests de charge, c'est souvent du temps et des journaux et d'exception en disant:
Error occurred when processing XXXXXXXX Web Service
Oracle.DataAccess.Client.OracleException Connection request timed out at Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck)
at Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, Object src)
at Oracle.DataAccess.Client.OracleConnection.Open()
at MyWorkspace.WorkForceDataAccess.CheckStaffIdInRSW()
at MyWorkspace.MyClass.MyFunction(MyDataType MyData)
Pour interroger la base de données, nous utilisons quelque chose comme ceci:
OracleConnection orConn = new OracleConnection();
orConn.ConnectionString = "user id=xxx; password=xxx; Connection Timeout=600; Max Pool Size=150; data source= (DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = MYHOST.MYDOMAIN.com)(PORT = 1771)) (CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = MYSERVICE.MYDOMAIN.com)))";
orConn.Open();
using (var cmd = new OracleCommand("MY_UTIL.check_StaffIdInRSW", orConn) { CommandType = CommandType.StoredProcedure })
{
cmd.Parameters.Add("P_Staff_Id", OracleDbType.Int32);
cmd.Parameters["P_Staff_Id"].Direction = ParameterDirection.Input;
cmd.Parameters["P_Staff_Id"].Value = Convert.ToInt32(MyDataObject.StaffId);
cmd.Parameters.Add("P_retvalue", OracleDbType.Int32);
cmd.Parameters["P_retvalue"].Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery(); //Execute the function
//obtain result
returnVal = int.Parse(cmd.Parameters["P_retvalue"].Value.ToString());
}
Je suis assez confiant sur le fait que la procédure stockée qui est invoquée, n'est pas en prenant tout le temps. Il est assez simple procédure qui vérifie si le P_Staff_Id existe dans la table et retourne le résultat.
En outre, cela se produit uniquement pendant les essais en charge. Au cours de l'exploitation normale, les choses sont bien, mais au cours de lourdes charges avec 1 message par seconde, cela se produit après l'exécution lisse pour un certain temps.
Comme une solution de contournement, j'ai ajouté "Délai d'attente de Connexion=600; Max Pool Size=150“ à la chaîne de connexion, mais cela ne corrige pas le problème.
Nous avons la même application s'exécutant sur un serveur de développement et il fonctionne très bien. Nous n'avons jamais rencontré ce problème là.
Des suggestions quant à ce qu'à essayer serait appréciée. Il semble que je suis à court d'options.
J'ai ajouté le Délai de Connexion et Max de la Taille du Pool pour la chaîne de connexion une fois ce problème est venu - mais il n'a pas aidé. Le service web a été fonctionne correctement dans l'environnement de DEV sans ces. Par la connexion de fuite, suggérez-vous de la fermeture et de l'élimination de la OracleConnection objet explicitement après est-il utilisé?
Annonce de fuite dans le joint - si l'objet de connexion a juste à court de vivre au sein d'une même fonction, puis en utilisant (var connexion = ...) {...} est certainement plus sûr. Mais je n'attends pas telle est la question. Vous obtiendrez différents exception lorsque la piscine est entièrement utilisé. Annonce de test de charge - j'espère que vous exécutez plusieurs instances de l'application ou de la fonction en parallèle. Également s'attendre à ce que vous utilisez des connexions dédiées, ne partage pas les serveurs d'Oracle configuration. Pouvez-vous vérifier comment les séances de regarder dans la base de données pendant le test pour voir combien de séances et combien de sessions actives en fait, il y sont.
OriginalL'auteur DjD | 2015-09-27
Vous devez vous connecter pour publier un commentaire.
Nous avons eu un problème similaire, et il a fallu du temps, de débogage et de résoudre ce problème. Notre code sur stressée avec de nombreux fichiers d'entrée, et le nombre de threads de traitement, chaque thread à l'aide de Entity framework et de l'ouverture d'Oracle db connection, et de faire un tas de requêtes db et inserts, utilisé pour déposer de temps en temps. Mais fonctionne la plupart du temps.
J'ai modifié out constructeur DbContext explicitement ouvrir le OracleConnection. J'ai ajouté un peu de code comme ceci
Il est améliorée, mais n'a toujours pas résoudre complètement. Je me suis cassé dans la prise de débogueur, et vu que le nombre de threads tentent d'ouvrir et de quelques fils sont le traitement de suite.
Sur Ouvrir dans Oracle pile, l'Oracle de son interne à des fins ne ThreadPool.QueueUserWorkItem et attend son achèvement. Je peux voir sur le dessus de la pile de son attente. Ici beaucoup de pool de connexions sont disponibles (la valeur par défaut est de 100), je suis à peine à l'aide de 10. Il n'est donc pas de ressource.
Mais le problème est dans notre code, nous avons également utilisé de pool de threads.QueueUserWorkItem avec aucune autre limitation. J'ai pensé que c'était cool de file d'attente tous les travaux que nous devons faire, combien jamais, nous avons besoin de cela, et de laisser .NET en prendre soin. Mais c'est subtil question. Tous nos travaux ont consommé la totalité de la file d'attente à compter. Lorsque OracleConnection veut obtenir un pool de connexion de la piscine, elle a aussi des files d'attente pour le pool de threads. Mais il ne va jamais se terminer. Nos emplois sont tous dans l'attente de OracleConnection.Ouvert, et sa file d'Attente Thread proc sera toujours dans la file d'attente. Donc, finalement, l'attente en sortie par timeout.
Il est dommage que même si il ya beaucoup de pool de connexion est disponible, nous avons consommé toutes les ThreadPool proc, et l'Oracle du pool de threads n'ont même pas une chance. Ici paramètre de pool de threads.SetMaxThreads aussi ne va pas aider. Le problème est toujours le même. Nous avons porc de tous les threads du pool de ressources, et Orcale ne va pas en trouver un et le sera encore dans la file d'attente.
La solution est de ne pas se fier seulement à ThreadPool, mais nous y ajoutons notre propre limitation. J'ai utilisé BlockingCollection et sempahores et d'ajouter que certaines limiter le nombre de connexions simultanées emplois dans le pool de threads, de 5. De cette façon OracleConnection trouverez toujours un pool de threads thread disponible, et l'habitude de l'échec.
OriginalL'auteur R. Sridharan
essayer d'ajouter de la connexion.close() à la fin.
Je ne vois pas libérer les connexions dans votre code et de les retourner à un pool de connexion de manière explicite.
Si la connexion est retourné, le pool de connexion uniquement lors de la GC est commencé.
OriginalL'auteur Sasa Ninkovic
Même que j'ai utilisé pour obtenir ce problème de plus en plus Fréquemment, même après l'utilisation de la Connexion.Close()
Après une longue Analyse, j'ai appris quelques chose comme mentionné ci-dessous
Corrigé :-
L'analyse prend du temps, mais la solution est de seulement 2 minutes
Par exemple :-
Sous PersistData(); Toutes les db des Opérations telles que l'ouverture, à proximité de l'e.tc. sera effectuée
Comme nous le sait "l'Aide" est la forme courte de
Espérons que cela aide, comme il m'a aidé à
OriginalL'auteur Mohammed Saifullah