Имя: Пароль:
1C
 
висящие com-соединения
0 IT-AleX
 
24.08.10
14:02
прошу помощи...
есть проект которые работает через веб-расширение (asp.net C#)... все формы самописные... и обращение к 1С как правило веду через вызов функции из глобальника или запросом к справочнику и через V8DataReader

везде где видел уже проставил conn.close все конструкции V8DataReader взял в using() {} но ничего до конца не помогло...

раньше до "оптимизации" у меня при отработке страницы создавалось 3 висящих соединения... теперь остаётся одно... и висит 1258 секунд... притом я пробывал несколько раз отработать страницу... и в каждом случае соединение отваливалось через 1258 секунд...

1) что это за волшебная цифра? её можно где-то увидеть/изменить?

2) какие объекты C# могут "захватывать" com-соединение в "заложники"?
т.е. conn не отпускается даже не смотря на conn.Close();
V8DbConnection.ClearPool(); - тоже не помогает... соединение продолжает висеть...

у меня на сколько я вижу может с 1С работать несколько типов объектов

V8DataReader...
притом ещё есть объекты (ObjectRef) хххх.GetValue
при обращении к V8.Call как правило возвращаю строку или строки...

3) как мне "освобождать" эти объекты?... все ли их нужно особождать?...

какова всё-таки правильная конструкция соединение-работа-завершение чтобы не создавалось это висящее подключение...

Заранее благодарю за ответы...
Очень нужна помощь!!!
Спасибо!
1 Drock
 
24.08.10
15:21
web.config
<configuration>
   <appSettings>
<add key="PoolCapacity" value="10"/>
<add key="PoolTimeout" value="1200"/>
....
Global.asax.cs


       protected void Application_Start(Object sender, EventArgs e)
       {

           RegisterRoutes(RouteTable.Routes);

           V8Metadata.SetDatabase("",
               System.Configuration.ConfigurationSettings.AppSettings[V8Consts.Database]);
           
           string poolCapacityStr =
               System.Configuration.ConfigurationSettings.AppSettings[V8Consts.PoolCapacity];
           if (poolCapacityStr != null)
           {
               try
               {
                   int poolCapacity = int.Parse(poolCapacityStr, CultureInfo.InvariantCulture);
                   V8DbConnection.PoolCapacity = poolCapacity;
               }
               catch (FormatException)
               {
               }
           }
           
           string poolTimeoutStr =
               System.Configuration.ConfigurationSettings.AppSettings[V8Consts.PoolTimeout];
           if (poolTimeoutStr != null)
           {
               try
               {
                   int poolTimeout = int.Parse(poolTimeoutStr, CultureInfo.InvariantCulture);
                   V8DbConnection.PoolTimeout = poolTimeout;
               }
               catch (FormatException)
               {
               }
           }

           string maxConnectionsStr =
               System.Configuration.ConfigurationSettings.AppSettings[V8Consts.MaxConnections];
           if (maxConnectionsStr != null)
           {
               try
               {
                   int maxConnections = int.Parse(maxConnectionsStr, CultureInfo.InvariantCulture);
                   V8DbConnection.MaxConnections = maxConnections;
               }
               catch (FormatException)
               {
               }
           }
           string versionStr =
               System.Configuration.ConfigurationSettings.AppSettings[V8Consts.ComConnectorVersion];
           if (versionStr != null)
           {
               try
               {
                   ComConnectorVersion version = (ComConnectorVersion)Enum.Parse(typeof(ComConnectorVersion), versionStr, true);
                   V8DbConnection.Version = version;
               }
               catch (ArgumentException)
               {
               }
           }
           

      //     V8Config.SetConfig("", V8Config.MapFileName);
       }

И самое главное после каждого, каждого обращения к V8Db, надо закрывать соединение.

           var connector = new V8Connector();
           var conn = connector.GetConnection();
           conn.Open();
....

conn.Close();
2 Drock
 
24.08.10
15:23
В итоге у меня пул из 3х коннектов обрабатывает примерно 700-800 посетителей в день вот тут http://sunrise-ufa.ru
3 IT-AleX
 
24.08.10
16:23
а остаются ли у вас висеть com-соединения? или висящих нет?

фитча в том что какие-то операции очень быстро открывают соединение, выполняют действия, закрывают соединения...
а какие-то висят и пользователь типа в 1С ничего не делает...
как вы у себя работаете с объектами 1С между open и close?
нету "не освобождённых" объектов при трассировке?
4 IT-AleX
 
25.08.10
10:13
var connector = new V8Connector();
           var conn = connector.GetConnection();
           conn.Open();
----------------
эм... прошу прощения за ламерский вопрос... а коннекция как тогда прописана?... что откуда возвращается GetConnection()?
5 Drock
 
25.08.10
10:27
(3) - Да висит пул, через который работают пользователи без задержек, ну или с минимальными задержками
V8DbConnection conn = connector.GetConnection();
           conn.Open();
using (
               var res =
                   V8.Call(conn, conn.Connection, "ПараметрыСессии", catId, orderDb.Customer.PriceId) as ComObject)
           {
               using (IDataReader dr = new V8DataReader(res, conn))
               {
                   while (dr.Read())
                   {
                       currentDate = dr["ТекущаяДата"];
                       productsQty = dr["КоличествоТоваровНаСкладе"].ToString();
                       retailPrice = dr["ЦенаРозница"];
                     
                                              store = dr["Склад"];
                                           parentref = dr["Родитель"];
                       dynamic = Convert.ToBoolean(dr["Динамический"]);
                       parentName = dr["НаименованиеРодителя"].ToString();
                   }
               }
           }

...
conn.Close();


(4) Отдельный класс

public class V8Connector
   {
       public V8DbConnection GetConnection()
       {
           var conn = new V8DbConnection
           {
               User = ConfigurationSettings.AppSettings.Get("UserName"),
               Password = ConfigurationSettings.AppSettings.Get("UserPassword"),
               Database = ConfigurationSettings.AppSettings.Get("Database")
           };
           return conn;
       }
   }
6 IT-AleX
 
25.08.10
11:03
спасибо...
я не знаю... м.б. уже у меня всё в более или менее штатном режиме работает...
тогда наверно другой вопрос... у вас в консоли сервера не висят вредоносный подключения?... т.е. подключения которые в 1С вроде бы ничего не делают если смотреть по номеру подключения по логу в 1С... но в консоли они захватывают хренову тучу баз SQL и висят чёрт знает сколько... при этом приводят к увеличению размера rphost.exe в процессах и в итоге приводят к ОЧЕНЬ сильному торможению сервера... нагрузка подскакивает до 95%... и в итоге пользователи веб-приложения могут ждать ответа от сервера минут по 5-10...  и получается что звонит нам служба поддержки клиентов в более или менее пиковую нагрузку (в субботу, я не представляю что будет под новый год) и говорят что в магазинах ничего не работает и они не могут подключится к нашим веб-приложениям... в итоге надо искать и-нет зализать на удалёнку и банально пребивать процесс в таскменеджере... блин... это ж не дело... как с этим бороться? может знаешь?

иоли ещё кто-нибудь знает?
Заранее спасибо...
7 Drock
 
25.08.10
12:30
Я думаю надо смотреть в сторону кода, Вашего веб приложения, полностью рассматривать логику и жизненный путь от точки входа до точки выхода из приложения.
Не совсем понятно - "Хренову тучу баз" , может быть таблиц ?
8 Drock
 
25.08.10
12:32
Настройте пул приложения согласно инструкции и приведенному выше коду.ю
9 IT-AleX
 
25.08.10
12:44
в консоли кластера при просмотре соединений есть несколько процессов в столбце под наименованием "захвачено СУБД" цифры 1 500,000 и столбец "переднно данных" на 65 мегабайт... и эти соединения отваливаются только через 75 минут по настройке rphost-ов... в течении 2500 секунд к рпхосту можно подсоедениться... а в течении 2000 все соединения доживают в нём но подключить новое соединение туда нельзя... и несколько раз уже было что "вредоносное" соединение приводило к очень медленной работе сервера... 5-10 минут отклик веб-приложения...
10 Drock
 
25.08.10
12:55
Ну соответственно, необходимо смотреть код приложения и выяснять, в каком месте не происходит закрытие коннекта.
11 Drock
 
25.08.10
12:58
содержимое файла Global.asax && Global.asx.cs
12 Drock
 
25.08.10
12:58
IIS настроить на сброс сессий
13 IT-AleX
 
25.08.10
14:11
закрытие коннекта есть везде...
но я предпологаю что какие-то переменные... сессии ли вьюстайта... ещё какие после записи в себе содержимого полученного от обработки датаридера данных из 1С... они и держат собой эти соединения... может быть такое?...

к примеру есть строчка типа string[] Arr = (string[])V8.Call(.....);
нужно ли каким-то образом "освобождать" переменную Arr? каким образом?

к примеру есть строчка типа ObjectRef ObRef = DataReaderParam.getValue(...);
нужно ли каким-то образом "освобождать" переменную ObRef? каким образом?
14 Drock
 
25.08.10
16:35
GC.Collect();
15 Drock
 
25.08.10
16:39
По идее, если вы, точно уверены , что у вас все закрывается, то надо копать в сторону Global.asax, во вторых кто делал "тюнинг" и в чем он заключался.

В третьих используйте GC.Collect();
http://msdn.microsoft.com/ru-ru/library/xe0c2357.aspx

Используйте этот метод, чтобы попытаться высвободить всю недоступную память.

Сборке мусора подвергаются все объекты, вне зависимости от времени их нахождения в памяти. Однако объекты, на которые имеются ссылки в управляемом коде, не освобождаются.Используйте этот метод, чтобы принудительно предпринять попытку высвободить максимальный объем доступной памяти.
16 IT-AleX
 
26.08.10
10:14
не помогло :(
17 Drock
 
26.08.10
12:48
Содержимое файлов Global.asax и Global.asax.cs можеш привести ?
18 Drock
 
26.08.10
12:48
Ну и приготовте ножницы, для тюнера :)
Независимо от того, куда вы едете — это в гору и против ветра!