使用Sanic和SSE实现实时股票行情推送
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
-
推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~
-
专栏导航
- Python系列: Python面试题合集,剑指大厂
- Git系列: Git操作技巧
- GO系列: 记录博主学习GO语言的笔记,该笔记专栏尽量写的试用所有入门GO语言的初学者
- 数据库系列: 详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
- 运维系列: 总结好用的命令,高效开发
- 算法与数据结构系列: 总结数据结构和算法,不同类型针对性训练,提升编程思维
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
💖The Start💖点点关注,收藏不迷路💖📒文章目录
- 什么是Server-Sent Events (SSE)
- 为什么选择Sanic
- 实现步骤
- 1. 安装依赖
- 2. 创建Sanic应用
- 3. 前端实现
- 4. 避免跨域问题
- 5. 优化与扩展
- 总结
实时数据推送已经成为了许多应用的关键功能之一,尤其是在金融、监控、社交媒体等领域。本文将深入探讨如何使用Sanic框架结合Server-Sent Events (SSE)技术,实现用户在浏览器中选择不同股票并实时接收对应的股票行情推送。本文将重点介绍实现步骤、技术细节以及实际使用中的一些优化建议。
什么是Server-Sent Events (SSE)
Server-Sent Events (SSE) 是一种轻量级的服务器推送技术,允许服务器向客户端推送数据。与WebSocket相比,SSE相对简单,特别适合需要单向数据流的应用场景,比如新闻推送、股票行情、实时通知等。
SSE的优势包括:
- 简单易用:使用HTTP协议,无需复杂的握手过程。
- 自动重连:浏览器原生支持自动重连机制,当连接断开时,客户端会自动尝试重新连接。
- 轻量级:非常适合频繁的数据推送,尤其是在数据更新频率较高的场景中。
为什么选择Sanic
Sanic是一个基于Python的异步Web框架,以其高性能和简单易用的API广受欢迎。Sanic天然支持异步操作,特别适合处理SSE这样的长连接请求。
使用Sanic和SSE的结合,可以轻松地实现高效的实时数据推送服务,特别是在股票行情等对实时性要求高的场景下。
实现步骤
接下来,我们将一步步实现一个简单的实时股票行情推送服务,用户可以在浏览器中选择股票并接收对应的实时行情。
1. 安装依赖
首先,确保已安装Sanic
和其他必要的库。可以通过以下命令安装:
pip install sanic
2. 创建Sanic应用
接下来,创建一个Sanic应用,并实现一个简单的SSE数据流。我们将模拟几个股票的实时数据,并根据用户的选择推送相应的股票行情。
from sanic import Sanic, response
import asyncio
import timeapp = Sanic("StockSSE")# 模拟股票行情数据
stock_data = {"AAPL": {"stock_name": "Apple", "price": 150.00, "change": 0.25},"GOOG": {"stock_name": "Google", "price": 2750.00, "change": -10.00},"AMZN": {"stock_name": "Amazon", "price": 3400.00, "change": 15.00}
}async def stock_data_generator(stock_symbol):while True:data = stock_data.get(stock_symbol, {})data['timestamp'] = time.time()yield f"data: {response.json(data)}\n\n"await asyncio.sleep(1)@app.route("/stock/<stock_symbol>")
async def stock_stream(request, stock_symbol):async def stock_stream(res):async for data in stock_data_generator(stock_symbol):await res.write(data)return response.stream(stock_stream, content_type='text/event-stream')if __name__ == "__main__":app.run(host="0.0.0.0", port=8000)
在这个示例中,我们定义了一个简单的股票数据模拟器,并使用/stock/<stock_symbol>
路由来处理SSE请求。通过stock_data_generator
生成器函数,我们可以持续不断地向客户端推送股票数据。
3. 前端实现
前端使用HTML和JavaScript的EventSource
对象来接收服务器推送的数据,并根据用户选择的股票更新显示内容。以下是一个简单的HTML页面,用户可以选择股票,并实时查看对应的行情。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>实时股票行情</title><style>body {font-family: Arial, sans-serif;}.stock-data {margin: 20px;padding: 10px;border: 1px solid #ddd;}select {margin: 20px;padding: 5px;}</style>
</head>
<body><h1>实时股票行情</h1><select id="stock-select"><option value="Apple">Apple</option><option value="GOOG">Google</option><option value="AMZN">Amazon</option></select><div id="stock-container"><div class="stock-data" id="stock-data">选择一个股票查看其行情数据...</div></div><script>let eventSource;const stockSelect = document.getElementById('stock-select');const stockDataDiv = document.getElementById('stock-data');function updateStock(stockSymbol) {if (eventSource) {eventSource.close();}eventSource = new EventSource(`/stock/${stockSymbol}`);eventSource.onmessage = function(event) {const stockData = JSON.parse(event.data);stockDataDiv.innerHTML = `股票名称: ${stockData.stock_name}<br>当前价格: ${stockData.price}<br>涨跌幅: ${stockData.change}<br>时间戳: ${stockData.timestamp}<br>`;};eventSource.onerror = function(event) {console.error('SSE 连接错误:', event);};}stockSelect.addEventListener('change', function() {const selectedSymbol = stockSelect.value;updateStock(selectedSymbol);});// 初始化加载第一个股票的数据updateStock(stockSelect.value);</script>
</body>
</html>
这个前端页面非常简单,通过JavaScript监听股票选择器的变化,并根据用户选择的股票启动新的SSE连接,实时更新行情数据。
4. 避免跨域问题
在实际应用中,跨域请求可能会导致浏览器拒绝连接。如果前端与后端不在同一个域下,可以使用Sanic的file
函数直接返回HTML页面,确保所有请求都来自同一域,从而避免跨域问题。
from sanic import response
@app.route("/")
async def index(request):return await response.file('static/index.html')
将HTML文件放置在static
目录下,并通过Sanic的路由直接返回该文件。这样,前端页面和数据请求都运行在同一个域下,消除了跨域问题。
5. 优化与扩展
在实际项目中,以下几点优化建议可以帮助你进一步提升系统的性能和用户体验:
- 数据源优化: 如果需要处理真实的股票数据,可以将
get_stock_data
函数扩展为从外部API获取实时数据。 - 推送频率: 根据业务需求,调整数据推送的频率,或者仅在数据发生变化时推送更新,以减少不必要的流量和资源占用。
- 错误处理: 添加错误处理机制,如在SSE连接断开时提供用户友好的提示,或在数据请求失败时进行重试。
- 负载均衡: 在高并发场景下,可以使用Nginx等反向代理服务器对Sanic服务进行负载均衡,确保服务的稳定性和高可用性。
总结
通过本文的介绍,开发者可以轻松实现一个基于Sanic和SSE的实时股票行情推送服务。该技术方案不仅简单高效,而且能够满足金融应用中对实时数据推送的高要求。在实际应用中,通过合理的优化和扩展,可以构建出性能卓越、用户体验良好的实时数据推送系统。
希望这篇文章能为你在实际开发中提供有价值的参考。未来,你可以将这些技术应用到更多的实时数据场景中,如新闻推送、社交媒体通知、监控报警等,为用户提供更加动态和互动的体验。
🔥🔥🔥道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
💖The End💖点点关注,收藏不迷路💖 |
相关文章:

使用Sanic和SSE实现实时股票行情推送
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storm…...

redis散列若干记录
字典 redis本身使用字典结构管理数据 redis使用hash表实现字典结构 使用了什么hash算法 使用SipHash算法,该算法能有效防止Hash表碰撞,并有不错的性能 hash冲突怎么解决 使用链表法解决hash冲突 hash表如何扩容 渐进式扩容,不会引起线程长期阻…...

Java面试八股之什么是STOMP协议
什么是STOMP协议 STOMP(Simple Text Oriented Messaging Protocol)是一种为消息队列和事件驱动架构设计的轻量级协议,主要用于在消息中间件之间进行消息交换。它的设计原则是简单、跨平台和易于实现,这使得STOMP成为许多实时应用…...

【自用】Python爬虫学习(一):爬虫基础与四个简单案例
Python爬虫学习(一) 基础知识四个简单的爬虫案列1.使用urlopen获取百度首页并保存2.获取某翻译单词翻译候选结果3.获取某网页中的书名与价格4.获取某瓣排名前250的电影名称 基础知识 对于一个网页,浏览器右键可以查看页面源代码,…...

[python]uiautomation.WindowControl函数用法
Python UIAutomation 窗口控件 介绍 在本文中,我们将探讨Python UIAutomation库以及如何使用它来控制和自动化Windows应用程序。我们将介绍UIAutomation的基础知识及其功能,并提供代码示例来演示其用法。 什么是UI自动化? UIAutomation是一个…...

学习记录第二十七天
进程 wait函数 功能 等待子进程结束:父进程调用wait函数后,会暂停执行,直到它的某个子进程结束。收集子进程状态:当子进程结束时,wait函数会返回子进程的终止状态,包括是正常终止还是被信号终止等信息。…...

servlet的执行顺序
执行的时候Tomcat先初始化 然后调用 server 根据server来回调请求方式下面会追入源码解释 package com.haogu.servlet;import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.…...
Go语言 类封装和绑定方法
本篇文章主要内容为Go语言类相关操作:封装和绑定方法介绍及示例。 目录 封装 绑定方法 类方法形参 指针形参 设置类方法参数 指针与非指针区别 总结 封装 go语言支持类的操作,但是没有class关键字,使用struct来模拟类。 示例如下&am…...
DirectShow过滤器开发-写WAV音频文件过滤器
下载本过滤器DLL 本过滤器将PCM音频流,或ADPCM,IEEE_FLOAT,ALAW,MULAW,GSM610音频流写入WAV音频文件。 写WAV音频文件过滤器信息 过滤器名称:写WAV 过滤器GUID:{CF704A9C-0C67-4712-BA33-DD0A…...

php根据截止时间计算剩余的时间,并且在剩余时间不足1天时仅显示小时数
//获取政策库文章public function getIndexZckList(){$fl_id = input(fl_id);if(empty(...
Docker最佳实践进阶(一):Dockerfile介绍使用
大家好,上一个系列我们使用docker安装了一系列的基础服务,但在实际开发过程中这样一个个的安装以及繁杂命令不仅仅浪费时间,更是容易遗忘,下面我们进行Docker的进阶教程,帮助我们更快速的部署和演示项目。 一、什么是Dockerfile? Dockerfile 是一个文本文件,其中包含了…...

Anything in Any Scene:无缝融入任何场景,实现逼真视频对象插入技术
人工智能咨询培训老师叶梓 转载标明出处 现实世界的视频捕获虽然因其真实性而宝贵,但常常受限于长尾分布的问题,即常见场景过度呈现,而关键的罕见场景却鲜有记录。这导致了所谓的"分布外问题",在模拟复杂环境光线、几何…...
安卓开发中的AppCompat框架|安卓系统|安卓应用|兼容性|UI组件|核心组件|ActionBar|Fragment|最佳实践|框架|移动开发|移动应用
目录 1. 什么是AppCompat框架 1.1 AppCompat的起源 1.2 AppCompat的重要性 2. AppCompat框架的核心组件 2.1 AppCompatActivity 2.2 AppCompat主题 2.3 AppCompat Widgets 3. 在项目中使用AppCompat框架 3.1 添加依赖项 3.2 应用AppCompat主题 4. AppCompat的高级功…...

React使用useRef ts 报错
最近在写自己的React项目,我在使用useRef钩子函数的时候发现 TS2322: Type MutableRefObject<HTMLDivElement | undefined> is not assignable to type LegacyRef<HTMLDivElement> | undefined Type MutableRefObject<HTMLDivElement | undefined&g…...
python-信息交互-pyautogui
python-信息交互-pyautogui 一: pyautogui1> waht?2> 功能分类3> 概念及作用二: 通用功能1> function all2> function 注释三: 鼠标控制1> mouse functions2> mouse functions demo3> mouse drag demo四: keyboard控制1> keyboard functions2> …...

flink1.18 编译遇到的问题
1. flink-runtime-web编译失败 源码编译时一直卡在 [INFO] Running ‘npm ci --cache-max0 --no-save’ in 处理方法: 修改flink-runtime-web/pom.xml文件 将<arguments>ci --cache-max0 --no-save ${npm.proxy}</arguments> 替换为:<a…...
2024年8月份编译Openwrt系统基础
概述: 本文档记录openwrt系统的编译过程,以备后续再用,技术支持与指导! 1.编译环境 环境需要Linux,我使用的环境是WSL2、Ubuntu 20.04 2.安装编译必须的依赖(wsl、linux) WSL2:Bu…...

Vue3+vite+ts 项目使用mockjs
1、安装mockjs npm i mockjs 2、安装vite-plugin-mock npm i vite-plugin-mock -D 3、安装axios npm i axios 4.在src目录下创建mock文件夹,在文件夹内创建login.ts等文件,并在文件夹内放置以下内容(注:URL要和真实请求地址保持一致&am…...

动态规划(二)——例题
目录 Help Jimmy 题目 解题思路 神奇的口袋 题目 枚举的解法 递归的解法 动态规划的解法 滑雪 题目 解题思路 解法一 解法二 Help Jimmy 题目 "Help Jimmy" 是在下图所示的场景上完成的游戏: 场景中包括多个长度和高度各不相同的平台。地面是…...
Node.js中判断是文件还是文件夹的多种方法
在Node.js中,我们经常需要判断一个路径是文件还是文件夹。Node.js提供了多种方法来实现这一功能,本文将详细介绍这些方法,并给出相应的示例代码。 一、使用fs.Stats对象 在Node.js中,fs模块提供了fs.stat()或fs.statSync()方法&…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...