Ich habe eine Anwendung, die Selen-Webdriver verwendet, um mit PhantomJS zu interagieren. Um die Dinge zu skalieren, möchte ich mehrere Instanzen von PhantomJS ausführen und sie mit haproxy ausgleichen. Dies ist für eine lokale Anwendung, so dass ich nicht mit der Bereitstellung in einer Produktionsumgebung oder ähnlichem beschäftigt bin.Wie lade ich phantomjs mit docker-compose und haproxy?
Hier ist meine docker-compose.yml
Datei:
version: '2'
services:
app:
build: .
volumes:
- .:/code
links:
- mongo
- haproxy
mongo:
image: mongo
phantomjs1:
image: wernight/phantomjs:latest
ports:
- 8910
entrypoint:
- phantomjs
- --webdriver=8910
- --ignore-ssl-errors=true
- --load-images=false
phantomjs2:
image: wernight/phantomjs:latest
ports:
- 8910
entrypoint:
- phantomjs
- --webdriver=8910
- --ignore-ssl-errors=true
- --load-images=false
phantomjs3:
image: wernight/phantomjs:latest
ports:
- 8910
entrypoint:
- phantomjs
- --webdriver=8910
- --ignore-ssl-errors=true
- --load-images=false
phantomjs4:
image: wernight/phantomjs:latest
ports:
- 8910
entrypoint:
- phantomjs
- --webdriver=8910
- --ignore-ssl-errors=true
- --load-images=false
haproxy:
image: haproxy
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
ports:
- 8910:8910
links:
- phantomjs1
- phantomjs2
- phantomjs3
- phantomjs4
Wie Sie sehen können, habe ich vier Instanzen von PhantomJS habe, eine haproxy Instanz und eine App (in Python geschrieben).
Hier ist mein haproxy.cfg
:
global
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
maxconn 4096
daemon
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
maxconn 2000
timeout connect 5000
timeout client 50000
timeout server 50000
frontend phantomjs_front
bind *:8910
stats uri /haproxy?stats
default_backend phantomjs_back
backend phantomjs_back
balance roundrobin
server phantomjs1 phantomjs1:8910 check
server phantomjs2 phantomjs2:8910 check
server phantomjs3 phantomjs3:8910 check
server phantomjs4 phantomjs4:8910 check
Ich weiß, ich Sticky Sessions oder etwas in haproxy verwenden müssen, diese Arbeit zu bekommen, aber ich weiß nicht, wie das zu tun.
Hier ist ein relevanter Ausschnitt aus meiner Python App-Code, der zu diesem Dienst verbindet:
def get_page(url):
driver = webdriver.Remote(
command_executor='http://haproxy:8910',
desired_capabilities=DesiredCapabilities.PHANTOMJS
)
driver.get(url)
source = driver.page_source
driver.close()
return source
Die Störung, die ich erhalte, wenn ich versuche, diesen Code auszuführen, ist dies:
phantomjs2_1 | [ERROR - 2016-07-12T23:35:25.454Z] RouterReqHand - _handle.error - {"name":"Variable Resource Not Found","message":"{\"headers\":{\"Accept\":\"application/json\",\"Accept-Encoding\":\"identity\",\"Connection\":\"close\",\"Content-Length\":\"96\",\"Content-Type\":\"application/json;charset=UTF-8\",\"Host\":\"172.19.0.7:8910\",\"User-Agent\":\"Python-urllib/3.5\"},\"httpVersion\":\"1.1\",\"method\":\"POST\",\"post\":\"{\\\"url\\\": \\\"\\\\\\\"http://www.REDACTED.com\\\\\\\"\\\", \\\"sessionId\\\": \\\"4eff6a60-4889-11e6-b4ad-095b9e1284ce\\\"}\",\"url\":\"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/url\",\"urlParsed\":{\"anchor\":\"\",\"query\":\"\",\"file\":\"url\",\"directory\":\"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/\",\"path\":\"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/url\",\"relative\":\"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/url\",\"port\":\"\",\"host\":\"\",\"password\":\"\",\"user\":\"\",\"userInfo\":\"\",\"authority\":\"\",\"protocol\":\"\",\"source\":\"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/url\",\"queryKey\":{},\"chunks\":[\"session\",\"4eff6a60-4889-11e6-b4ad-095b9e1284ce\",\"url\"]}}","line":80,"sourceURL":"phantomjs://code/router_request_handler.js","stack":"[email protected]://code/router_request_handler.js:80:82"}
phantomjs2_1 |
phantomjs2_1 | phantomjs://platform/console++.js:263 in error
app_1 | Traceback (most recent call last):
app_1 | File "selenium_process.py", line 69, in <module>
app_1 | main()
app_1 | File "selenium_process.py", line 61, in main
app_1 | source = get_page(args.url)
app_1 | File "selenium_process.py", line 52, in get_page
app_1 | driver.get(url)
app_1 | File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/webdriver.py", line 248, in get
app_1 | self.execute(Command.GET, {'url': url})
app_1 | File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/webdriver.py", line 236, in execute
app_1 | self.error_handler.check_response(response)
app_1 | File "/usr/local/lib/python3.5/site-packages/selenium/webdriver/remote/errorhandler.py", line 163, in check_response
app_1 | raise exception_class(value)
app_1 | selenium.common.exceptions.WebDriverException: Message: Variable Resource Not Found - {"headers":{"Accept":"application/json","Accept-Encoding":"identity","Connection":"close","Content-Length":"96","Content-Type":"application/json;charset=UTF-8","Host":"172.19.0.7:8910","User-Agent":"Python-urllib/3.5"},"httpVersion":"1.1","method":"POST","post":"{\"url\": \"\\\"http://www.REDACTED.com\\\"\", \"sessionId\": \"4eff6a60-4889-11e6-b4ad-095b9e1284ce\"}","url":"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/url","urlParsed":{"anchor":"","query":"","file":"url","directory":"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/","path":"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/url","relative":"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/url","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/session/4eff6a60-4889-11e6-b4ad-095b9e1284ce/url","queryKey":{},"chunks":["session","4eff6a60-4889-11e6-b4ad-095b9e1284ce","url"]}}
app_1 |
So, wie bekomme ich Load Balancing? Was vermisse ich?
UPDATE
dachte ich, dass ich eine Art Session-Management in haproxy müssen aus. Der selen webdriver und phantomjs kommunizieren über Sitzungen. Der Client sendet eine POST /session
und empfängt eine Antwort mit der Sitzungs-ID im Text. Diese Antwort sieht etwa so aus:
{"sessionId":"5a27f2b0-48a5-11e6-97d7-7f5820fc7aa6","status":0,"value":{"browserName":"phantomjs","version":"2.1.1","driverName":"ghostdriver","driverVersion":"1.2.0","platform":"linux-unknown-64bit","javascriptEnabled":true,"takesScreenshot":true,"handlesAlerts":false,"databaseEnabled":false,"locationContextEnabled":false,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"cssSelectorsEnabled":true,"webStorageEnabled":false,"rotatable":false,"acceptSslCerts":false,"nativeEvents":true,"proxy":{"proxyType":"direct"}}}
Dann wird, wie die Sitzung fortschreitet, wird die Session-ID auf den Server als Teil der URI in nachfolgenden Anfragen gesendet, wie GET /session/5a27f2b0-48a5-11e6-97d7-7f5820fc7aa6/source
. Wie kann ich dieses Zeug für klebrige Sitzungen in Haproxy greifen?
FWIW, es wäre nicht sinnvoll, Sitzungen an die anfordernde IP-Adresse zu binden, da es nur eine Instanz meiner App gibt, die mehrere Verbindungen zu den verschiedenen phantomjs-Servern herstellt. – DynamiteReed
Haben Sie eine Lösung gefunden? –
Leider habe ich nicht. – DynamiteReed