I use a bokeh server that is loaded when accessing a flask route. I am trying to make the server work with num-procs != 1. There is no problem when using num-procs 1
@app.route('/cyclone/<sid>')
def trackServer(sid):
#Stuff ...
# Retrieve the script to include the bokeh app to the page.
script = server_document('http://derive.ifremer.fr/bokeh_server/panel', arguments={"sid": sid})
# Other stuff...
return render_template("cyclone.html", script=script, resources=CDN.render(), template="Flask",
years=getAllAvailYears(),
cycInfos=cycInfos, year=cycInfos[1].year, basin=cycInfos[4][0], sid=sid, hasAcq=hasAcq)
In server_document function, I am passing a URL argument ‘sid’.
What is not working :
When using num-procs != 1, and accessing the bokeh server through the flask route, the bokeh server application does not always receive the url argument.
To be more precise :
The flask route is accessed
The bokeh server loads a first time, always correctly receiving the URL argument
Soon after, the bokeh server seems to load the app a second time, this time the URL argument is not always received (curdoc().session_context.request.arguments is empty)
After the second loading, if the url argument is correctly received, the application shows in the browser. If not received, the app crash because it needs this argument.
In my code, the line failing is : args = curdoc().session_context.request.arguments because the returned dict should contain my url argument name and value
What I tried : It is correctly working when directly accessing the bokeh application in my browser (not going through the flask route) When doing this, the bokeh app still seems to load 2 times, but both times it correctly gets the URL argument.
Could it be an issue with server_document ? Something I’m doing wrong ?
Probably related but issues are closed (and fixed):
@Skealz This should be resolve, since as of 2.x all HTPP request arguments are stuffed inside the websocket session token. So it should not matter if the websocket connection lands on a different process than the original HTTP request. But if you are saying you are seeing an issue, then it will require real investigation. For that we absolutely will need a complete, minimal, reproducer we can run ourselves to look into.
@Skealz when I run that code flask returns a 404 just on the request to 127.0.0.1:5000
dev) ❯ * Serving Flask app "flask_app.py"
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
2020-06-16 02:21:35,444 Starting Bokeh server version 2.1.0+6.g5e72ad3e4.dirty (running on Tornado 6.0.3)
2020-06-16 02:21:35,444 Host wildcard '*' will allow connections originating from multiple (or possibly all) hostnames or IPs. Use non-wildcard values to restrict access explicitly
2020-06-16 02:21:35,445 User authentication hooks NOT provided (default user enabled)
2020-06-16 02:21:35,454 Bokeh app running at: http://0.0.0.0:5006/bokeh_app
2020-06-16 02:21:35,454 Bokeh app running at: http://0.0.0.0:5006/bokeh_app
2020-06-16 02:21:35,455 Starting Bokeh server with process id: 79838
2020-06-16 02:21:35,455 Starting Bokeh server with process id: 79839
2020-06-16 02:21:35,455 Bokeh app running at: http://0.0.0.0:5006/bokeh_app
2020-06-16 02:21:35,455 Starting Bokeh server with process id: 79840
2020-06-16 02:21:35,455 Bokeh app running at: http://0.0.0.0:5006/bokeh_app
2020-06-16 02:21:35,456 Starting Bokeh server with process id: 79841
127.0.0.1 - - [16/Jun/2020 02:21:42] "GET / HTTP/1.1" 404 -
@Philipp_Rudiger I think this is a consequence of the WS landing on the same process as the original HTTP request. In that case, the existing session is re-used (i.e. the app code is not run again). Which is also consistent with it happening relatively infrequently when n=4.
A short term solution may simply be to always re-create an app session by running the app code on the WS connect. That’s obviously expensive/wasteful in many cases, though. The best solution would be to only run it once on the ws connect, and not run it at all on the HTTP connection. But that would require some breaking changes (as we have previously discussed)
@Skealz You should make a GitHub issue with the information you provided. I am afraid I don’t have any workaround to provide in the immediate term.
value=test is correctly passed the first time but not the second one foo=bar is correctly passed the second time but not the first one
In this minimal application, the value given after the “host” portion of the URL is transferred to bokeh. Check for the value variable in this snippet.
@app.route('/<value>')
def index(value):
# Retrieve the script to include the bokeh app to the page.
script = server_document('http://localhost:5006/bokeh_app', arguments={"value": value})
return render_template("app.html", script=script, resources=CDN.render())
from flask import request
@app.route("/")
def index():
urlParamValue = request.args.get('value')
# Retrieve the script to include the bokeh app to the page.
script = server_document('http://localhost:5006/bokeh_app', arguments={"value": urlParamValue})
return render_template("app.html", script=script, resources=CDN.render())
@Philipp_Rudiger actually at first I didn’t notice that the args were passed in the embedding call. Is there a code path that prefers url args over any sent by the embedding call (there must be)? Fixing that would be sufficient I think.
@Philipp_Rudiger Yes, this is an issue with the processing of HTTP request arguments, which go through the session token. The situation more summarized is this:
Now, a user navigates to the page that embeds the app, and also supplies args on the URL:
https://some.flaskapp.com/stuff?baz=quux
If --num-procs=1 then the server HTTP and ws connections land on the same process. The app code is executed once for the session, and sees foo=bar
However, if --num-procs > 1` then one of two things can happen:
HTTP and ws land on the same process.
The app code is executed once for the session, and sees foo=bar
HTTP and ws land on the different process.
The app code is executed twice for the session, but the executions seen different values for arguments. The first exection (for the HTTP connect) sees foo=bar. But the second execution (for the ws connect on the other process) does not. Instead that app code sees baz=quux from the browser URL.
My hypothesis here is that somewhere there is a condition to choose HTTP args either out of the token, or off the URL, and that it is doing the wrong thing. It should always prefer any arguments from the token over any in the URL. (In fact for embedding specifically it’s possible we should ignore the URL, since the URL is for the Flask or whatever app, and not for the Bokeh app)