FastAPI集成Socket.io坑点汇集和技术选型

背景

单纯的 websocket 通信方式存在大量的辅助性的工作需要处理,例如心跳机制、粘包处理、协议规范等,所以直接使用 websocket 开发,等于重复造轮子,毫无价值,而 socket.io 整理了一整套规范和机制,可以满足聊天室的功能,还能对不同的业务场景进行命名空间级别的隔离,简直不要太好用,完全满足我们这种低并发场景的各类需求且上手极其容易。

FastAPI 如何集成 socket.io?

有个 socket.io 的fastapi-socketio官方库,该库依赖传统的 python-socketio 库(这里请一定注意 socket.io-client.js 版本对应关系),fastapi-socketio 主要给出 fastapi 如何集成 python-socketio 的方法,省去了普通人将 python-socketio 集成到 fastapi 的工作。

代码 Demo

from fastapi import FastAPI
from fastapi_socketio import SocketManager
import uvicorn

app = FastAPI()
socket_manager = SocketManager(app=app, mount_location="/ws")

@socket_manager.on('connect',namespace="/ws")
async def connect(sid, environ):
    print(sid)
    print(environ)


if __name__ == "__main__":
    uvicorn.run(app, host="localhost", port=8888)

socket.io-client 的几个关键点

坑死你的命名空间

我们常规思维都是把 https://example.com/orders 这里的 orders 作为路径对待,可惜的是 socket.io 竟然把 host 之后的所有 path 都变成了 namespace,这是个大坑,一般人如果直接使用 host 作为 websocket 服务器一点问题都没有,但总有些情况下我们的 SSL 证书不足,我们没用二级域名,我们用了 path 来作为新的服务 endpoint,采用 nginx 进行反向代理过去,你以为会到 /orders,其实还是 https://example.com/socket.io?xxx... ,这让我百思不得其解,在多次确定服务端没有错误的情况下,我开始思考是不是 socket.io 不是这样配置的?

socket.io 命名空间用在哪里?

socket.io 原理详解 中我发现了engine.io,深入调试 socket.io 客户端源码时发现,socket.io 是建立在 engine.io 基础上针对 onmessage.data 结构设置了自己的一套协议,就叫 socket.io 协议,这个协议就有一个 namespace 的 key,这个 key 可以在 socket.io 协议层对事件进行区分,而不必新建一个 websocket,这???我还真没想到这种复用方式,也的确挺好,因此 /orders 被放到了 onmessage.data 中了,并没有在 connect 时,像 http 的方式发送给服务端了,问题来了/socket.io?xxx 这一坨参数是什么鬼?从哪里来的?

engine.io 中的 path

在 io(url, opts) 配置中,opts 有个 path 的 key,这个 key 默认就是 socket.io

虽然官方文档中也强调了,但谁能联想到?

我们再来看下服务端的默认配置

再来看看 fastapi-socketio 的源码

于是客户端的请求链接应该是这样的,是不是很惊讶?

socket = io('ws://localhost:8888/ws', {
  transports: ['websocket'],
  path:'/ws/socket.io'
});

socket.on('message', function(msg) {
    console.log(msg);
});
socket.on('reply', function(msg) {
    console.log(msg);
});

socket.io 技术选型?

因为 fastapi 主打的是异步框架,采用 asgi 的方式运行,所以python-socketio选择异步的方式进行

asgi 和 wsgi 两者的比较

以下文章讲得怪怪的,其实几句话就可以讲清楚,wsgi 是基于 python 同步语言时代产生的一种协议,按照这种协议开发出来 uwsgi 中间件可以同时满足与同步语言的应用框架下的数据交换,同时还能对外暴露接口,支持 http 协议,使得 nginx 能直接反向代理到 uwsgi,其实不用 nginx,uwsgi 本身就是个 http 协议服务器了,到了后来 async/await 这种基于事件循环的协程式语言出现,原来 wsgi 不够用了,所以就出了 asgi 协议,支持这个协议的中间件有 uvicorn 等,你说为啥需要 wsgi 协议,没有这个协议,你怎么拿到 http 协议 header 中的 Origin?

Django 3.0 ASGI 指南及其性能_Wang_AI的博客-CSDN博客

WSGI和ASGI的异同_studyeboy的博客-CSDN博客_asgi

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Socket.IO 是一种实时通信协议,它可以在客户端和服务器之间建立双向通信的连接,从而实现实时通信。在集成 Socket.IO 和 Spring Boot 时,可以使用 Spring Boot 中的 WebSockets 模块来实现与客户端的实时通信。 以下是集成 Socket.IO 和 Spring Boot 的步骤: 1. 在 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.7.17</version> </dependency> ``` 2. 创建一个 SocketConfig 类,用于配置 Socket.IO: ``` @Configuration public class SocketConfig { @Bean public SocketIOServer socketIOServer() { Configuration config = new Configuration(); config.setHostname("localhost"); config.setPort(9092); SocketIOServer server = new SocketIOServer(config); return server; } } ``` 3. 创建一个 SocketController 类,用于处理 Socket.IO 的事件: ``` @Component public class SocketController { @Autowired private SocketIOServer server; @PostConstruct public void init() { server.addEventListener("message", String.class, (client, data, ackSender) -> { System.out.println("Received message: " + data); server.getBroadcastOperations().sendEvent("message", data); }); } } ``` 在上面的示例中,我们使用 @PostConstruct 注解来初始化 Socket.IO 事件监听器,当客户端发送 "message" 事件时,服务器将打印消息并将其广播给所有客户端。 4. 在 Spring Boot 应用程序主类中添加以下代码: ``` @EnableAutoConfiguration @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Autowired private SocketIOServer server; @PreDestroy private void destroy() { server.stop(); } } ``` 在上面的示例中,我们在应用程序启动时自动启动 Socket.IO 服务器,并在应用程序关闭时停止服务器。 现在,您已经成功地将 Socket.IO 集成到 Spring Boot 中了。您可以使用 Socket.IO 客户端与服务器进行实时通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值