python基于FastAPI實(shí)現(xiàn)一個(gè)簡(jiǎn)易的在線用戶統(tǒng)計(jì)功能
概述
這是一個(gè)基于Python的FastAPI框架實(shí)現(xiàn)的服務(wù),用于統(tǒng)計(jì)客戶端的心跳信息,并據(jù)此維護(hù)在線用戶列表以及記錄活躍用戶數(shù)。
功能特性
- 心跳接收:接受來(lái)自客戶端的心跳包,以更新客戶端的狀態(tài)。
- 在線用戶統(tǒng)計(jì):提供API接口來(lái)獲取當(dāng)前在線用戶的數(shù)量。
- 活躍用戶統(tǒng)計(jì):提供API接口來(lái)獲取最近指定天數(shù)內(nèi)活躍的用戶數(shù)量。
- 請(qǐng)求頻率限制:對(duì)每個(gè)IP地址實(shí)施每秒一次的請(qǐng)求頻率限制。
安裝與運(yùn)行
請(qǐng)確保已經(jīng)安裝了Python 3.10+。
克隆或下載項(xiàng)目源代碼到本地。
在項(xiàng)目根目錄下安裝所需的依賴庫(kù):
pip install fastapi uvicorn
運(yùn)行服務(wù):
python main.py
或者使用uvicorn命令直接運(yùn)行(假設(shè)文件名為main.py):
uvicorn main:app --reload --host 0.0.0.0 --port 8001
API 文檔
http://127.0.0.1:8001/docs

心跳接收
- URL:
/heartbeat - 方法:
POST - 描述: 接收客戶端發(fā)送的心跳信號(hào),并更新客戶端為在線狀態(tài)。
- 響應(yīng):
200 OK: 返回JSON格式的信息確認(rèn)收到心跳。429 Too Many Requests: 如果客戶端在1秒內(nèi)發(fā)送了多個(gè)請(qǐng)求。
獲取在線用戶數(shù)量
- URL:
/online_clients - 方法:
POST - 描述: 返回當(dāng)前在線的客戶端數(shù)量。
- 響應(yīng):
200 OK: 返回包含在線用戶數(shù)量的JSON對(duì)象。429 Too Many Requests: 請(qǐng)求過(guò)于頻繁。
獲取活躍用戶數(shù)量
- URL:
/total_users - 方法:
GET 或 POST - 參數(shù):
days(可選, 默認(rèn)值為7): 指定要查詢的天數(shù)。
- 描述: 返回最近幾天內(nèi)有活動(dòng)記錄的用戶數(shù)量。
- 響應(yīng):
200 OK: 返回包含活躍用戶數(shù)量和查詢天數(shù)的JSON對(duì)象。429 Too Many Requests: 請(qǐng)求過(guò)于頻繁。
數(shù)據(jù)存儲(chǔ)
所有客戶端的心跳時(shí)間戳將被持久化到一個(gè)JSON文件中,該文件位于服務(wù)啟動(dòng)時(shí)所在的目錄下的users_data.json。每次接收到新的心跳信號(hào)時(shí),都會(huì)更新此文件。
注意事項(xiàng)
- 本服務(wù)僅用于演示目的,實(shí)際生產(chǎn)環(huán)境中可能需要考慮更健壯的數(shù)據(jù)存儲(chǔ)解決方案、安全性增強(qiáng)措施等。
- 為了保護(hù)服務(wù)器免受濫用,已實(shí)施了基本的請(qǐng)求頻率限制。根據(jù)實(shí)際需求,可以調(diào)整這個(gè)限制。
- 服務(wù)默認(rèn)監(jiān)聽(tīng)在8001端口上,可以通過(guò)修改
uvicorn.run函數(shù)中的port參數(shù)來(lái)更改。
希望這份文檔能對(duì)你有所幫助!如果有任何問(wèn)題或需要進(jìn)一步的幫助,請(qǐng)隨時(shí)告訴我。
源碼 main.py
from fastapi import FastAPI, Request, Depends, HTTPException
from collections import defaultdict
from datetime import datetime, timedelta
import asyncio
import json
import os
app = FastAPI()
# 存儲(chǔ)客戶端的心跳數(shù)據(jù)
clients_last_heartbeat = defaultdict(datetime)
# 每個(gè)IP請(qǐng)求時(shí)間間隔限制為1秒
last_request_time = defaultdict(datetime)
# 在線客戶端統(tǒng)計(jì)
online_clients = set()
# 心跳超時(shí)時(shí)間設(shè)置為1分鐘
HEARTBEAT_TIMEOUT = timedelta(minutes=10)
# 用戶數(shù)據(jù)文件路徑
USER_DATA_FILE = "users_data.json"
# 加載用戶數(shù)據(jù)
def load_user_data():
if os.path.exists(USER_DATA_FILE):
with open(USER_DATA_FILE, "r") as f:
return json.load(f)
return {}
# 保存用戶數(shù)據(jù)
def save_user_data(data):
with open(USER_DATA_FILE, "w") as f:
json.dump(data, f)
# 初始化用戶數(shù)據(jù)
all_users = load_user_data()
@app.on_event("startup")
async def startup_event():
# 啟動(dòng)后臺(tái)任務(wù),每1分鐘檢查一次在線設(shè)備
asyncio.create_task(remove_offline_clients())
async def remove_offline_clients():
"""
定時(shí)任務(wù):移除超過(guò)心跳超時(shí)時(shí)間未發(fā)送心跳的客戶端
"""
while True:
await asyncio.sleep(HEARTBEAT_TIMEOUT.total_seconds())
now = datetime.utcnow()
# 找出超過(guò)超時(shí)時(shí)間未發(fā)送心跳的設(shè)備,并將其從在線列表中移除
offline_clients = {ip for ip, last_heartbeat in clients_last_heartbeat.items()
if now - last_heartbeat > HEARTBEAT_TIMEOUT}
# 從在線設(shè)備中移除離線的客戶端
for client in offline_clients:
online_clients.discard(client)
del clients_last_heartbeat[client] # 刪除心跳記錄
print(f"清除離線客戶端, 當(dāng)前在線客戶端數(shù)量: {len(online_clients)}")
# 請(qǐng)求頻率限制,1秒內(nèi)只能請(qǐng)求一次
def request_limit(request: Request):
client_ip = request.client.host
now = datetime.utcnow()
if client_ip in last_request_time and (now - last_request_time[client_ip]).total_seconds() < 1:
raise HTTPException(status_code=429, detail="Too Many Requests")
last_request_time[client_ip] = now
@app.post("/heartbeat")
async def receive_heartbeat(request: Request, limit: None = Depends(request_limit)):
"""
接受客戶端的心跳包
"""
client_ip = request.client.host
now = datetime.utcnow()
# 更新心跳時(shí)間并將客戶端標(biāo)記為在線
clients_last_heartbeat[client_ip] = now
online_clients.add(client_ip)
# 更新所有用戶數(shù)據(jù)并保存到文件
all_users[client_ip] = now.isoformat()
save_user_data(all_users)
return {"message": "Heartbeat received", "ip": client_ip}
@app.get("/online_clients")
async def get_online_clients(request: Request, limit: None = Depends(request_limit)):
"""
獲取當(dāng)前在線客戶端數(shù)量
"""
return {"online_clients_count": len(online_clients)}
@app.post("/online_clients")
async def get_online_clients2(request: Request, limit: None = Depends(request_limit)):
"""
獲取當(dāng)前在線客戶端數(shù)量
"""
return {"online_clients_count": len(online_clients)}
@app.get("/total_users")
async def get_total_users(days: int = 7, request: Request = None, limit: None = Depends(request_limit)):
"""
獲取最近n天活躍的用戶數(shù)
"""
now = datetime.utcnow()
cutoff_date = now - timedelta(days=days)
# 篩選最近n天活躍的用戶
recent_users_count = sum(
1 for last_seen in all_users.values()
if datetime.fromisoformat(last_seen) >= cutoff_date
)
return {"recent_users_count": recent_users_count, "days": days}
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8001)
到此這篇關(guān)于python基于FastAPI實(shí)現(xiàn)一個(gè)簡(jiǎn)易的在線用戶統(tǒng)計(jì)功能的文章就介紹到這了,更多相關(guān)python統(tǒng)計(jì)在線用戶內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python+PyQt5設(shè)計(jì)實(shí)現(xiàn)一個(gè)C++源代碼行數(shù)統(tǒng)計(jì)工具
- 從入門到實(shí)戰(zhàn)詳解Python數(shù)據(jù)統(tǒng)計(jì)的完全指南
- 基于Python制作一個(gè)詞頻統(tǒng)計(jì)工具的完整指南
- Python+Qt實(shí)現(xiàn)智能應(yīng)用時(shí)長(zhǎng)統(tǒng)計(jì)工具
- 基于Python開(kāi)發(fā)圖片文件信息統(tǒng)計(jì)工具
- 使用Python統(tǒng)計(jì)網(wǎng)站訪問(wèn)流量
- Python字符串查找和統(tǒng)計(jì)方法詳解
相關(guān)文章
Python concurrent.futures模塊使用實(shí)例
這篇文章主要介紹了Python concurrent.futures模塊使用實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
PyPDF2讀取PDF文件內(nèi)容保存到本地TXT實(shí)例
這篇文章主要介紹了PyPDF2讀取PDF文件內(nèi)容保存到本地TXT實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
python算法測(cè)試結(jié)果自動(dòng)保存到excel表格的實(shí)現(xiàn)步驟
我們?cè)谶M(jìn)行算法評(píng)估是通常會(huì)針對(duì)每個(gè)樣本的算法處理結(jié)果進(jìn)行統(tǒng)計(jì),例如每個(gè)樣本正確預(yù)測(cè)數(shù)量、漏檢數(shù)量和誤檢數(shù)量、精度等,本文小編將給大家介紹python算法測(cè)試結(jié)果自動(dòng)保存到excel表格的實(shí)現(xiàn)步驟,感興趣的朋友可以參考下2023-12-12
Python中isnumeric()方法的使用簡(jiǎn)介
這篇文章主要介紹了Python中isnumeric()方法的使用,isnumeric()方法的使用是Python入門中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-05-05
Django在Win7下的安裝及創(chuàng)建項(xiàng)目hello word簡(jiǎn)明教程
這篇文章主要介紹了Django在Win7下的安裝及創(chuàng)建項(xiàng)目hello word,需要的朋友可以參考下2014-07-07
利用Python自動(dòng)化實(shí)現(xiàn)Excel單元格數(shù)據(jù)驗(yàn)證
在當(dāng)今數(shù)據(jù)驅(qū)動(dòng)的世界里,Excel作為最常用的數(shù)據(jù)處理工具之一,其數(shù)據(jù)質(zhì)量直接影響著決策的準(zhǔn)確性,本文將深入探討如何利用 Spire.XLS for Python 庫(kù),在Excel中設(shè)置各種復(fù)雜的數(shù)據(jù)驗(yàn)證規(guī)則,需要的小伙伴可以了解下2025-09-09

