我们正在使用socket.io进行移动服务器通信。由于我们无法强制升级用户的设备,如果我们想升级到版本1(非反向兼容),我们必须在服务器上处理这两个版本一段时间。
有哪些选择?
我目前最喜欢的是将旧版本和新版本包装在多路复用器中。它根据头和查询参数检测传入请求的版本,从而知道要调用哪些函数。
另一个(shittier)选项是将新版本包装在一个模块中,该模块可以在必要时将旧版本的协议转换为新版本(并再次返回)。这具有严重的缺点。确保我已经正确地确定并处理了所有微小的差异,这将是一项耗时且不确定的工作。一些差异可能需要一些严重的按摩。
(如果您感到好奇或知道有帮助,我们会在Go中这样做。)
答案 0 :(得分:2)
您似乎可以在服务器上运行两个单独版本的socket.io.由于这两个版本没有唯一的模块文件名,因此您可能需要从不同的路径加载一个版本。然后,显然在加载模块并初始化它们时,您将它们分配给不同命名的变量。例如:
var io_old = require('old/socket.io');
var io = require('socket.io);
一旦你在服务器上加载了两个版本,我认为有两种不同的方法可以运行它们。
1)为每个版本使用不同的端口。旧版本将使用与node.js Web服务器共享的默认端口80(无需更改配置)。较新的版本将在不同的端口(例如端口3000)上运行。然后,您将每个版本的socket.io初始化为其自己的端口。然后,您的新版本客户端将连接到运行较新版本的端口。
对于在端口80上运行的旧socket.io服务器,您将使用您已经拥有的任何可能挂钩到现有http服务器的初始化。
对于在其他端口上运行的新socket.io服务器,您可以单独初始化它:
var io_old = require('old/socket.io')(server);
var io = require('socket.io')(3000);
然后,在新版本客户端中,您将在连接时指定端口3000。
var socket = io("http://yourdomain.com:3000");
2)为每个版本使用不同的HTTP请求路径。默认情况下,每个socket.io连接都以一个如下所示的HTTP请求开始:http://yourdomain.com/socket.io?EIO=xx&transport=xxx?t=xxx
。但是,该请求的/socket.io
部分是可配置的,并且socket.io的两个单独版本可以各自使用不同的路径名。在服务器上,启动socket.io侦听的.listen()
方法采用可选的选项对象,可以使用path: "/socket.io-v2"
中的自定义路径进行配置。同样,客户端中的.connect()
方法也接受该选项对象。这个选项很难找到the documentation,因为它实际上是一个engine.io选项(socket.io使用),但是socket.io将选项传递给engine.io。
我自己没有尝试过这些,但我研究了如何从客户端和服务器启动socket.io连接,看起来底层引擎支持这种功能,我看不出它为什么不能工作的原因。
以下是您如何更改服务器上的路径:
var io = require('socket.io')(server, {path: "/socket.io.v1"});
然后,在新版本的客户端代码中,您将连接如下:
var socket = io({path: "/socket.io.v1"});
这将导致初始连接请求发送到HTTP URL,如下所示:
http://yourdomain.com/socket.io.v1?EIO=xx&transport=xxx?t=xxx
这将由HTTP服务器上的不同请求处理程序处理,从而将两个版本分开。
仅供参考,socket.io连接URL中的EIO=3
查询参数实际上也可能是engine.io版本号,也可用于识别客户端版本和“做正确的事”基于该值。我还没有找到任何关于它如何工作的文档,甚至无法找到在engine.io或socket.io源代码中查看查询参数的位置,因此需要进行更多调查作为另一种可能性。
答案 1 :(得分:0)
我真的没有立即解决这个问题,但我有一些建议。我猜你可以用它来节省很多时间。
答案 2 :(得分:0)
我们将把0.9.x版本和当前版本保持为服务器上的独立库。最终,当客户端池或多或少全部更新时,我们只需拔掉0.9.x版本的插件。
我们管理这两个版本的方法是将socket.io服务包装在一个包中,该包将确定将请求传递给哪个包装的socket.io版本。此确定将取决于请求的功能,例如自定义标头(可以添加到较新的客户端)以及查询参数和由一个版本或另一个版本专用的其他标头。
由于我们使用Go,到目前为止还没有普遍认同的方法来管理依赖关系,更不用说一种可以尊重版本差异的方法。假设回购的back-compat分支没有被破坏(它是),我们有两个选择。第一个是fork repo并使back-compat版本成为master。然后我们将其导入,就好像它与另一个无关。第二种选择是使用gopkg.in假装单独的分支是单独的回购。
在任何一种情况下,我们都可以像这样导入两个分支/回购
import (
socketioV0 "github.com/path/to/older/version"
socketioV1 "github.com/path/to/current/version"
)
然后使用导入名称socketioV0
和socketioV1
在代码中引用它们。