python 基于FastAPI实现一个简易的在线用户统计 服务
简易在线用户统计服务
概述
这是一个基于Python的FastAPI框架实现的服务,用于统计客户端的心跳信息,并据此维护在线用户列表以及记录活跃用户数。
功能特性
- 心跳接收:接受来自客户端的心跳包,以更新客户端的状态。
- 在线用户统计:提供API接口来获取当前在线用户的数量。
- 活跃用户统计:提供API接口来获取最近指定天数内活跃的用户数量。
- 请求频率限制:对每个IP地址实施每秒一次的请求频率限制。
安装与运行
- 请确保已经安装了Python 3.10+。
- 克隆或下载项目源代码到本地。
- 在项目根目录下安装所需的依赖库:
pip install fastapi uvicorn - 运行服务:
或者使用python main.pyuvicorn命令直接运行(假设文件名为main.py):uvicorn main:app --reload --host 0.0.0.0 --port 8001
API 文档
http://127.0.0.1:8001/docs

心跳接收
- URL:
/heartbeat - 方法:
POST - 描述: 接收客户端发送的心跳信号,并更新客户端为在线状态。
- 响应:
200 OK: 返回JSON格式的信息确认收到心跳。429 Too Many Requests: 如果客户端在1秒内发送了多个请求。
获取在线用户数量
- URL:
/online_clients - 方法:
POST - 描述: 返回当前在线的客户端数量。
- 响应:
200 OK: 返回包含在线用户数量的JSON对象。429 Too Many Requests: 请求过于频繁。
获取活跃用户数量
- URL:
/total_users - 方法:
GET 或 POST - 参数:
days(可选, 默认值为7): 指定要查询的天数。
- 描述: 返回最近几天内有活动记录的用户数量。
- 响应:
200 OK: 返回包含活跃用户数量和查询天数的JSON对象。429 Too Many Requests: 请求过于频繁。
数据存储
所有客户端的心跳时间戳将被持久化到一个JSON文件中,该文件位于服务启动时所在的目录下的users_data.json。每次接收到新的心跳信号时,都会更新此文件。
注意事项
- 本服务仅用于演示目的,实际生产环境中可能需要考虑更健壮的数据存储解决方案、安全性增强措施等。
- 为了保护服务器免受滥用,已实施了基本的请求频率限制。根据实际需求,可以调整这个限制。
- 服务默认监听在8001端口上,可以通过修改
uvicorn.run函数中的port参数来更改。
希望这份文档能对你有所帮助!如果有任何问题或需要进一步的帮助,请随时告诉我。
源码 main.py
from fastapi import FastAPI, Request, Depends, HTTPException
from collections import defaultdict
from datetime import datetime, timedelta
import asyncio
import json
import osapp = 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.hostnow = 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.hostnow = datetime.utcnow()# 更新心跳时间并将客户端标记为在线clients_last_heartbeat[client_ip] = nowonline_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 uvicornuvicorn.run(app, host="0.0.0.0", port=8001)相关文章:
python 基于FastAPI实现一个简易的在线用户统计 服务
简易在线用户统计服务 概述 这是一个基于Python的FastAPI框架实现的服务,用于统计客户端的心跳信息,并据此维护在线用户列表以及记录活跃用户数。 功能特性 心跳接收:接受来自客户端的心跳包,以更新客户端的状态。在线用户统计…...
glibc中xdr的一个bug
本人在64位linux服务器上(centos7),发现xdr_u_long这个函数有个bug,就是数字的范围如果超过unsigned int的最大值(4294967295)时,xdr_u_long失败。 这个场景主要用在unix时间戳上面,比如一款软件,设置有效期为100年。…...
Android Framework定制sim卡插入解锁pin码的界面
文章目录 手机设置SIM卡pin码一、安卓手机二、苹果手机 Android Framework中SIM卡pin码代码定位pin码提示文本位置定位pin码java代码位置 定制pin码framework窗口数字按钮 手机设置SIM卡pin码 设置 SIM 卡 PIN 码可以提高手机的安全性,防止他人在未经授权的情况下使…...
cc2530 Basic RF 讲解 和点灯讲解(1_1)
1. Basic RF 概述 Basic RF 是 TI 提供的一套简化版的无线通信协议栈,旨在帮助开发者快速搭建无线通信系统。它基于 IEEE 802.15.4 标准的数据包收发,但只用于演示无线设备数据传输的基本方法,不包含完整功能的协议。Basic RF 的功能限制包括…...
Android H5页面性能分析策略
文章目录 引言一、拦截资源加载请求以优化性能二、通过JavaScript代码监控资源下载速度三、使用vConsole进行前端性能调试四、使用Chrome DevTools调试Android端五、通过抓包分析优化网络性能六、总结 引言 在移动应用开发中,H5页面的性能直接影响到用户体验。本文…...
【前端面试】Typescript
Typescript面试题目回答 Typescript有哪些常用类型? Typescript的常用类型包括: 基本类型:boolean(布尔类型)、number(数字类型)、string(字符串类型)。特殊类型:nul…...
程序语言的内存管理:垃圾回收GC(Java)、手动管理(C语言)与所有权机制(Rust)(手动内存管理、手动管理内存)
文章目录 程序语言的内存管理:垃圾回收、手动管理与所有权机制引言一、垃圾回收机制(GC)(Java)1. 什么是垃圾回收机制2. 垃圾回收的工作原理3. 优点与缺点4. 示例代码 二、手动管理内存的分配和释放(C语言&…...
研究生论文学习记录
文献检索 检索论文的网站 知网:找论文,寻找创新点paperswithcode :这个网站可以直接找到源代码 直接再谷歌学术搜索 格式:”期刊名称“ 关键词 在谷歌学术搜索特定期刊的关键词相关论文,可以使用以下几种方法&#…...
毕业设计选题:基于Django+Vue的图书馆管理系统
开发语言:Python框架:djangoPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 系统首页 图书馆界面 图书信息界面 个人中心界面 后台登录界面 管理员功能界面 用户…...
#网络安全#NGSOC与传统SOC的区别
NGSOC是Next Generation Security Operation Center(下一代安全运营中心)的缩写。 NGSOC安全运营服务基于态势感知与安全运营平台来开展监测分析等一系列的服务工作,旨在通过专业、高效的运营服务工作,帮助用户尽可能发挥NGSOC作…...
GCN+BiLSTM多特征输入时间序列预测(Pytorch)
目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GCNBiLSTM多特征输入时间序列预测(Pytorch) 可以做风电预测,光伏预测,寿命预测,浓度预测等。 Python代码,基于Pytorch编写 1.多特征输入单步预测…...
LinkedList和链表之刷题课(下)
1. 给定x根据x把链表分割,大的结点放在x后面,小的结点放在x前面 题目解析: 注意此时的pHead就是head(头节点的意思) 基本上就是给定一个链表,我们根据x的值来把这个链表分成俩部分,大的那部分放在x后面,小的那部分放在x前面,并且我们不能改变链表本来的顺序,比如下面的链表,我…...
ollama 在 Linux 环境的安装
ollama 在 Linux 环境的安装 介绍 他的存在在我看来跟 docker 的很是相似,他把市面上已经存在的大语言模型集合在一个仓库中,然后通过 ollama 的方式来管理这些大语言模型 下载 # 可以直接通过 http 的方式吧对应的 shell 脚本下载下来,然…...
C语言二刷指针篇
&取得变量的地址 printf("%p\n", &a); printf("%p\n", a); printf("%p\n", &a[0]); printf("%p\n", &a[1]); 前三个输出相同,a[0]和a[1]之间相差4 指针就是保存地址的变量,指针里放的是别的…...
LeetCode题练习与总结:回文对--336
一、题目描述 给定一个由唯一字符串构成的 0 索引 数组 words 。 回文对 是一对整数 (i, j) ,满足以下条件: 0 < i, j < words.length,i ! j ,并且words[i] words[j](两个字符串的连接)是一个回文…...
CesiumJS 案例 P7:添加指定长宽的图片图层(原点分别为图片图层的中心点、左上角顶点、右上角顶点、左下角顶点、右下角顶点)
CesiumJS CesiumJS API:https://cesium.com/learn/cesiumjs/ref-doc/index.html CesiumJS 是一个开源的 JavaScript 库,它用于在网页中创建和控制 3D 地球仪(地图) 一、添加指定长宽的图片图层(原点为图片图层的中心…...
Redis 主从同步 问题
前言 相关系列 《Redis & 目录》(持续更新)《Redis & 主从同步 & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Redis & 主从同步 & 总结》(学习总结/最新最准/持续更新)《Redis &a…...
【SQL Server】探讨 IN 和 EXISTS之间的区别
前言 在使用 SQL 查询相关表数据时,通常需要根据另一个表中的值来筛选数据。而 IN 与 EXISTS 子句都是用于此场景的常用方式,但使用时两者存在工作方式不同。它们使用上的选择会显著影响查询的性能,尤其是在大型数据集中。本文我们一起探讨 IN 和 EXISTS 之间的区别、使用与…...
清理pip和conda缓存
当用户目录没有空间时,可清理pip和conda缓存 清理conda缓存: conda clean --all清理pip缓存: pip cache purgeNote: 可以利用软链接,将用户目录下的文件链接到其他位置 首先移动文件或文件夹到其他位置 mv ~/test /…...
git rebase和merge的区别
Git merge和Git rebase是两种不同的合并策略,它们在处理分支合并时有各自的优点和缺点。 Git fetch git fetch 命令用于从远程仓库获取最新的更改,但不会自动合并这些更改到你的本地分支。它会下载远程仓库的所有分支和标签,并更新你的本地…...
ABAQUS三维多孔材料建模:自定义与多软件导出
ABAQUS三维多孔材料,可生成实体多孔材料空隙连接或六面体网格映射模型。 可自定义参数包括基体长宽高,骨料半径范围,体积比以及网格的尺寸。 可导出到comsol ansys cad等。最近在研究ABAQUS三维多孔材料建模,发现了一些超有趣的功…...
Stable Diffusion显存不够?5个你没想到的省显存技巧(实测可跑24GB模型)
Stable Diffusion显存优化实战:5个突破性技巧释放GPU潜力 当你在深夜赶制商业项目,Stable Diffusion突然弹出"CUDA out of memory"的红色警告,那种绝望感每个AI创作者都懂。我曾在RTX 4090上加载24GB的动漫风格模型时,发…...
通义千问3-VL-Reranker-8B在电商搜索中的惊艳效果展示
通义千问3-VL-Reranker-8B在电商搜索中的惊艳效果展示 1. 多模态重排序如何改变电商搜索体验 电商平台的搜索功能正面临前所未有的挑战。当用户输入"白色连衣裙 夏季 透气"时,传统搜索引擎只能基于文本匹配返回结果,无法理解"透气"…...
从SPP到ASPP:一文读懂语义分割中的多尺度特征提取技术
从SPP到ASPP:解码语义分割中的多尺度特征提取技术演进 在计算机视觉领域,语义分割任务要求模型对图像中的每个像素进行分类,这需要算法能够同时理解局部细节和全局上下文。传统卷积神经网络(CNN)在处理这一挑战时面临一个根本性矛盾ÿ…...
佣金乱、订单乱?换推客系统立刻理顺
做分销、带推客,最头疼的不是没人卖,而是账乱、单乱、人心乱。订单对不上、佣金算不准、退款没回冲、归属说不清,每天都在扯皮、对账、解释,生意越做越心累。其实问题根本不在人,而在系统。佣金乱、订单乱?…...
文档转换自动化:Word to Markdown全流程实战指南
文档转换自动化:Word to Markdown全流程实战指南 【免费下载链接】word-to-markdown A ruby gem to liberate content from Microsoft Word documents 项目地址: https://gitcode.com/gh_mirrors/wo/word-to-markdown 在数字化内容管理中,文档转换…...
仅限内部技术团队流通的Dify异步接入SOP(含安全审计清单+可观测性埋点规范)
第一章:Dify 自定义节点异步处理如何实现快速接入在 Dify v1.0 版本中,自定义节点(Custom Node)支持通过 Webhook 或本地 Python 函数方式扩展业务逻辑。当节点需执行耗时操作(如大模型微调、外部 API 调用、文件批量处…...
vSphere集群运维实录:我是如何用DRS规则搞定‘主备分离’和‘亲密无间’的
vSphere集群运维实战:DRS规则在复杂业务架构中的高阶应用 去年夏天,我们团队接手了一个金融系统的虚拟化迁移项目。这套系统包含12台域控制器、8组MySQL主从集群和超过30个Web应用节点,全部运行在由24台ESXi主机组成的vSphere集群上。当第一次…...
Zabbix虚拟机安装避坑指南:从镜像下载到控制台访问的全流程解析
Zabbix虚拟机安装实战:7个关键环节深度解析与典型问题解决方案 第一次接触Zabbix监控系统的技术人员,往往会在虚拟机安装环节遇到各种"坑"。本文将以问题导向的视角,带你拆解从镜像下载到控制台访问的全流程,重点解决那…...
程序员面试别再死磕算法了!面试官真正想看的是这几点
文章目录开篇:刷题300道,面试5分钟挂,你中招了吗?算法是门票,但门票不能当饭吃面试官真正在偷看的五个隐藏考点1. 代码的"卫生习惯"比你想象的更重要2. 系统设计:别只会砌砖,要会盖楼…...
