COM + зависает при вызове COM-объекта под нагрузкой - PullRequest
3 голосов
/ 16 июня 2011

У нас есть код COM +, написанный на всех любимых языках (?) - VB6. Этот компонент COM + вызывает стандартный COM-компонент, написанный третьей стороной, которая выполняет вызовы в базу данных SQL Server. Мы ничего не делаем в COM + - ничего более (это только пример; мы не вызываем наши функции doStuff :-)):

Function doStuff
   Dim o As Library.Object
   Set o = New Library.Object
   str = o.DoSomething()
   Set o = Nothing
   doStuff = str
End Function

В качестве ужасно быстрого стресс-теста мы обернули вызов в просто-напросто простой VBScript, который просто создает объект, вызывает метод в цикле, ничего не устанавливает и повторяет это несколько раз. Затем мы запускаем четыре из них одновременно в командной строке.

Мы видим, как четыре окна COM + перестали работать, как будто они каким-то образом заблокировали друг друга. Исходя из поведения выходных данных, похоже, что разные окна совместно используют экземпляры объектов где-то по пути: например, скорость, с которой вывод появляется между окнами, синхронизируется между окнами ... так что два могут быстро расти на скорости в то время как два других выплевывают линию в секунду (и когда они выплевывают линию, они делают это одновременно).

Затем, в конечном счете, все четыре окна, кажется, перестают работать - в службах компонентов мы видим, что время вызова начинает расти (поэтому с нескольких миллисекунд на вызов оно увеличивается до 30, 40 секунд). Иногда dllhost.exe завершается ошибкой, и мы получаем диалоговое окно ошибки COM Surrogate (в этот момент окно восстанавливается, когда появляется новый dllhost).

В базе данных есть активность no , поэтому мы исключили, что на уровне базы данных что-то блокируется. Кажется, мы добились лучших результатов, установив для компонента COM значение «Транзакции: отключено», но зависания не исчезают. Вместо new мы попытаемся создать COM-объект с CreateObject, чтобы увидеть, что он делает (если что-нибудь). Объектам присваивается значение «Ничто» после завершения как в COM +, так и на уровне VBScript.

Стоит отметить, что если сторонняя библиотека вызывается напрямую из VBScript (в обход COM +), проблем не возникает. Таким образом, создается впечатление, что это как-то связано с тем, как COM + взаимодействует с COM-объектами, но кроме того, чтобы поиграть с другими настройками в свойствах объектов в службах компонентов, на самом деле не уверен, что еще происходит.

Есть какие-нибудь предложения относительно того, что происходит под капотом, чтобы вызвать это? Или настройки подправить?

Дополнительная информация
В ответе на вопросы в ответах:

  • Глобальные переменные не используются (согласно http://support.microsoft.com/kb/815053)
  • Автоматическое выполнение и сохранение в памяти установлены правильно (согласно http://support.microsoft.com/kb/264957)
  • Поскольку объект является объектом VB COM +, на нем работает STA, поэтому пул объектов не может быть настроен

Дальнейшая работа ... Похоже, что это проблема синхронизации где-то глубоко в COM + или COM. В нашем тестовом скрипте, если мы добавим случайную задержку в 10-50 мс на каждую итерацию, проблема исчезнет. Если у нас фиксированная задержка, мы блокируем. Похоже, некоторые поиски в Google показывают, что это может быть проблемой для сильно загруженного COM + с STA, что описано здесь в блоге MS . Было бы неплохо вернуться к блоку Server 2000 или блоку Server 2003 SP1: это может быть следующее, что нужно увидеть ...

Ответы [ 3 ]

2 голосов
/ 23 июня 2011

Похоже, что вы, возможно, столкнулись с проблемой COM + и STA из звонков с квартиры.

Раньше у Microsoft была замечательная статья, опубликованная Майклом МакКауном под названием «Сохранение производительности приложений при портировании с MTS на COM +», в которой обсуждался этот вопрос, но, похоже, она была удалена (здесь есть архивная версия здесь ).

По сути, пул потоков COM + STA связывает до 5 операций с каждым потоком STA. Когда вы выполняете вызов вне помещения (сторонний компонент или SQL Server), COM + позволяет обслуживать другие запросы в качестве другого действия в потоке STA. Это может произойти до 5 действий (на поток). Кроме того, после того, как контроль был передан другому действию, исходное действие не может восстановить контроль, пока второе действие не будет завершено. При большой нагрузке и / или если вызовы являются «длительными», то время для завершения первого действия является суммой времени для завершения всех других действий (в потоке). Это может убить вашу производительность.

Если вы можете переключить настройку для всего вашего сервера COM +, вы можете настроить COM + для использования старого подхода MTS 100 STA. См. Ключ реестра для настройки потока COM + и активности для получения подробной информации. Вы можете увидеть, если это помогает вашей производительности. Другой подход - избегать компонентов STA.

0 голосов
/ 18 июня 2011

2 вещи приходят на ум:

  1. Вы пытались сделать переменную o локальной вместо уровня модуля?

    Функция doStuff Dim o as Library.Object
    Set o = Новая библиотека. Объект str = o.DoSomething () Set o = Nothing doStuff = str Конечная функция

  2. Вы считаете, что компонент Library.Object и метод .DoSomething не содержат глобальных переменных (или операторов MessageBox)?

  3. Можете ли вы бросить операторы журналирования после каждой строки, чтобы увидеть, где код дросселирует?

  4. Нажмите ProcMon , чтобы увидеть, когда он перестанет работать с реестром. Последний звонок не удался? Если да, то куда?

0 голосов
/ 16 июня 2011

Возможно Концепции объединения объектов COM + и связанные с ними статьи, такие как Настройка компонента для пула .

Объединяемые объекты должны соответствовать определенным требованиям кразрешить использование одного экземпляра объекта несколькими клиентами.Например, они не могут содержать состояние клиента или иметь какое-либо сходство потоков.

...