AnimeGAN+Flask部署過程


本地加載預訓練模型並進行推理,測試通過。想將其打包成網頁應用並對外展示。
hk的朋友有一個帶有公網ip的樹莓派服務器,開始嘗試

Try 樹莓派

配置環境

安裝conda

安裝conda,下載linux版格式不對,改成aarch64,還是報錯,"Illegal instruction"
換成Miniforge 樹莓派安裝Python3.8 64bit
然后 conda create -n deeplearning python=3.8 創建一個虛擬環境

安裝pytorch

樹莓派上只能編譯安裝

安裝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 功能嘛,而且有 LocalRemoteDynamic 三種模式,將遠端流量轉發到本地選擇 Remote

查看設置
奇怪的是竟然沒有轉發成功,,現在想來應該是8080端口被之前的程序占用了,應該先 kill 掉 Note: ``` netstat -anp | grep 8080 ```

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 應用

待填坑

1 小時上線之用 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:哎呀不用了,但是還是可以進一步改善獲取數據的方式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM