本地加載預訓練模型並進行推理,測試通過。想將其打包成網頁應用並對外展示。
hk的朋友有一個帶有公網ip的樹莓派服務器,開始嘗試
Try 樹莓派
配置環境
安裝conda
安裝conda,下載linux版格式不對,改成aarch64,還是報錯,"Illegal instruction"
換成Miniforge 樹莓派安裝Python3.8 64bit
然后 conda create -n deeplearning python=3.8 創建一個虛擬環境
安裝pytorch
樹莓派上只能編譯安裝
- 編譯安裝,兩個小時,樹莓派上安裝 PyTorch,直接放棄
為了節省時間,找大佬編譯好的 - 號稱是
linux-aarch64的,PyTorch 1.10.0 for the RPi 64-bit Bullseye,不行 armv7l不行,樹莓派4開箱及PyTorch配置記錄- 參考 樹莓派4B arm平台aarch64 pip安裝pytorch 去某鏡像站 找個whi,例如 torch-1.10.0-cp38-cp38-linux_aarch64.whl,然后
pip install,OK
安裝opencv
圖片的保存和resize用到了 opencv
sudo apt-get install opencv-python 無效,安裝成功但程序未檢測到
換用 pip install opencv,ok
運行AnimeGAN
環境沒問題,但是predict時會報錯:Out of memory

於是朋友給機器加了8G交換區間:

沒有出現爆內存了,但是網頁推理到一半會變成502,不知道是樹莓派的問題,還是終極Bug(后面會提))的問題
Note:
一些查看內存的命令
df -h # 磁盤掛載情況
free -h # 內存和交換區大小
dmesg # 內存日志
白忙活,換用Colab,印象中記得Colab也可以生成一個外部訪問的鏈接,於是,沖!
Try Colab
開啟外部訪問鏈接
from google.colab.output import eval_js
print(eval_js("google.colab.kernel.proxyPort(12345)"))
得到 https://bh0uv4zwoz6-496ff2e9c6d22116-12345-colab.googleusercontent.com/
很好,沒毛病
Out of memory
查看顯卡 !nvidia-smi,一張K80,11G顯存
上傳小點的圖片,推理成功
大點的圖片,Out of memory,need 13G only 11G is available
設置成CPU,慢點,又不是不能用!!
嘗試 ngrok
讓朋友測試一下??只有我能打開?可能是我瀏覽器登錄了Google賬號,和Colab是同一個
面向瀏覽器,找有沒有能公共訪問的端口訪問服務
[Is there a general way to run Web Applications on Google Colab?](Is there a general way to run Web Applications on Google Colab?),找到ngrok
github上還有樣例 flask-ngrok,開始
pip install flask-ngrok 安裝之后,只要添加一句 from flask_ngrok import run_with_ngrok
啟動后得到 http://5b8b-34-67-126-207.ngrok.io 類似這樣的鏈接
效果:的確能公開訪問,但是大圖片同樣gg,當時以為是 ngrok.io 的帶寬有限,現在想大概率也是終極Bug問題
放棄?我們不是有公網ip嗎,我在本地跑(程序最開始在本地是調通了的),再做內網穿透總行了吧
Try 本地
內網穿透
先把內網穿透弄好,就是將公網Ip某個端口的流量轉發到本地的某個端口
1. Termius 端口轉發
Termius文檔-Local, Remote, and Dynamic Forwarding
玩轉SSH端口轉發
通過終端命令設置端口轉發
如何刪除ssh轉發的端口
Termius不是有 port Forwarding 功能嘛,而且有 Local、Remote、Dynamic 三種模式,將遠端流量轉發到本地選擇 Remote
查看設置
2. 搭建 FRP 服務
由於服務端是arm架構的樹莓派,本地是m1 mac
進入frp github,服務端選擇 linux-arm64 的 frps,客戶端選擇 darwin-arm64 的 frpc(雖然一種包里面server和client都包含了)
修改服務端的 frps.ini
[common]
bind_port = 12345
修改本地的 frpc.ini
[common]
server_addr = tongchen.dynv6.net
server_port = 12345 # 監聽端口
[AnimaGAN Service] # 名字可以隨便取
type = tcp
local_ip = 127.0.0.1
local_port = 8080 # 要映射端口
remote_port = 8080 # 要映射端口
其他的設置,管理頁面、開機自啟等暫時不用,詳見 搭建屬於自己的FRP內網穿透、在Ubuntu 18.04上安裝frp
啟動服務端 ./frps -c frps.ini
啟動客戶端 ./frpc -c frpc.ini
總之,現在訪問 http://tongchen.dynv6.net:8080/ 等同於訪問我本地的 http://127.0.0.1:8080
運行 app.py
直接運行 python app.py,顯然沒問題
但是這樣簡單運行的話,只要按一下 ctrl + c 終止運行,或者關掉終端,網站就連接不了了,我們要尋求更長久的真正的部署。
1. Gunicorn + Gevent
運行以下命令即可安裝這兩個利器,可以異步同時處理多個請求
對於工作模式,默認是sync,即同步模式。這種模式就是說在調用的時候,必須等待調用返回結果后,決定后續的行為。而異步則是在調用這個job的時候,不用等待其執行結果,還可以執行其他job
pip install gunicorn gevent
在根目錄下新建文件 /gunicorn.conf.py
workers = 5 # 定義同時開啟的處理請求的進程數量,根據網站流量適當調整
worker_class = "gevent" # 采用gevent庫,支持異步處理請求,提高吞吐量
bind = "0.0.0.0:8080"
現在的啟動命令變成 gunicorn app:app -c gunicorn.conf.py
ps:
會有一個報錯,因為模型推理時間10s+
Gunicorn的日志里,有很多worker timeout error,Gunicorn worker timeout error
所以再加一個配置 timeout=600
於是就有比較漂亮的工作流啦

額外話:設置workers會開啟多線程處理,但是,瓶頸在內存,就算開啟5個線程也沒有足夠的內存同時運行5個線程

像這種情況,5個線程都gg,都不會得到響應
因為大一點的圖片,峰值內存會達到13G
2. 套一層nginx
按照上面的解釋,其實直接使用Gunicorn就完全可以實現外網訪問了,為什么非要加一層Nginx呢?
原因其實也很簡單,Nginx功能強大,用Nginx轉發Gunicorn服務,重點是解決“慢客戶端行為”給服務器帶來的性能降低問題;另外,在互聯網上部署HTTP服務時,還要考慮的“快客戶端響應”、SSL處理和高並發等問題,而這些問題在Nginx上一並能搞定,所以在Gunicorn服務之上加一層Nginx反向代理,是個一舉多得的部署方案。那為什么需要Nginx轉發Gunicorn服務?

在M1 Mac上安裝nginx,直接用brew,Mac M1 安裝Nginx
接下來就是配置了,nginx的默認配置文件在 /opt/homebrew/etc/nginx(可以用brew info nginx查看),修改 nginx.conf 配置文件
server {
listen 8090; `// Nginx需要監聽的接口`
server_name localhost;
location /{
proxy_pass http://127.0.0.1:8080; // 反向代理
}
}
監聽端口設為8090,是因為80被占了,如果設置成80,訪問的時候都不用加端口號了
然后執行以下命令重啟nginx:sudo nginx -s reload
3. 使用 Docker 封裝 Flask 應用
待填坑
python上手實踐 -- docker+nginx+gunicorn+flask項目部署
完善網頁UI
主要是增加"友情提醒"
點擊查看代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AnimeGAN Demo</title>
<style>
.warning{
line-height: 5px;
font-size: 13px;
color: #f44336;
}/* css 注釋說明:設置行距行高22px */
</style>
</head>
<body>
<h1>AnimeGAN: 今天out of memory了嗎</h1>
<div class="warning">
<p>友情提示:</p>
<p>1. 不要傳澀圖,上傳的圖片都會保存的</p>
<p>2. 圖片越大,生成時間越長,請耐心等待</p>
</div>
<form action="./upload" enctype='multipart/form-data' method='POST'>
<input type="file" name="file" style="margin-top:20px;"/>
<br>
<i>請輸入你當前的心情(開心、超開心、超超開心):</i>
<input type="text" class="txt_input" name="name" value="超超開心" style="margin-top:10px;"/>
<input type="submit" value="上傳" class="button-new" style="margin-top:15px;"/>
</form>
</body>
</html>
點擊查看UI
終極Bug
離譜,本地沒問題,轉發的會在推理的過程過網頁掛掉:

調了一上午,各種日志,frp、gunicron、chrome dev的日志都是正常的,就不知道為啥會掛掉,又為啥直接訪問localhost就行呢......
去實驗室問師兄,好家伙,它的瀏覽器可以!!
然后給小伙伴試了一下,有的可以,有的不行,,,說明是瀏覽器的問題,,但是我測試的時候localhost和遠端是用同一個瀏覽器
總之,跑路吧
別跑了, 破案了,梯子的原因,把梯子推掉就行了
怎么發現的呢?
我本地可以,用鏈接不行
用鏈接部分朋友可以,部分朋友不可以,不可以的朋友都經常使用tz
測試一下~~真的梯子的原因
我之前本地可以是因為本地的流量沒有走梯子
List To do
- 支持網頁端選擇模型
- 嘗試用ajax從服務端獲取數據,從而可能能解決終極Bug:哎呀不用了,但是還是可以進一步改善獲取數據的方式
