让Pomelo支持HTTP协议

背景 我们一直在尝试让服务器端摆脱Pomelo这个老框架, 让他能更符合现在主流的后端架构.在我们的概念中, 除了服务器端主动推送的通知外,别的业务都可以通过使用无状态的http来进行交互但受限于Pomelo的框架,我们的全部业务都是通过长连接来实现的, 这就导致我们的业务是有状态的. 下面就是对 Pomelo是否能支持HTTP协议的一次调研和尝试

回顾

让我们在回顾下 现在服务端的架构吧

目标

  • 不加新类型实现HTTP服务
  • 新的HTTP服务支持负载均衡(无状态)
  • 尽量少或是不改动现有代码的基础上实现

过程

实现目标1

这个目标还是很简单,无非就是让一些进程在现有TCP监听的基础上加上HTTP端口的监听即可,最合适加HTTP端口监听的服务器类型自然是Logic进程,因为我们大部分业务都在Logic上,于是开始在Logic进程上再监听一个HTTP端口

修改配置, 为每一个Logic添加一个http端口

在启动logic进程时, 添加一个HTTP组件, 启动一个HTTP服务这样Logic进程不止支持TCP还支持HTTP了

实现目标2

打眼一看目标2也很简单, 现在每一个Logic进程都有HTTP端口了,我们在Nginx上配置下请求的端口即可实现简单的负载均衡

但目标二还有一层含义, Logic进程应该是无状态的, 怎么实现无状态的,放到目标三来说明

实现目标3

第三个目标是想在尽量不改动现有代码的基础上来实现这套逻辑, 我们先来看看现在的一个协议是如何被调用的以SPIN协议为例,最终Pomelo会路由到下面的这段代码来 如果我们想手动执行这个方法的话,需要构建所需的参数这里有三个参数, app: 是pomelo对象, session: backend Session, next: 执行完成后的回调函数第一 三 两个参数都挺简单的, 能很简单的获取和构造得到我们看下pomelo的源代码第二个参数就挺麻烦了, 这个backend Session是从哪来的呢?

Backend Session从哪来的?

通过名称:找到了两个相关的文件,一个是组件,另外一个是服务, 我们主要来看服务这个文件,也就是 backendSessionService.js
我们发现这里有一个crete方法, 我找下是什么时候创建的这个backend Session吧我又查阅了相关的文档

通过代码的注释和文档得知 每一个请求都会创建一个新的backend session, 而这个backend Session又是通过前端服务器的session创建的, 那么我们要自己去创建这个backend session的话就要获得session才行

如何获得Session

Session又是从哪来的呢?通过前文的构建图可以看出Session其实是分散到每一个connector进程上的,我们的logic想直接获得别的进程上的信息还是比较困难的. 这时候很容易想到了第三方的存储介质, 比如我们的Redis. 可以把Session存一份到Redis吗?

登录完成后首次存储Redis

第一个想到可以存储的地方当然是登录完成后了具体实现如下:

在connector进程启动时, 加载一个叫 SessionRedisStore的组件

这个组件提供一些列操作Session的方法, 例如将Session存储到Redis中去或是从Redis中取Session信息等

当玩家登录成功后就可以手动的存储一份到redis中C2SLogin.js

同步Session信息到Redis

除了登录完成后存储的初始Session的信息, 我们还需要当Session信息改变的时候也需要同步信息到Reis中去,我们通过文档得知 当我们需要对Session信息做出修改时会调用Push方法(文档上没提到的还有一个PushAll函数可以批量的修改Session里的字段)这时候我们需要做一个请求的拦截, 当调用push的顺便去更新我们的redis中的数据这时候PomeloFilter就派上用场了

这是文档上对Filter下的定义:我们利用Filter的原理,在执行这个请求前,将session做一个封装,当执行session.push的时候触发我们的redis数据更新

我们在Logic启动时增加一个过滤器

这个过滤器主要是修改了push和pushAll两个函数, 在执行原push方法的同时添加了更新redis的逻辑

好了通过这一系列的修改后,我们终于实现了将session信息存储到redis中,并且可以同步session的变化了

如何自己创建Backend Session

我们上一步把session存储到了redis中,目的就是为了实现通过session创建Backend Session, 具体如何实现呢?

这里直接调用的是pomelo自己的创建方法

串联整体的逻辑

让我们重新来串联下业务逻辑

  1. 玩家登录到Connector进程上,将Session信息同步到Redis
  2. 玩家访问Logic有两种方式
  3. TCP: 和之前的相同
  4. HTTP: 通过URL路由后构建backend session最后执行C2SSpin这样我们就实现了,最少修改成本实现了HTTP协议的支持

结果展示

TCP访问

下面是一个服务器端实现的客户端程序登录:

SPIN的返回值

HTTP访问

EnterRoom

Spin

Cursor

LLM: claude-3.5-sonnet以及claude-3.7-sonnet这些代码绝大部分都是Cursor帮我实现的, 我是一步一步的提供给他思路

下面是我一个三段式的提示词,其中也用到了Cursor的 Docs和 Web功能

背景:我这个项目通过pomelo实现的, 主要有两类服务器 第一类是:connector是用于登录并和客户端保持连接的, 进程中存储了session信息, 第二类是: logic进程是用于逻辑处理的,进程中存储了另外一个session名称叫backendSession,是每次请求时connector通过session创建而来的, 这两类服务器的交互方式是 玩家在connector进程登录后,通过路由的方式转发到logic进程进行一些逻辑处理,我已经在现在的代码的基础上在logic进程上实现一个http的服务,我想实现的是玩家登录后就可以通过http请求直接访问logic服务了,实现几乎不修改代码就能支持websocket协议和http协议

需求: 现在有一个问题, 在执行时需要一个backendSession参数, 而这个backendSession就如前文说的一样,是通过connector生成的, 为了让http服务也能获得这个session, 所以我想把connector的session存一份到redis上, 并且有更新的时候能及时更新,并且提供给我通过session创建backendSession的方法

要求:参考pomelo的文档 @Pomelo中文文档 和 源代码@github.com/NetEase/pom... 来实现

相关推荐
MZWeiei30 分钟前
Scala:case class(通俗易懂版)
开发语言·后端·scala
小杨4041 小时前
springboot框架项目实践应用三(监控运维组件admin)
spring boot·后端·监控
sevevty-seven2 小时前
Spring Boot 自动装配原理详解
java·spring boot·后端
lamdaxu3 小时前
分布式调用(02)
后端
芒猿君3 小时前
AQS——同步器框架之源
后端
SaebaRyo4 小时前
手把手教你在网站中启用https和http2
后端·nginx·https
A-Kamen4 小时前
Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现与实战指南
java·spring boot·后端
豆豆酱4 小时前
Transformer结构详解
后端