当前位置: 首页 > news >正文

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

简易在线用户统计服务

概述

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

功能特性

  • 心跳接收:接受来自客户端的心跳包,以更新客户端的状态。
  • 在线用户统计:提供API接口来获取当前在线用户的数量。
  • 活跃用户统计:提供API接口来获取最近指定天数内活跃的用户数量。
  • 请求频率限制:对每个IP地址实施每秒一次的请求频率限制。

安装与运行

  1. 请确保已经安装了Python 3.10+。
  2. 克隆或下载项目源代码到本地。
  3. 在项目根目录下安装所需的依赖库:
    pip install fastapi uvicorn
    
  4. 运行服务:
    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

在这里插入图片描述

心跳接收

  • 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框架实现的服务&#xff0c;用于统计客户端的心跳信息&#xff0c;并据此维护在线用户列表以及记录活跃用户数。 功能特性 心跳接收&#xff1a;接受来自客户端的心跳包&#xff0c;以更新客户端的状态。在线用户统计…...

glibc中xdr的一个bug

本人在64位linux服务器上(centos7)&#xff0c;发现xdr_u_long这个函数有个bug&#xff0c;就是数字的范围如果超过unsigned int的最大值(4294967295)时&#xff0c;xdr_u_long失败。 这个场景主要用在unix时间戳上面&#xff0c;比如一款软件&#xff0c;设置有效期为100年。…...

Android Framework定制sim卡插入解锁pin码的界面

文章目录 手机设置SIM卡pin码一、安卓手机二、苹果手机 Android Framework中SIM卡pin码代码定位pin码提示文本位置定位pin码java代码位置 定制pin码framework窗口数字按钮 手机设置SIM卡pin码 设置 SIM 卡 PIN 码可以提高手机的安全性&#xff0c;防止他人在未经授权的情况下使…...

cc2530 Basic RF 讲解 和点灯讲解(1_1)

1. Basic RF 概述 Basic RF 是 TI 提供的一套简化版的无线通信协议栈&#xff0c;旨在帮助开发者快速搭建无线通信系统。它基于 IEEE 802.15.4 标准的数据包收发&#xff0c;但只用于演示无线设备数据传输的基本方法&#xff0c;不包含完整功能的协议。Basic RF 的功能限制包括…...

Android H5页面性能分析策略

文章目录 引言一、拦截资源加载请求以优化性能二、通过JavaScript代码监控资源下载速度三、使用vConsole进行前端性能调试四、使用Chrome DevTools调试Android端五、通过抓包分析优化网络性能六、总结 引言 在移动应用开发中&#xff0c;H5页面的性能直接影响到用户体验。本文…...

【前端面试】Typescript

Typescript面试题目回答 Typescript有哪些常用类型? Typescript的常用类型包括&#xff1a; 基本类型&#xff1a;boolean&#xff08;布尔类型&#xff09;、number&#xff08;数字类型&#xff09;、string&#xff08;字符串类型&#xff09;。特殊类型&#xff1a;nul…...

程序语言的内存管理:垃圾回收GC(Java)、手动管理(C语言)与所有权机制(Rust)(手动内存管理、手动管理内存)

文章目录 程序语言的内存管理&#xff1a;垃圾回收、手动管理与所有权机制引言一、垃圾回收机制&#xff08;GC&#xff09;&#xff08;Java&#xff09;1. 什么是垃圾回收机制2. 垃圾回收的工作原理3. 优点与缺点4. 示例代码 二、手动管理内存的分配和释放&#xff08;C语言&…...

研究生论文学习记录

文献检索 检索论文的网站 知网&#xff1a;找论文&#xff0c;寻找创新点paperswithcode &#xff1a;这个网站可以直接找到源代码 直接再谷歌学术搜索 格式&#xff1a;”期刊名称“ 关键词 在谷歌学术搜索特定期刊的关键词相关论文&#xff0c;可以使用以下几种方法&#…...

毕业设计选题:基于Django+Vue的图书馆管理系统

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 系统首页 图书馆界面 图书信息界面 个人中心界面 后台登录界面 管理员功能界面 用户…...

#网络安全#NGSOC与传统SOC的区别

NGSOC是Next Generation Security Operation Center&#xff08;下一代安全运营中心&#xff09;的缩写。 NGSOC安全运营服务基于态势感知与安全运营平台来开展监测分析等一系列的服务工作&#xff0c;旨在通过专业、高效的运营服务工作&#xff0c;帮助用户尽可能发挥NGSOC作…...

GCN+BiLSTM多特征输入时间序列预测(Pytorch)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GCNBiLSTM多特征输入时间序列预测&#xff08;Pytorch&#xff09; 可以做风电预测&#xff0c;光伏预测&#xff0c;寿命预测&#xff0c;浓度预测等。 Python代码&#xff0c;基于Pytorch编写 1.多特征输入单步预测…...

LinkedList和链表之刷题课(下)

1. 给定x根据x把链表分割,大的结点放在x后面,小的结点放在x前面 题目解析: 注意此时的pHead就是head(头节点的意思) 基本上就是给定一个链表,我们根据x的值来把这个链表分成俩部分,大的那部分放在x后面,小的那部分放在x前面,并且我们不能改变链表本来的顺序,比如下面的链表,我…...

ollama 在 Linux 环境的安装

ollama 在 Linux 环境的安装 介绍 他的存在在我看来跟 docker 的很是相似&#xff0c;他把市面上已经存在的大语言模型集合在一个仓库中&#xff0c;然后通过 ollama 的方式来管理这些大语言模型 下载 # 可以直接通过 http 的方式吧对应的 shell 脚本下载下来&#xff0c;然…...

C语言二刷指针篇

&取得变量的地址 printf("%p\n", &a); printf("%p\n", a); printf("%p\n", &a[0]); printf("%p\n", &a[1]); 前三个输出相同&#xff0c;a[0]和a[1]之间相差4 指针就是保存地址的变量&#xff0c;指针里放的是别的…...

LeetCode题练习与总结:回文对--336

一、题目描述 给定一个由唯一字符串构成的 0 索引 数组 words 。 回文对 是一对整数 (i, j) &#xff0c;满足以下条件&#xff1a; 0 < i, j < words.length&#xff0c;i ! j &#xff0c;并且words[i] words[j]&#xff08;两个字符串的连接&#xff09;是一个回文…...

CesiumJS 案例 P7:添加指定长宽的图片图层(原点分别为图片图层的中心点、左上角顶点、右上角顶点、左下角顶点、右下角顶点)

CesiumJS CesiumJS API&#xff1a;https://cesium.com/learn/cesiumjs/ref-doc/index.html CesiumJS 是一个开源的 JavaScript 库&#xff0c;它用于在网页中创建和控制 3D 地球仪&#xff08;地图&#xff09; 一、添加指定长宽的图片图层&#xff08;原点为图片图层的中心…...

Redis 主从同步 问题

前言 相关系列 《Redis & 目录》&#xff08;持续更新&#xff09;《Redis & 主从同步 & 源码》&#xff08;学习过程/多有漏误/仅作参考/不再更新&#xff09;《Redis & 主从同步 & 总结》&#xff08;学习总结/最新最准/持续更新&#xff09;《Redis &a…...

【SQL Server】探讨 IN 和 EXISTS之间的区别

前言 在使用 SQL 查询相关表数据时,通常需要根据另一个表中的值来筛选数据。而 IN 与 EXISTS 子句都是用于此场景的常用方式,但使用时两者存在工作方式不同。它们使用上的选择会显著影响查询的性能,尤其是在大型数据集中。本文我们一起探讨 IN 和 EXISTS 之间的区别、使用与…...

清理pip和conda缓存

当用户目录没有空间时&#xff0c;可清理pip和conda缓存 清理conda缓存&#xff1a; conda clean --all清理pip缓存&#xff1a; pip cache purgeNote&#xff1a; 可以利用软链接&#xff0c;将用户目录下的文件链接到其他位置 首先移动文件或文件夹到其他位置 mv ~/test /…...

git rebase和merge的区别

Git merge和Git rebase是两种不同的合并策略&#xff0c;它们在处理分支合并时有各自的优点和缺点。 Git fetch git fetch 命令用于从远程仓库获取最新的更改&#xff0c;但不会自动合并这些更改到你的本地分支。它会下载远程仓库的所有分支和标签&#xff0c;并更新你的本地…...

【elkb】linux麒麟v10安装ELKB 8.8.X版本(ARM架构)

下载软件 相关版本信息 elasticsearch&#xff1a;8.8.1kibana&#xff1a;8.8.1logstash&#xff1a;8.8.1filebeat&#xff1a;8.8.1 下载地址 https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.8.1-linux-aarch64.tar.gzhttps://artifacts.elastic…...

bluez hid host介绍,连接键盘/鼠标/手柄不是梦,安排

零. 前言 由于Bluez的介绍文档有限,以及对Linux 系统/驱动概念、D-Bus 通信和蓝牙协议都有要求,加上网络上其实没有一个完整的介绍Bluez系列的文档,所以不管是蓝牙初学者还是蓝牙从业人员,都有不小的难度,学习曲线也相对较陡,所以我有了这个想法,专门对Bluez做一个系统…...

GPT打数模——电商品类货量预测及品类分仓规划

背景 电商企业在各区域的商品存储主要由多个仓库组成的仓群承担。其中存储的商品主要按照属性&#xff08;品类、件型等&#xff09;进行划分和打标&#xff0c;便于进行库存管理。图 1 是一个简化的示意图&#xff0c;商品品类各异&#xff0c;件数众多&#xff0c;必须将这些…...

华为OD机试 - 螺旋数字矩阵 - 矩阵(Python/JS/C/C++ 2024 D卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…...

分类预测 | GCN图卷积神经网络多特征分类预测(MATLAB)

分类预测 | GCN图卷积神经网络多特征分类预测(MATLAB) 目录 分类预测 | GCN图卷积神经网络多特征分类预测(MATLAB)分类效果基本介绍程序设计参考资料分类效果 基本介绍 GCN图卷积神经网络多特征分类预测(MATLAB) 在图卷积神经网络(GCN)中,多特征分类...

FPGA搭建PCIE3.0通信架构简单读写测试,基于XDMA中断模式,提供3套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案本博客方案的PCIE2.0版本 3、PCIE基础知识4、工程详细设计方案工程设计原理框图XDMA配置及使用XDMA中断模块数据缓存架构用户逻辑Windows版本XDMA驱动安装Linux版本XDMA驱动安装测试应用程序工程源码架构PCIE上板…...

App相关技术以及打包

平时小伙伴们自己的博客网站只能在浏览器打开&#xff0c;但是有时候你想要制作自己独立个人博客app&#xff0c;宣传并推广自己的app&#xff0c;打造个人ip。如何把自己的web博客网站打包成安卓app&#xff1f; 1.开发App的相关技术使⽤ ⽬前市⾯上的移动互联开发技术主要分…...

【unity】【游戏开发】Unity代码不给提示怎么办?

【现象】 Unity用着用着忽然VS脚本不给提示了。 【分析】 重启Unity无效 重启VS无效 重装VS无效 感觉应该是项目设置问题 【最终方法】 打开Edit->Preferences。 如果是这个画面就把Script Editor改成自己的VS编辑器。 变成下面这个样子&#xff0c;点击Regenerate Pr…...

Kubernetes固定Pod IP和Mac地址

方案1&#xff1a; 在 Calico GitHub Issues#5196 问题的 commits#6249 提交中&#xff0c;引入新的 Pod 注释cni.projectcalico.org/hwAddr&#xff0c;用于将指定的 MAC 地址分配给容器端 Veth 接口。 将Calico升级至v3.24.1或以上版本&#xff0c;使用如下注解轻松设置Pod…...

计算机组成原理之数据的对齐和大/小端存放方式、计算机中数据对齐的具体方式有哪些

1、计算机组成原理之数据的对齐和大/小端存放方式 数据对齐 数据对齐是处理器为了提高处理性能而对存取数据的起始地址所提出的一种要求。 系统一次性读取内存中数据的大小是固定的&#xff0c;例如字长为32位的操作系统&#xff0c;默认的一次读取4字节内容。因此&#xff…...

广州网站建设o2o/万网域名查询注册商

信号调制与解调[实验目的]1&#xff0e; 了解用MATLAB 实现信号调制与解调的方法。 2&#xff0e; 了解几种基本的调制方法。 [实验原理]由于从消息变换过来的原始信号具有频率较低的频谱分量&#xff0c;这种信号在许多信道中不适宜传输。因此&#xff0c;在通信系统的发送端通…...

网站建设组织/淘宝店铺如何推广

解决方法一&#xff1a;RequestMapping(value"/getphone",produces "text/plain;charsetutf-8") /**输入手机号码后判断手机号是否存在*/ RequestMapping(value"/getphone",produces "text/plain;charsetutf-8") ResponseBody publi…...

给网站增加功能怎么做/公司软文

转自&#xff1a;http://code4app.com/article/cocoapods-install-usage 目录 CocoaPods是什么&#xff1f;如何下载和安装CocoaPods&#xff1f;如何使用CocoaPods&#xff1f; 场景1&#xff1a;利用CocoaPods&#xff0c;在项目中导入AFNetworking类库场景2&#xff1a;如何…...

唐山网站制作方案/电商项目策划书

二、 依赖属性的优先级 由于WPF 允许我们可以在多个地方设置依赖属性的值&#xff0c;所以我们就必须要用一个标准来保证值的优先级别。比如下面的例子中&#xff0c;我们在三个地方设置了按钮的背景颜色&#xff0c;那么哪一个设置才会是最终的结果呢&#xff1f;是Black、Red…...

关于怎么做网站/济南seo网站优化公司

对原件&#xff0c;有这几种&#xff1a;1&#xff0c;全中文&#xff08;含标点&#xff0c;一些英文符号&#xff09;2&#xff0c;中英文&#xff08;英文较多&#xff0c;或英文占大多数&#xff09;3&#xff0c;全英文&#xff08;这个用finereader8.0&#xff09; 針對1…...

做公寓酒店跟网站合作有什么技巧/b站推广app大全

我发现童鞋们对百度的技术很感兴趣哦&#xff0c;呵呵&#xff0c;大型互联网公司真是聚集牛人的地方&#xff0c;不过我感觉和google比起来&#xff08;看他们网站的源码&#xff09;&#xff0c;google的网页的代码比百度更加复杂&#xff0c;我以前觉得google什么都是开源&a…...