我看到一些使用 Selenium WebDriver 运行并行嵌套循环 Web 压力测试的死实例怪异现象,简单的例子是,比如说,点击 300 个唯一页面,每个页面有 100 次展示。
我“成功”使用 ThreadLocal<FirefoxWebDriver>
获取 4 - 8 个 WebDriver 实例每个任务线程隔离它们,并在 ParallelOptions 实例上使用 MaxDegreeOfParallelism 来限制线程。我仅对外部循环(页面集合)进行分区和并行化,并检查 .IsValueCreated
关于ThreadLocal<>
容器内部每个分区的“长时间运行任务”方法的开始。为了便于稍后清理,我将每个新实例添加到以线程 ID 为键控的 ConcurrentDictionary 中。
无论我使用什么并行化或分区策略,WebDriver 实例偶尔都会执行以下操作之一:
- 启动但不显示网址或进行展示
- 启动,运行任意数量的展示次数,然后在某个时刻闲置
当其中任何一种情况发生时,并行循环最终似乎会注意到线程没有执行任何操作,并且它会生成一个新分区。如果 n 是允许的线程数,则这会导致 n 个高效线程仅在大约 50-60% 的时间内出现。
最后清理工作仍然正常;可能有 2n 个或更多打开的浏览器,但高效和低效的浏览器都会被清理。
有没有办法监视这些无用的 WebDriver 实例,并且 a) 立即清除它们,再加上 b) 让并行循环立即替换任务段,而不是像现在那样滞后几分钟?
最佳答案
我也遇到了类似的问题。事实证明,WebDriver 没有查找开放端口的最佳方法。如上所述here它会在端口上获得系统范围的锁定,找到开放的端口,然后启动实例。这可能会导致您尝试启动的其他实例缺乏端口。
我通过直接在ThreadLocal<IWebDriver>
的委托(delegate)中指定一个随机端口号来解决这个问题。像这样:
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);
});
这对我来说效果相当一致,尽管如果您最终使用了列表中 Unresolved 所有 50 个,则会出现问题。
关于c# - 在并行任务期间跟踪失效的 WebDriver 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10327095/