年初被迫接受了一個開發任務,自己從來沒做過產品及開發只能硬著頭皮上。一邊百度一邊 AI,終於最近有了些進展。隨手記一下學到的知識點,比較細碎,記下來或許有用。
專案#
被安排的是開發一個網站可用性監測引擎。別的語言都不太擅長所以選用了 python。py 裡自己最熟悉的框架又是 flask,所以便從這裡開始。
python 的 post 數據#
flask 和很多 py 框架都有一些 “反人類”(也有可能是反我)的寫法。
比如寫一個路由
@app.post("/test/api/add")
def ch(request: Request):
pass
比如這樣寫才能拿到 post 數據,普通訪問只能 get。
並發#
剛開始寫的時候只告訴我是個模塊,後來又說是引擎,漸漸的越來越大,都快變成我一個人開發一個產品。
這個時候才知道我這個引擎到後面要接受整個公司所有專案的監測任務,目標保守估計幾千個。大致估算了下並發估計能有 300 左右。
於是想到 flask 有沒有可能扛不住這麼大的並發,查一查到底怎麼樣。
於是查到 flask 是個開發引擎,不建議在生產環境使用。我尋思應該也是指高並發問題。然後又查到 fastapi 適合高並發場景,並且更適合作為 api “引擎”。就決定切換為 fastapi。
- 單純的切換到 fastapi 其實起不到優化效果,需要將函數加上 async 關鍵詞,使用異步才能優化。
- 接受數據的時候需要加 await 關鍵詞,要不然會接受不到數據,不知道為什麼。這個還要學習
- 所有函數都要加上 async,否則不但不優化,反而還有負優化
- 使用 fastapi 時需要另外安裝 web 服務器,官方建議安裝 uvicorn,但是在安裝的時候是 uvicorn [xxxx] 的形式。這種格式表示安裝 uvicorn 以及依賴。
- 使用異步時就不能再使用 requests 了,它不支持異步請求,我換了 aiohttp
- 也是最重要的一點。實測,fastapi 對並發優化其實和 flask 效果差不出太多
檢測請求#
上游服務器給我任務,然後我要去監測。
所謂的監測就是 get 推送過來的 url。這裡也有幾個知識點
- 請求最好帶上 UA 之類的東西,類似於爬蟲的那些策略,防止被反爬系統干擾
- 監測網站時最好使用 GET 方法,有些網站限制了方法。我想過用 HEAD 但是產生了誤報,推測可能是中間件或者安全設備配置的策略
- 當請求一個網站返回 200 時不一定就真的代表網站可訪問,需要判斷一下返回包的大小進一步確定。
- 超時時間長一點,有時候目標網絡確實爛,也有時候請求過多我們自己的網絡層會阻塞
- 奇怪的網絡架構。舉個例子,政府機構網站。縣區級單位很多會選擇把網站掛靠到上級的主機上。雖然一名不一樣但是指向了一個主機。當對這個市區進行監測時在主機端看來我是高頻請求,類 DDOS,所以就會直接拉黑。唯一的辦法就是使用代理池,每個請求換一個代理。
整體架構#
最開始我想的只是寫一個腳本了事,腳本不過幾 K 大小。漸漸的我發現整個架構需要改變。
首先公司沒有給我配代理池,只給了一個高頻撥號服務器和一個公司出口服務器。所以我想盡量利用這兩個機器,於是決定使用負載均衡。
其實之前只是一直聽說並沒有實際用過。畢竟我的主要工作是怎麼打進去,至於負載均衡,只是多讓我拿下一個權限而已。
負載均衡#
仔細學習了學習,發現負載均衡其實還是反代為基礎。通過反代服務器進行請求轉發。看了下和很久以前寫的文章
初探单域名单端口多服务 web
很像。
那篇文章是說按照後綴轉發到不同服務器,負載均衡則是按照某種算法進行轉發。
以前我還以為是有什麼專業的服務組件去完成,如果是反代為基礎,那麼 nginx 自然是最好用的。
配置文件大概是這麼寫的
worker_processes 4; //工作進程數,一般和主機核數相同
events {
worker_connections 40960;//每個進程可跑的線程數,我這比較大因為直接用了phpstudy的參數
}
http {
upstream web { //負載節點
server 192.168.1.2:8000;
server 192.168.1.3:8000;
}
server {
listen 80;//反代服務器監聽端口
location / {
proxy_pass http://web;//指定節點列表,這裡的web就是upstream web中的web。平時這裡是一個正常的url
}
}
}
docker 學習#
既然都這樣了,單獨在服務器上裝一個 nginx 還挺麻煩的。所以我想到了 docker。以前用 docker 都是在使用別人的東西的時候按著人家給的命令執行,自己就知道一個docker ps
和docker images
這次自己換了方向,從使用者變成了開發者,於是學到了一些東西。
服務器系統是 centos7, yum install docker
然後還要安裝 docker-compose(我終於記住這個單詞了)
神奇的是 centos7 無法用 yum 直接安裝,而是用 pip 進行 docker-compose 的安裝。但是實測安裝完成以後無法使用,可能是其他什麼問題。於是按照官方文檔直接用 wget 拉取了一個可執行文件。
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose.yaml#
也學了學 docker-compose.yaml 的規則。畢竟節點架構就不能再用 sqlite 了。也得部署 mysql,兩組件加起來還是用 docker-compose 一鍵配置簡單
version: '3'
services:
nginx:
image: nginx //鏡像名
ports:
- "19100:80" //物理機端口:容器內服務端口
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro //文件覆蓋到容器內
db:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: web
ports:
- "3306:3306"
volumes:
- ./web.sql:/docker-entrypoint-initdb.d/web.sql //docker-entrypoint-initdb.d下的sql文件會自動導入到數據庫
好了,暫時就想到了這些。遇到了很多問題,也學到了很多。果然應了那句話:你所承受的磨難終將成為日後的資本
寫的有點對瀏覽器開始卡了,就這樣吧。有哪些問題各位師傅請積極評論督促我進步學習。
最後其實還有一個問題,監測會有誤報。把可用目標報成宕機,不知道為什麼。同一個目標 py 腳本測不可用,curl 和 httpx 工具測都正常,想不通為什麼。往大佬們指點。