Вопрос по c#, webdriver – Отслеживание мертвых экземпляров WebDriver во время параллельной задачи

2

Я вижу странный случай мертвого экземпляра, который запускает параллельные веб-стресс-тесты с вложенными циклами с использованием Selenium WebDriver. Простой пример, скажем, просмотр 300 уникальных страниц по 100 показов в каждой.

Я "успешно" получение 4 - 8 экземпляров WebDriver с использованиемThreadLocal<FirefoxWebDriver> изолировать их для каждого потока задач и MaxDegreeOfParallelism для экземпляра ParallelOptions для ограничения потоков. Я делю и распараллеливаю только внешний цикл (набор страниц) и проверяю.IsValueCreated наThreadLocal<> контейнер внутри начала каждого раздела "длительное задание" метод. Чтобы облегчить очистку позже, я добавляю каждый новый экземпляр в ConcurrentDictionary с ключом идентификатора потока.

Независимо от того, какую стратегию распараллеливания или разбиения я использую, экземпляры WebDriver иногда выполняют одно из следующих действий:

Launch but never show a URL or run an impression Launch, run any number of impressions fine, then just sit idle at some point

Когда что-то из этого происходит, параллельный циклeventually кажется, замечает, что поток ничего не делает, и порождает новый раздел. Еслиn допустимое количество потоков, это приводит кn продуктивные нити только около 50-60% времени.

Очистка все еще отлично работает в конце; может быть 2 или более открытых браузеров, но продуктивные и непродуктивные одинаково очищаются.

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

Просто любопытно, ты выступаешь против Selenium Grid 2? Anders
Похоже, некоторые ваши темы заблокированы. Вы пробовали отладку, чтобы увидеть, где они заблокированы? svick
Нет, я использую обычный текстовый файл. классы webDriver. О том, чтобы взять NHtmlUnit для тест-драйва тоже. Paul Smith
Кажется, что происходит несколько медленный процесс асинхронной инициализации с сервером управления Selenium при создании экземпляраIWebDriver, Проблема в том, что работа продолжается под капотомafter призыв кnew FirefoxDriver() прекратил блокировать Если вы попытаетесь создать другие экземпляры слишком быстро, большинство из них не смогут подключиться. Так как нетOnReady событие ниIsReady Я обошел его, спя нить в течение нескольких секунд после создания каждого экземпляра. Это дает мне 100% надежные и работающие экземпляры WebDriver. Paul Smith

Ваш Ответ

2   ответа
1

У меня была похожая проблема. Оказывается, что в WebDriver нет лучшего способа поиска открытых портов. Как описаноВот он получает системную блокировку портов, находит открытый порт и затем запускает экземпляр. Это может истощить другие случаи, когда вы пытаетесь запустить порты.

Я обошел это, указав случайный номер порта непосредственно в делегате дляThreadLocal<IWebDriver> как это:

        var ports = new List<int>();
        var rand = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);

        var driver = new ThreadLocal<IWebDriver>(() =>
        {
            var profile = new FirefoxProfile();
            var port = rand.Next(50) + 7050;
            while(ports.Contains(port) && ports.Count != 50) port = rand.Next(50) + 7050;
            profile.Port = port;
            ports.Add(port);
            return new FirefoxDriver(profile);
        });

Это работает довольно последовательно для меня, хотя есть проблема, если вы в конечном итоге используете все 50 в списке, который не решен.

1

Since there is no OnReady event nor an IsReady property, I worked around it by sleeping the thread for several seconds after creating each instance. Doing that seems to give me 100% durable, functioning WebDriver instances.

Благодаря вашемупредложениеЯ реализовалIsReady функциональность в моем проекте с открытым исходным кодомWebinator, Используйте это, если хотите, или используйте код, описанный ниже.

Я попытался создать 25 экземпляров, и все они были функциональными, поэтому я достаточно уверен в алгоритме на данный момент (я использую HtmlAgilityPack, чтобы увидеть, существуют ли элементы, но я пропущу его для простоты здесь):

public void WaitForReady(IWebDriver driver)
{
    var js = @"{ var temp=document.createElement('div'); temp.id='browserReady';" +
             @"b=document.getElementsByTagName('body')[0]; b.appendChild(temp); }";
    ((IJavaScriptExecutor)driver).ExecuteScript(js);

    WaitForSuccess(() =>
    {
        IWebElement element = null;
        try
        {
            element = driver.FindElement(By.Id("browserReady"));
        }
        catch
        {
            // element not found
        }

        return element != null;
    },
    timeoutInMilliseconds: 10000);

    js = @"{var temp=document.getElementById('browserReady');" +
         @" temp.parentNode.removeChild(temp);}";
    ((IJavaScriptExecutor)driver).ExecuteScript(js);
}

private bool WaitForSuccess(Func<bool> action, int timeoutInMilliseconds)
{
    if (action == null) return false;

    bool success;
    const int PollRate = 250;
    var maxTries = timeoutInMilliseconds / PollRate;
    int tries = 0;
    do
    {
        success = action();
        tries++;
        if (!success && tries <= maxTries)
        {
            Thread.Sleep(PollRate);
        }
    }
    while (!success && tries < maxTries);
    return success;
}

Предполагается, что если браузер отвечает на функции javascript и находит элементы, то он, вероятно, является надежным экземпляром и готов к использованию.

Похожие вопросы