Deploying a multi-user Dashboard#
cuXfilter dashboard when run from a jupyter/jupyterlab notebook, can be run as a single session temporary dashboard within the context of the notebook session. Since it is a Bokeh web application, it is also possible to run it as a multi-instance, multi-user dashboard behind a load balancer (e.g: nginx load balancer).
Example#
Running the auto_accidents dashboard behind a local load balancer:
main.py#
from bokeh.server.server import Server
import cuxfilter
import sys
DATA_DIR = './data'
cux_df = cuxfilter.DataFrame.from_arrow(DATA_DIR+'/auto_accidents.arrow')
cux_df.data['ST_CASE'] = cux_df.data['ST_CASE'].astype('float64')
def bkapp(doc):
global cux_df
label_map = {1: 'Sunday', 2: 'Monday', 3: 'Tuesday', 4: 'Wednesday', 5: 'Thursday', 6: 'Friday', 7: 'Saturday', 9: 'Unknown'}
gtc_demo_red_blue_palette = [ (49,130,189), (107,174,214), (123, 142, 216), (226,103,152), (255,0,104) , (50,50,50) ]
# declare charts
chart1 = cuxfilter.charts.scatter(x='dropoff_x', y='dropoff_y', aggregate_col='ST_CASE',
color_palette=gtc_demo_red_blue_palette)
chart2 = cuxfilter.charts.multi_select('YEAR')
chart3 = cuxfilter.charts.bar('DAY_WEEK', x_label_map=label_map)
chart4 = cuxfilter.charts.bar('MONTH')
# declare dashboard
d = cux_df.dashboard([chart1, chart2, chart3, chart4], layout=cuxfilter.layouts.feature_and_double_base,theme = cuxfilter.themes.default, title='Auto Accident Dataset')
# run the dashboard as a webapp:
d._dashboard.generate_dashboard(
d.title, d._charts, d._theme
).server_doc(doc)
if __name__ == '__main__':
server = Server({'/custom_dashboard': bkapp}, num_procs=1, allow_websocket_origin=["127.0.0.1:80"])
server.start()
print('running server on port '+str(port))
server.io_loop.start()
Load balancing#
Based on Bokeh deployment documentation mentioned here, we can setup load balancing with nginx reverse proxying setup.
Example nginx.conf
upstream demos {
least_conn;
server 127.0.0.1:5001;
server 127.0.0.1:5000;
}
server {
listen 80 default_server;
server_name _;
location / {
proxy_pass http://demos;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:$server_port;
proxy_buffering off;
}
}
Run the above as a python script:
python main.py 5000
python main.py 5001