Ubuntu18通過nginx+uwsgi來部署Superset到服務器


本文基於某某雲服務上選擇的Ubuntu18系統,其中自帶了mysql5.7、python2、python3.6.8。大家安裝的時候請注意環境了,不能照搬,不同系統的,有些安裝後的文件路徑不一致(反正我發現centos安裝的有些文件跟Ubuntu18有差異)
這是我成功部署後,回顧式的記錄了所做的過程。
2019年12月,由於換了服務器,又重新部署了,重新修正完善了一下。
希望給使用Superset的人員帶來方便!!!

來一張SuperSet的圖驗證真僞

在這裏插入圖片描述

大致網絡路由

路由轉換

前提是每個端口(8000、8009)在雲服務器上需要獲得安全策略通過

切換成pip3(pip3 command not found)

參考的其他文章解決方案

#強制重新用python3安裝pip文件,默認會是python2。
sudo apt-get install --reinstall python3-pip
#升級pip版本
pip3 install --upgrade setuptools pip 
# 後說明,在後邊的安裝過程中,發現pip list 和 pip3 list有少量的差異
# 所以:建議大家在虛擬環境下安裝的時候還是用pip3安裝。

安裝virtualenvwrapper及建立虛擬環境superset_env

1.安裝virtualenvwrapper

pip3 install virtualenvwrapper

2.創建目錄用來存放虛擬環境

 mkdir $HOME/.virtualenvs

查找virtualenvwrapper.sh、python3、virtualenv的路徑,供下邊文件配置使用:

#sudo  find / -name virtualenvwrapper.sh
/usr/local/bin/virtualenvwrapper.sh

#sudo  find / -name python3
/usr/bin/python3

#sudo  find / -name virtualenv
/usr/local/bin/virtualenv

3.在~/.bashrc中添加環境變量等:

export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh   #上邊的路徑
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv
source /usr/local/bin/virtualenvwrapper.sh

4.運行及生效文件

source ~/.bashrc

運行後的結果:

virtualenvwrapper.user_scripts creating /root/.virtualenvs/premkproject
virtualenvwrapper.user_scripts creating /root/.virtualenvs/postmkproject
virtualenvwrapper.user_scripts creating /root/.virtualenvs/initialize
virtualenvwrapper.user_scripts creating /root/.virtualenvs/premkvirtualenv
virtualenvwrapper.user_scripts creating /root/.virtualenvs/postmkvirtualenv
virtualenvwrapper.user_scripts creating /root/.virtualenvs/prermvirtualenv
virtualenvwrapper.user_scripts creating /root/.virtualenvs/postrmvirtualenv
virtualenvwrapper.user_scripts creating /root/.virtualenvs/predeactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/postdeactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/preactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/postactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/get_env_details

5.建立虛擬環境superset_env

mkvirtualenv superset_env

結果如下:

virtualenvwrapper.user_scripts creating /root/.virtualenvs/superset_env/bin/predeactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/superset_env/bin/postdeactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/superset_env/bin/preactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/superset_env/bin/postactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/superset_env/bin/get_env_details

虛擬環境下安裝Superset

由於superset的機密機制是引用第三方庫cryptography,先安裝其依賴:

# 參照官網,如果是unbuntu系統的安裝依賴選項,python3.6版本
sudo apt-get install build-essential libssl-dev libffi-dev python3.6-dev python-pip libsasl2-dev libldap2-dev

# 紅帽系統和RHEL-derivatives系統
sudo yum upgrade python-setuptools
sudo yum install gcc gcc-c++ libffi-devel python-devel python-pip python-wheel openssl-devel cyrus-sasl-devel openldap-devel

# window不是官方支持的系統
# 先在https://bootstrap.pypa.io/get-pip.py下載  get-pip.py文件
pip3 install cryptography

根據上邊的虛擬路徑,先切換路徑到bin:
cd /root/.virtualenvs/superset_env/bin

pip3 install superset

# 後期升級superset
pip3 install apache-superset --upgrade
superset db upgrade
superset init

如果安裝出現這個錯誤:Failed building wheel for sasl。

執行以下命令解決:

sudo apt-get install libsasl2-dev

Superset配置與初始化

如果安裝通暢,可以忽略如下的報錯。

fabmanager create-admin --app superset

報錯一:Was unable to import superset Error: cannot import name ‘_maybe_box_datetimelike’

解決辦法:

pip install pandas==0.23.4

報錯二 "Can’t determine which FROM clause to join "

sqlalchemy.exc.InvalidRequestError: Can’t determine which FROM clause to join from, there are multiple FROMS which can join to this entity. Try adding an explicit ON clause to help resolve the ambiguity.

pip install SQLAlchemy==1.2.18

刪除mysql5.7(不是必須)

由於系統自帶的mysql5.7.26,又不知道密碼,試了各種辦法查找密碼,不行,乾脆粗暴點重裝

#首先在系統終端中查看MySQL的依賴項,運行命令:dpkg --list|grep mysql
卸載命令:sudo apt-get remove mysql-common
卸載命令:sudo apt-get autoremove --purge mysql-server-5.7
清除殘留數據,運行命令:dpkg -l|grep ^rc|awk '{print$2}'|sudo xargs dpkg -P
再次查看MySQL的剩餘依賴項,運行命令:dpkg --list|grep mysql
繼續刪除剩餘依賴項,如:sudo apt-get autoremove --purge mysql-apt-config
如果再次查看剩餘依賴項還有沒有刪除的,繼續上一步

具體參考徹底刪除mysql5.7

安裝mysql8(需最新的,網上其他的mysql-apt-config_0.8.10-1_all.deb是安裝成5.7的了)

通過https://dev.mysql.com/downloads/file/?id=487007,下載最新的mysql8.0。
或者:wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.13-1_all.deb
(後邊語句的這個沒驗證)
接下來在命令窗口依次輸入:

sudo dpkg -i mysql-apt-config_0.8.13-1_all.deb
sudo apt update
sudo apt-get install mysql-server
輸入密碼後提示(爲了更好的兼容5.7的,加密方式選擇第二種(5.x版本的):)

創建數據庫及用戶授權

參考設置mysql5.7文章
如果版本是5.7的話,這裏有個開啓遠程3306端口問題:
僅僅通過語句授權不能實現遠程登錄,需要在配置文件中註釋掉本地綁定。

1. 查看3306端口是否正常
root@node1:~# netstat -an | grep 3306
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN
注意:現在的3306端口綁定的IP地址是本地的127.0.0.1
 
2. 修改Mysql配置文件(注意路徑,跟之前網上的很多版本位置都不一樣)
root@node1:~# vim /etc/mysql/mysql.conf.d/mysqld.cnf
找到
bind-address            = 127.0.0.1
前面加#註釋掉上一行
create database news character set utf8;
# 'news':用戶名; '123news':密碼
create user 'news'@'39.15.16.14' identified by '123news';
# 給用戶授權,僅此授權還不夠
grant all privileges on news.* to 'news'@'39.15.16.14';
# 刷新權限
flush privileges;

SuperSet的數據庫從sqlite庫切換到mysql

vim /root/.virtualenvs/superset_env/lib/python3.6/site-packages/superset/config.py
修改一下文件中的SQLALCHEMY_DATABASE_URI :
SQLALCHEMY_DATABASE_URI =‘mysql://賬號:密碼@IP地址或者hostname/數據庫名?charset=utf8’

mssql配置(補充)

SQLALCHEMY_DATABASE_URI = mssql+pymssql://數據庫登錄名:登錄密碼@數據庫地址:端口號/數據庫

# 先升級庫
sudo apt-get install python3 python-dev python3-dev build-essential libssl-dev libffi-dev libxml2-dev libxslt1-dev zlib1g-dev python-pip
sudo apt install libmysqlclient-dev
# 安裝 mysqlclient 、pymysql
pip install mysqlclient 
pip install pymysql

重新設置SuperSet

# 重新初始化密碼,注意郵箱設置的唯一性
fabmanager create-admin --app superset
# 初始化數據庫
superset db upgrade
# 加載examples
superset load_examples
#初始化
superset init
# 啓動服務器,以前的runserver作廢了
superset  run

安裝nginx

注意安裝路徑:/home/software/nginx(後邊配置文件需要用到)

wget http://nginx.org/download/nginx-1.16.0.tar.gz
tar zxvf nginx-1.16.0.tar.gz
mv nginx-1.16.0 nginx
cd nginx
./configure --prefix=/home/software/nginx --with-http_stub_status_module --with-http_gzip_static_module
make
make install

配置nginx環境變量

vi ~/.bashrc   
#打開文檔添加:
alias nginx='/home/software/nginx/sbin/nginx'
# 保存並退出後生效更改
source ~/.bashrc

uwsgi安裝

pip install uwsgi

uwsgi配置

在 /root/.virtualenvs/superset_env/lib/python3.6/site-packages/superset路徑下新建一個uwsgi的入口文件:run.py(類似django的uwsgi文件)。

touch run.py

在文件中添加內容:

from superset import app
if __name__ == '__main__':
    app.run(host='0.0.0.0')

uwsgi.ini文件配置:

注意新建文件位置爲/home/uwsgi_conf:這個路徑可以自由設置

mkdir -p /home/uwsgi_conf
cd /home/uwsgi_conf
vi uwsgi.ini

文件具體的設置內容:

[uwsgi]
# 指定項目名所在的路徑(superset類似flask的一個工程,chdir是指定根目錄。只是我們安裝superset直接到了Python安裝包的位置下,其中/root/.virtualenvs/superset_env是我的虛擬環境的路徑,其後就是安裝superset的包的路徑)
chdir=/root/.virtualenvs/superset_env/lib/python3.6/site-packages/superset/
# 指定uwsgi協議入口文件(也就是剛纔我們新建的文件,由於前邊指定功能根目錄了,所以不許前綴路徑)
wsgi-file=run.py
# 指定入口文件中調用run方法的變量名
callable=app
#指定http(由於我們用Ngnix代理,所有用Socket)
#http=127.0.0.1:8000
# 指定sock的文件路徑(端口8009自主設定)
socket= 127.0.0.1:8009
# 指定靜態文件(static-map=網頁地址=本地文件位置,靜態文件一般在nginx中配置)
#static-map=/static=/home/myproject/static
# 設置日誌目錄
#daemonize= /home/uwsgi_conf/uwsgi.log
# pid文件位置(這行最好註釋,反正我不註釋會報錯)
#pidfile= /home/uwsgi_conf/uwsgi.pid(這行最好註釋,反正我不註釋會報錯)
# 進程個數(我的服務器是4核的)
workers=8
# 啓動uwsgi的用戶名和用戶組(都用root啓動,是出於權限的考慮,其他權限可能會啓動失敗)
#uid=root(這行最好註釋,反正我不註釋會報錯)
#gid=root(這行最好註釋,反正我不註釋會報錯)
# 啓用主進程
master=true
# 自動移除unix Socket和pid文件當服務停止的時候(默認)
vacuum=true
# 序列化接受的內容,如果可能的話(默認)
thunder-lock=true
# 啓用線程(默認)
enable-threads=true
# 設置自中斷時間(默認)
harakiri=30
# 設置緩衝(默認)
post-buffering=4096
# 設置代碼改動後自動加載(默認)
py-autoreload = 1

運行測試(可以跳過)

說明:根據Superset的說明文檔,如果不是使用默認的gunicorn,得在Superset的設置文檔中將ENABLE_FLASK_COMPRESS 設置成False
原話爲:
If not using gunicorn, you may want to disable the use of flask-compress by setting ENABLE_FLASK_COMPRESS = False in your superset_config.py

如果設定成了socket,就不要這樣設置了,(直接跳過下邊的測試,最終按nginx來運行)

uwsgi --ini /home/uwsgi_conf/uwsgi.ini
# 另一種指定文件的測試方式
# uwsgi --http :8000--wsgi-file test.py

打開瀏覽器,訪問127.0.0.1:8088。
如果正常訪問,則說明配置沒有問題

配置Superset的config

cd /root/.virtualenvs/superset_env/lib/python3.6/site-packages/superset/

vi config.py

在打開的配置文件中,找到ENABLE_FLASK_COMPRESS=True所在位置
同時修改成下邊的

ENABLE_FLASK_COMPRESS = False 

安裝nginx

sudo apt-get update
sudo apt-get install nginx

配置nginx

修改用戶及增加server配置項(頭尾部分需修改,其他的都按默認的處理):

# nginx路徑:
cd /etc/nginx
vi nginx.conf

啓動nginx後會有警告提示:正在使用root賬戶。
建議使用其他賬戶,具體怎麼配置等以後再調試。先跑通再說。

#修改用戶名root(這個需要修改原文件)
user root;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # SSL Settings
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Logging Settings
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
		 ##
        # Gzip Settings
        ##

        gzip on;

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # Virtual Host Configs
        ##
        
		#關鍵的增加部分及下邊的server
		# upstream就類似把server 127.0.0.1:8009綁定到一個名詞superset
		        upstream superset {
		            server 127.0.0.1:8009;
		        }
		        
		        server {
		            listen       8000 default_server;
		            listen       [::]:8000 default_server;
		            server_name  49.4.0.0;       #公網IP,建議把行後邊的註釋移到上頭,以免運行錯誤 ,我這只是方便你理解
		            root          /root/.virtualenvs/superset_env/lib/python3.6/site-packages/superset;  # 指定項目根目錄
		
		            location / {
		                include  uwsgi_params;
		                uwsgi_pass superset;    #上邊upstream綁定的名稱superset
		                }
		        }
				include /etc/nginx/conf.d/*.conf;
		        include /etc/nginx/sites-enabled/*;
	}

端口80被佔用

設置保存後,最好檢查一下nginx服務是否正常啓動,有時由於端口80被佔用( bind() to 0.0.0.0:80 failed),導致無法正常啓動,會報錯如下:

#  查詢nginx的連接狀態
systemctl status nginx.service
nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; disabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Sat 2019-07-13 13:59:24 CST; 43s ago
     Docs: man:nginx(8)
  Process: 3137 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=1/FAILURE)
  Process: 3126 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)

Jul 13 13:59:21 ecs-f316-0001 systemd[1]: Starting A high performance web server and a reverse proxy server...
Jul 13 13:59:21 ecs-f316-0001 nginx[3137]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 13 13:59:22 ecs-f316-0001 nginx[3137]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 13 13:59:22 ecs-f316-0001 nginx[3137]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 13 13:59:23 ecs-f316-0001 nginx[3137]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 13 13:59:23 ecs-f316-0001 nginx[3137]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Jul 13 13:59:24 ecs-f316-0001 nginx[3137]: nginx: [emerg] still could not bind()
Jul 13 13:59:24 ecs-f316-0001 systemd[1]: nginx.service: Control process exited, code=exited status=1
Jul 13 13:59:24 ecs-f316-0001 systemd[1]: nginx.service: Failed with result 'exit-code'.
Jul 13 13:59:24 ecs-f316-0001 systemd[1]: Failed to start A high performance web server and a reverse proxy server.

解決辦法

# 殺死nginx進程
killall -9 nginx
# 重新啓動服務
systemctl restart nginx.service

重新啓動uwsgi.ini的端口占用問題(例如ctr+C後重新啓動)

問題:probably another instance of uWSGI is running on the same address (127.0.0.1:8009)

[uWSGI] getting INI configuration from uwsgi.ini
(superset_env) root@ecs-f316-0001:/home/uwsgi_conf# *** Starting uWSGI 2.0.18 (64bit) on [Sat Jul 13 16:03:51 2019] ***
compiled with version: 7.4.0 on 09 July 2019 13:10:40
os: Linux-4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019
nodename: ecs-f316-0001
machine: x86_64
clock source: unix
detected number of CPU cores: 4
current working directory: /home/uwsgi_conf
detected binary path: /root/.virtualenvs/superset_env/bin/uwsgi
!!! no internal routing support, rebuild with pcre support !!!
uWSGI running as root, you can use --uid/--gid/--chroot options
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
chdir() to /root/.virtualenvs/superset_env/lib/python3.6/site-packages/superset/
your processes number limit is 31645
your memory page size is 4096 bytes
detected max file descriptor number: 65535
lock engine: pthread robust mutexes
thunder lock: enabled
probably another instance of uWSGI is running on the same address (127.0.0.1:8009).
bind(): Address already in use [core/socket.c line 769]

解決辦法

sudo fuser -k 8009/tcp     #8009就是配置中設置的端口號,自行修正

uwsgi --ini uwsgi.ini   #重新啓動

SuperVisor安裝及配置(這部分可以跳過閱讀,我僅保留記錄)

SuperVisor安裝

# 先切換到虛環境
pip install supervisor

SuperVisor配置

安裝好supervisor之後,默認是沒有生成配置文件的。可以通過以下命令生成配置文件.
參考–使用Supervisor守護Uwsgi進程
SuperVisor監視uwsgi
但是現在SuperVisor不可以監視後端程序了,否則status報backoff:
在這裏插入圖片描述

echo_supervisord_conf > /etc/supervisord.conf
vim /etc/supervisord.conf

在supervisord.conf文檔的後邊修改include的配置文件路徑

[include]
files = /etc/supervisor/*.conf

# 在文檔的前邊修改下邊三處,改成與下邊uwsgi.conf對應路徑/var/run/或/var/log/
/tmp/supervisor.sock 改成 /var/run/supervisor.sock,
/tmp/supervisord.log 改成 /var/log/supervisor.log,
/tmp/supervisord.pid 改成 /var/run/supervisor.pid

[inet_http_server] 
port=9001    ;端口自定義
username=user      
password=123

/etc/supervisor/目錄下創建一個uwsgi.conf文件,也就是上邊設置的include路徑,此處文件會被supervisord監視其內容的執行。

cd /etc/supervisor
touch uwsgi.conf
vim /etc/supervisor/uwsgi.conf

修改uwsgi.conf

; supervisor的程序名字
[program:supervisor_uwsgi]
; supervisor執行的命令,注意uwsgi的安裝路徑
command=/root/.virtualenvs/superset_env/bin/uwsgi --ini /home/uwsgi_conf/uwsgi.ini
; 項目的目錄
directory = /root/.virtualenvs/superset_env/lib/python3.6/site-packages/superset
; 開始的時候等待多少秒
startsecs=0
; 停止的時候等待多少秒
stopwaitsecs=0
; 自動開始
autostart=true
; 程序掛了後自動重啓
autorestart=true
; 輸出的log文件
stdout_logfile=/var/log/supervisord.log
; 輸出的錯誤文件
stderr_logfile=/var/log/supervisord.err

[supervisord]
; log的級別
loglevel=info

SuperVisor運行

#編輯退出後運行命令,在supervisor.conf路徑
supervisorctl -c supervisord.conf   
# 如果已經啓動,停止原有的supervisord
sudo pkill supervisord

進入到管理控制檯,然後執行相關的命令進行管理:

status      # 查看狀態`在這裏插入代碼片`
start program_name      #啓動程序supervisor
restart program_name   #重新啓動程序
stop program_name      #關閉程序
reload                           # 重新加載配置文件
quit                             #退出控制檯

Web端圖形化管理supervisor

據據前邊supervisor設置文件的地址:IP:9001,就可以方便的管理

後記

數據庫密碼獨立配置

def example_password_as_env_var(url):
    # assuming the uri looks like
    # mysql://localhost?superset_user:{SUPERSET_PASSWORD}
    return url.password.format(os.environ)

SQLALCHEMY_CUSTOM_PASSWORD_STORE = example_password_as_env_var

自己建立一個環境變量:SUPERSET_PASSWORD;試了一下,沒成功。
其中設置如下:
SQLALCHEMY_DATABASE_URI = ‘mssql+pymssql://sa:{}@localhost:1433/reports’

def lookup_password(url):
    return url.format(os.environ.get('SUPERSET_PASSWORD'))
SQLALCHEMY_CUSTOM_PASSWORD_STORE = lookup_password

沒辦法,先放棄系統自帶的格式SQLALCHEMY_CUSTOM_PASSWORD_STORE ,做了如下修改成功:

SQLALCHEMY_DATABASE_URI = 'mssql+pymssql://sa:{}@localhost:1433/reports'
# 結合環境變量值來重新賦值
SQLALCHEMY_DATABASE_URI=SQLALCHEMY_DATABASE_URI.format(os.environ.get('SUPERSET_PASSWORD'))

更進一步的可以把賬號也添加進環境變量,這個請您自己測試。

聯動圖設置

看下示例中的一個聯動效果圖:

聯動關聯州及國家氣泡圖

1、設置篩選項框
建立一個圖(filter-box):
在這裏插入圖片描述
注意綠色的Metric字段,這個字段跟待聯動圖的Metric字段關聯的
2、設置待聯動圖的Metric
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章