web-dev-qa-db-fra.com

ConnectionResetError: [Errno 104] Réinitialisation de la connexion par l'homologue et ERR_NAME_NOT_RESOLVED sur heroku avec test mobile via Selenium

Je voudrais tester plusieurs agents d'utilisateurs mobiles avec du sélénium et du chrome. J'utilise python 3.6 et je déploie sur heroku. Basé sur http://chromedriver.chromium.org/mobile-emulation .

Vous pouvez télécharger mon projet pour Windows et Heroku sur:

https://github.com/kc1/mobiletest

(gardez à l'esprit que si vous déployez sur heroku, vous devez définir FLASK_CONFIG en production. Veuillez également noter que le code du projet est légèrement différent de celui de cette question car j'ai joué avec le code au cours de la semaine dernière.)

J'ai:

def some_long_calculation():
    driver = create_chromedriver('kkk')
    # driver = create_chromedriver()

    driver.get("https://www.yahoo.com/")
    .....

et :

def create_chromedriver(ua=False):
    options = webdriver.ChromeOptions()
    CHROMEDRIVER_PATH = os.getenv('$HOME') or basedir+'/chromedriver.exe'
    FLASK_CONFIG = os.getenv('FLASK_CONFIG')

    if ua:

        mobile_emulation = {"deviceName": "Nexus 5"}
        options.add_experimental_option("mobileEmulation", mobile_emulation)


    if FLASK_CONFIG and FLASK_CONFIG == "production":
        CHROMEDRIVER_PATH = '/app/.chromedriver/bin/chromedriver'
        GOOGLE_CHROME_SHIM = os.getenv('$GOOGLE_CHROME_SHIM') or 'no path found'
        options.binary_location = '/app/.apt/usr/bin/google-chrome-stable'

        options.add_argument('--disable-gpu')
        options.add_argument('--no-sandbox')

    return webdriver.Chrome(executable_path=CHROMEDRIVER_PATH, options=options)  

Si je l'exécute localement avec le navigateur mobile activé, cela fonctionne comme prévu:

enter image description here

Si je l'exécute sur heroku avec le navigateur mobile activé:

enter image description here

Ensuite, je l'ai essayé sur heroku avec l'utilisateur mobile désactivé, je reçois:

enter image description here

Donc, au moins, je sais que la configuration fonctionne jusqu'à chrome et chromedriver.

journaux heroku:

2018-07-15T17:37:53.967643+00:00 app[web.1]:     driver = create_chromedriver('kkk')
2018-07-15T17:37:53.967637+00:00 app[web.1]:     png = some_long_calculation()
2018-07-15T17:37:53.967645+00:00 app[web.1]:   File "/app/app/main/cl.py", line 120, in create_chromedriver
2018-07-15T17:37:53.967640+00:00 app[web.1]:   File "/app/app/main/cl.py", line 123, in some_long_calculation
2018-07-15T17:37:53.967648+00:00 app[web.1]:     return webdriver.Chrome(executable_path=CHROMEDRIVER_PATH, options=options)
2018-07-15T17:37:53.967651+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/Selenium/webdriver/chrome/webdriver.py", line 75, in __init__
2018-07-15T17:37:53.967654+00:00 app[web.1]:     desired_capabilities=desired_capabilities)
2018-07-15T17:37:53.967656+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/Selenium/webdriver/remote/webdriver.py", line 156, in __init__
2018-07-15T17:37:53.967659+00:00 app[web.1]:     self.start_session(capabilities, browser_profile)
2018-07-15T17:37:53.967661+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/Selenium/webdriver/remote/webdriver.py", line 251, in start_session
2018-07-15T17:37:53.967669+00:00 app[web.1]:     response = self.command_executor.execute(driver_command, params)
2018-07-15T17:37:53.967664+00:00 app[web.1]:     response = self.execute(Command.NEW_SESSION, parameters)
2018-07-15T17:37:53.967667+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/Selenium/webdriver/remote/webdriver.py", line 318, in execute
2018-07-15T17:37:53.967672+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/Selenium/webdriver/remote/remote_connection.py", line 472, in execute
2018-07-15T17:37:53.967674+00:00 app[web.1]:     return self._request(command_info[0], url, body=data)
2018-07-15T17:37:53.967677+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/Selenium/webdriver/remote/remote_connection.py", line 496, in _request
2018-07-15T17:37:53.967679+00:00 app[web.1]:     resp = self._conn.getresponse()
2018-07-15T17:37:53.967682+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/http/client.py", line 1331, in getresponse
2018-07-15T17:37:53.967685+00:00 app[web.1]:     response.begin()
2018-07-15T17:37:53.967687+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/http/client.py", line 297, in begin
2018-07-15T17:37:53.967695+00:00 app[web.1]:     line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
2018-07-15T17:37:53.967690+00:00 app[web.1]:     version, status, reason = self._read_status()
2018-07-15T17:37:53.967698+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/socket.py", line 586, in readinto
2018-07-15T17:37:53.967692+00:00 app[web.1]:   File "/app/.heroku/python/lib/python3.6/http/client.py", line 258, in _read_status
2018-07-15T17:37:53.967700+00:00 app[web.1]:     return self._sock.recv_into(b)
2018-07-15T17:37:53.967712+00:00 app[web.1]: ConnectionResetError: [Errno 104] Connection reset by peer

Comment puis-je réparer cela?

ÉDITER:

Merci pour votre réponse détaillée. J'ai changé le code pour incorporer les drapeaux que vous avez mentionnés. Chrome est 67.0.3396.99. Chromedriver est 2.40 et Selenium est 3.13. Malheureusement, il n'y a aucun changement dans le résultat. Je reçois toujours la même erreur. En ce qui concerne votre étape 2 et 3. Je déploie actuellement sur heroku donc je n'ai pas le contrôle total des variables d'environnement. Y a-t-il un moyen de faire ces changements en utilisant python?

EDIT 2:

Comme j'y pense plus sur https://sites.google.com/a/chromium.org/chromedriver/mobile-emulation l'exemple utilise

from Selenium import webdriver
mobile_emulation = { "deviceName": "Nexus 5" }
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
driver = webdriver.Remote(command_executor='http://127.0.0.1:4444/wd/hub',
                  desired_capabilities = chrome_options.to_capabilities())

Suggérez-vous que le navigateur est à ' http://127.0.0.1:4444/wd/hub '

8
user61629

ConnectionResetError: [Errno 104] Connexion réinitialisée par l'homologue

En général, lorsqu'un client se termine brutalement sans fermer la connexion, un RST packet Est envoyé par la pile TCP/IP du système d'exploitation sous-jacent. Python convertit cela en une exception avec le texte Réinitialisation de la connexion par l'homologue . Selon votre pile d'erreur trace cela signifie qu'une fois que self._read_status() a été invoquée (en interne) Python supposé recevoir quelque chose mais la connexion a été soudainement interrompue et Python vous informe de cette erreur en levant l'exception:

ConnectionResetError: [Errno 104] Connection reset by peer

La situation est quelque peu similaire à cette expression :

"Réinitialisation de la connexion par l'homologue" est l'équivalent TCP/IP du claquement du téléphone sur le crochet. C'est plus poli que simplement de ne pas répondre, laissant une pendaison. Mais ce n'est pas le FIN-ACK attendu du converseur TCP/IP vraiment poli.

Il peut y avoir plusieurs probabilités derrière cette erreur comme suit.


Étape de solution A

Une solution rapide et précise consistera à ajouter quelques-uns ChromeOptions recommandés ainsi que celui existant comme suit:

options.add_argument("start-maximized"); // open Browser in maximized mode
options.add_argument("disable-infobars"); // disabling infobars
options.add_argument("--disable-extensions"); // disabling extensions
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage"); // overcome limited resource problems

puis

return webdriver.Chrome(executable_path=CHROMEDRIVER_PATH, options=options) 

Remarque : Vous devez supprimer l'argument options.add_argument('--disable-gpu') car il s'applique uniquement au système d'exploitation Windows.


Étape B de la solution

Quelques points:

  • Selon la documentation de Python Chrome Mobile Emulation la Clé et Value la paire semble être "deviceName": "Google Nexus 5" (pas "deviceName": "Nexus 5")
  • Vous pouvez modifier votre code pour invoquer Remote() de l'une des manières suivantes:

    • Appel de Remote() à DesiredCapabilities():

      from Selenium import webdriver
      # import DesiredCapabilities was missing in your program
      from Selenium.webdriver.common.desired_capabilities import DesiredCapabilities
      
      mobile_emulation = { "deviceName": "Google Nexus 5" }
      chrome_options = webdriver.ChromeOptions()
      chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
      capabilities = DesiredCapabilities.CHROME
      capabilities = options.to_capabilities()
      driver = webdriver.Remote(command_executor='http://127.0.0.1:4444/wd/hub', desired_capabilities = capabilities)
      
    • Vous trouverez une discussion similaire sur l'invocation de Remote() à ChromeOptions() dans Comment ajouter des options de sélénium chrome à 'desireCapabilities'?

    • Appel de Remote() à ChromeOptions():

      from Selenium import webdriver
      mobile_emulation = { "deviceName": "Google Nexus 5" }
      chrome_options = webdriver.ChromeOptions()
      chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
      driver = webdriver.Remote(command_executor='http://127.0.0.1:4444/wd/hub', options=chrome_options)
      
    • Vous trouverez une discussion similaire sur l'appel de Remote() à ChromeOptions() dans Remote WebDriver UnreachableBrowserException: impossible de démarrer une nouvelle session

  • Pour votre référence, voici le lien vers la documentation sur Webdriver.Android
  • Pour votre référence, voici le lien vers la documentation sur Getting started with Selendroid

Étape C de la solution

Si l'erreur persiste, effectuez les tâches de mise à niveau/nettoyage suivantes:

  • Mettre à niveau Selenium aux niveaux actuels Version 3.13.0 .
  • Mettre à niveau ChromeDriver au niveau --- ChromeDriver v2.40 actuel.
  • Gardez Chrome version entre Chrome v66-68 niveaux. ( selon les notes de publication de ChromeDriver v2.4 )
  • Clean your Project Workspace through your [~ # ~] ide [~ # ~] and Rebuild votre projet avec les dépendances requises uniquement.
  • ( WindowsOS uniquement) Utilisez CCleaner outil pour effacer toutes les tâches du système d'exploitation avant et après l'exécution de votre Suite de tests.
  • ( LinuxOS uniquement) Libérez et libérez la mémoire non utilisée/mise en cache dans Ubuntu/Linux Mint avant et après l'exécution de votre Suite de test.
  • Si votre version de base Web Client est trop ancienne, désinstallez-la via Revo Uninstaller et installez une version récente GA et la version publiée de Web Client.
  • Prenez un Redémarrage du système.
  • Appelez toujours driver.quit() dans la méthode tearDown(){} pour fermer et détruire les instances WebDriver et Web Client avec élégance.
  • Exécutez votre @Test.

Étape de solution D

À la recherche d'une solution granulaire à une erreur spécifique, je suis entré dans Amazon S3 et "Connection Reset by Peer" où Garry Dolley estivale la cause du problème est une combinaison des facteurs mentionnés ci-dessous:

  • Mise à l'échelle de la fenêtre TCP
  • noyaux Linux 2.6.17 ou plus récents

Les noyaux Linux 2.6.17+ ont augmenté la taille maximale de la fenêtre/du tampon TCP, et cela a commencé à entraîner la perte d'autres équipements, s'il ne pouvait pas gérer suffisamment grand TCP windows. L'engrenage réinitialisera la connexion, et nous voyons cela comme un message "Connection reset by peer".

Une solution potentielle sera de mettre les entrées suivantes dans /etc/sysctl.conf:

  • net.ipv4.tcp_wmem = 4096 16384 512000
  • net.ipv4.tcp_rmem = 4096 87380 512000

Remarque : ce correctif est simple, mais il ralentira votre échange de débit maximal de téléchargements plus rapides.


PS

Le cas échéant, assurez-vous que/etc/hosts sur votre système contient l'entrée suivante:

127.0.0.1               localhost.localdomain localhost

Discussions connexes

Voici quelques-unes des discussions connexes:


Les références

Voici les références de cette discussion:

8
DebanjanB

Le message d'erreur spécifique indique

Android L'adresse IP du serveur est introuvable.

Pour moi, cela indique que le navigateur essaie de rechercher une entrée DNS pour Android, qui n'est pas un TLD valide. Par hasard, le navigateur tente-t-il d'accéder à http://Android, plutôt que quelque chose comme https://www.google.com? Je peux reproduire ce même message d'erreur dans mon propre Chrome en tapant http://Android dans la barre d'adresse. Cela m'amène à croire que la spécification d'une URL appropriée pour le navigateur devrait résoudre le problème.

2
Josh W Lewis