it编程 > 前端脚本 > Python

python基于FastAPI实现一个简易的在线用户统计功能

10人参与 2025-10-24 Python

概述

这是一个基于python的fastapi框架实现的服务,用于统计客户端的心跳信息,并据此维护在线用户列表以及记录活跃用户数。

功能特性

安装与运行

请确保已经安装了python 3.10+。

克隆或下载项目源代码到本地。

在项目根目录下安装所需的依赖库:

pip install fastapi uvicorn

运行服务:

python main.py

或者使用uvicorn命令直接运行(假设文件名为main.py):

uvicorn main:app --reload --host 0.0.0.0 --port 8001

api 文档

http://127.0.0.1:8001/docs

心跳接收

获取在线用户数量

获取活跃用户数量

数据存储

所有客户端的心跳时间戳将被持久化到一个json文件中,该文件位于服务启动时所在的目录下的users_data.json。每次接收到新的心跳信号时,都会更新此文件。

注意事项

希望这份文档能对你有所帮助!如果有任何问题或需要进一步的帮助,请随时告诉我。

源码 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()

# 存储客户端的心跳数据
clients_last_heartbeat = defaultdict(datetime)

# 每个ip请求时间间隔限制为1秒
last_request_time = defaultdict(datetime)

# 在线客户端统计
online_clients = set()

# 心跳超时时间设置为1分钟
heartbeat_timeout = timedelta(minutes=10)

# 用户数据文件路径
user_data_file = "users_data.json"

# 加载用户数据
def load_user_data():
    if os.path.exists(user_data_file):
        with open(user_data_file, "r") as f:
            return json.load(f)
    return {}

# 保存用户数据
def save_user_data(data):
    with open(user_data_file, "w") as f:
        json.dump(data, f)

# 初始化用户数据
all_users = load_user_data()

@app.on_event("startup")
async def startup_event():
    # 启动后台任务,每1分钟检查一次在线设备
    asyncio.create_task(remove_offline_clients())

async def remove_offline_clients():
    """
    定时任务:移除超过心跳超时时间未发送心跳的客户端
    """
    while true:
        await asyncio.sleep(heartbeat_timeout.total_seconds())
        now = datetime.utcnow()
        # 找出超过超时时间未发送心跳的设备,并将其从在线列表中移除
        offline_clients = {ip for ip, last_heartbeat in clients_last_heartbeat.items()
                           if now - last_heartbeat > heartbeat_timeout}
        
        # 从在线设备中移除离线的客户端
        for client in offline_clients:
            online_clients.discard(client)
            del clients_last_heartbeat[client]  # 删除心跳记录

        print(f"清除离线客户端, 当前在线客户端数量: {len(online_clients)}")

# 请求频率限制,1秒内只能请求一次
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()
    # 更新心跳时间并将客户端标记为在线
    clients_last_heartbeat[client_ip] = now
    online_clients.add(client_ip)
    
    # 更新所有用户数据并保存到文件
    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)):
    """
    获取当前在线客户端数量
    """
    return {"online_clients_count": len(online_clients)}

@app.post("/online_clients")
async def get_online_clients2(request: request, limit: none = depends(request_limit)):
    """
    获取当前在线客户端数量
    """
    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天活跃的用户数
    """
    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)


到此这篇关于python基于fastapi实现一个简易的在线用户统计功能的文章就介绍到这了,更多相关python统计在线用户内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

您想发表意见!!点此发布评论

推荐阅读

Python爬虫抓取豆瓣TOP250数据从分析到实践的全过程(详细图解)

10-25

Python实现半角数字转全角数字的完整方法

10-26

Python利用正则表达式将英文双引号替换为中文双引号

10-26

Python实现把一个文件夹下所有的文件名和绝对路径存入execl表格

10-26

python实现发送图片到打印机进行打印

10-26

Python+PyQt5打造一个代码行数统计工具

10-26

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论