使用DRb共享Selenium WebDriver对象出现Drb::DRbConnError错误如何解决
问题原因
- 核心原因是Selenium WebDriver实例绑定其创建进程(也就是Client1.rb的运行进程),你通过DRb存储到服务端的并不是驱动对象的完整副本,只是指向Client1进程中该实例的远程引用。
- Client1.rb执行完最后一行代码后会直接退出,进程销毁后该远程引用的指向地址失效,Client2.rb调用驱动方法时,DRb尝试访问已经退出的Client1进程,就会抛出
Drb::DRbConnError: connection closed错误。
解决方案
方案1:保留Client1进程不退出
在Client1.rb的最后添加一行代码,让Client1进程持续运行不销毁:
# Client1.rb 末尾新增 DRb.thread.join
这种改法最简单,只要Client1不停止运行,驱动实例就一直有效,Client2就可以正常调用。
方案2:将驱动实例放到DRb服务端初始化
直接在服务端封装驱动的所有操作,避免在客户端创建驱动再上传,从根源上避免引用失效问题。修改后代码示例:
调整后的Server.rb
require 'drb/drb' require 'selenium-webdriver' URI="druby://localhost:8787" class TestScope @@driver = nil def init_firefox_driver @@driver = Selenium::WebDriver::Driver.for :firefox end def navigate_to(url) @@driver.navigate.to url end # 可以按需封装更多驱动操作方法 def get_driver return @@driver end end FRONT_OBJECT=TestScope.new DRb.start_service(URI, FRONT_OBJECT, safe_level: 0, verbose: true) DRb.thread.join
调整后的Client1.rb
require 'drb/drb' SERVER_URI="druby://localhost:8787" DRb.start_service test_scope = DRbObject.new_with_uri(SERVER_URI) test_scope.init_firefox_driver test_scope.navigate_to "http://www.google.com"
调整后的Client2.rb
require 'drb/drb' SERVER_URI="druby://localhost:8787" DRb.start_service test_scope = DRbObject.new_with_uri(SERVER_URI) test_scope.navigate_to "http://www.yahoo.com"
这种方案稳定性更高,只要服务端进程不退出,所有客户端都可以正常操作同一个驱动实例。
其他注意事项
- DRb的
safe_level设为1时会限制部分对象的序列化和方法调用,如果出现权限类报错可以先改为0测试。 - 如果需要更长时间的浏览器复用,也可以直接在启动火狐时开启远程调试端口,后续脚本直接通过调试端口附着到已经运行的浏览器实例,不需要依赖DRb。
内容的提问来源于stack exchange,提问作者Vishwanath Heddoori
相关产品推荐
相关产品推荐

