近期工作上在 node.js 服務上,多開了一個 python api 服務做整合應用,目前先試著混合架構來擠擠機器資源而不是 micorservice 架構。
實作就是 Nginx 擋在前面,接著有些 requests 交給 node.js 運作,有些 requests 交給 python api 服務,整體上就是透過 Proxy Pass 架構:
$ cat /etc/nginx/conf.d/service.conf | grep locationlocation / {location /node/ { rewrite ^/node/(.*)$ /$1 break; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; proxy_http_version 1.1; proxy_read_timeout 60; proxy_pass http://localhost:3000; }location /python/ { rewrite ^/python/(.*)$ /$1 break; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; proxy_http_version 1.1; proxy_read_timeout 60; proxy_pass http://unix:/var/run/service-py.sock; }
其中 node.js 是跑在 3000 port 服務,而 python api 跑在 unix:/var/run/service-py.sock ,上述 Nginx 設定檔剛好可以作為筆記,屬於兩種不同的設計方式,此外,這邊收到 requests 導向到 node.js 或 python api 時,都會刻意再去掉一些 prefix ,讓後面的服務開發比較多彈性。
回到 python api ,此次採用 Flask framework,他的運行很簡單:
```% cat app.py...if __name__ == '__main__':app.run(host='localhost', port=3001)```
直接執行法:
% python3 app.py* Serving Flask app 'app' (lazy loading)* Environment: productionWARNING: This is a development server. Do not use it in a production deployment.Use a production WSGI server instead.* Debug mode: offWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.* Running on http://localhost:3001Press CTRL+C to quit
使用 Flask 指令執行:
$ FLASK_APP=app.py flask run --host 0.0.0.0 --port 3001* Serving Flask app 'app.py' (lazy loading)* Environment: productionWARNING: This is a development server. Do not use it in a production deployment.Use a production WSGI server instead.* Debug mode: offWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.* Running on all addresses (0.0.0.0)* Running on http://127.0.0.1:3001* Running on http://x.x.x.x:3001Press CTRL+C to quit
最後則是為了穩定性,採用 Nginx + WSGI 整合方式,透過 Gunicorn 來工作:
$ cat wsgi.pyfrom app import appif __name__ == "__main__":app.run()$ sudo gunicorn --workers 4 --bind unix:/var/run/service-py.sock -m 777 wsgi:app[2024-08-07] [1701223] [INFO] Starting gunicorn 20.0.4[2024-08-07] [1701223] [INFO] Listening at: unix:/var/run/service-py.sock (1701223)[2024-08-07] [1701223] [INFO] Using worker: sync[2024-08-07] [1701225] [INFO] Booting worker with pid: 1701225[2024-08-07] [1701226] [INFO] Booting worker with pid: 1701226[2024-08-07] [1701227] [INFO] Booting worker with pid: 1701227[2024-08-07] [1701228] [INFO] Booting worker with pid: 1701228
如果要把運行也包裝系統指令方便處理,就只需:
$ cat /etc/systemd/system/my-py.service[Unit]Description=my-py-serviceAfter=network.target[Service]Type=simpleUser=rootWorkingDirectory=/path/project#ExecStart=/usr/bin/python3 app.py#Environment=FLASK_APP=app.py#ExecStart=/usr/bin/python3 -m flask run --port 3001 --host 0.0.0.0ExecStart=/usr/bin/gunicorn --workers 4 --bind unix:/var/run/service-py.sock -m 777 wsgi:appRestart=on-failure[Install]WantedBy=multi-user.target
後續就可以透過以下方式管理:
$ sudo systemctl status my-py.service$ sudo systemctl stop my-py.service$ sudo systemctl start my-py.service$ sudo systemctl restart my-py.service
沒有留言:
張貼留言