更改端口而不丢失数据

Posted

技术标签:

【中文标题】更改端口而不丢失数据【英文标题】:Change port without losing data 【发布时间】:2011-07-25 09:38:09 【问题描述】:

我正在为我的 http 服务器构建一个设置管理器。我希望能够更改设置而不必终止整个过程。我希望能够更改的设置之一是更改端口号,我想出了多种解决方案:

杀死进程并重新启动它 调用 server.close() 然后做第一种方法 调用 server.close() 并在同一进程中初始化新服务器

问题是,我不确定每种方法的影响是什么。我知道第一个会起作用,但我真的很想完成这些事情:

响应现有请求而不接受新请求 在新服务器的内存中维护数据 尽可能减少正常运行时间

有什么方法可以得到我想要的一切吗? server.close() 的 API 给了我希望: server.close(): Stops the server from accepting new connections.

我的服务器只能由我创建的客户端和通过浏览器连接的数量非常有限的客户端访问,因此我将能够通知他们端口更改。我知道更改端口通常不是一个好主意,但我想考虑到方便或可能需要的边缘情况。

附:如果有任何改变,我正在使用 connect。

附言相对不相关,但是如果我使用 UNIX 服务器套接字或更改主机名会发生什么变化?这可能是一个更相关的用例。

P.P.P.S.这段代码说明了使用 server.close() 的问题。以前的服务器都没有被杀死,但更多的服务器被创建并访问相同的资源......

var http = require("http");

var server = false,
    curPort = 8888;

function OnRequest(req,res)
    res.end("You are on port " + curPort);
    CreateServer(curPort + 1);

function CreateServer(port)
    if(server)
        server.close();
        server = false;
    
    curPort = port;
    server = http.createServer(OnRequest);
    server.listen(curPort);

CreateServer(curPort);

资源:

http://nodejs.org/docs/v0.4.4/api/http.html#server.close

【问题讨论】:

似乎浏览器可以访问自节点进程启动以来他们能够访问的任何端口。例如,我在chrome中加载页面,它在8888端口上工作,然后我在FireFox中在8888端口上加载它,它没有工作,但新端口可以。 Curl 没有表现出这种行为,并且杀死浏览器似乎会禁用对“旧”端口的访问。这是否意味着在浏览器清除缓存之前,请求永远不会真正结束? 【参考方案1】:

我测试了 close() 函数。它似乎什么都不做。服务器仍然接受他的端口上的连接。重启进程是我唯一的方法。

我使用了以下代码:

var http = require("http");

var server = false;
function OnRequest(req,res)    
    res.end("server now listens on port "+8889);
    CreateServer(8889);

function CreateServer(port)
    if(server)
        server.close();
        server = false;
    
    server = http.createServer(OnRequest);
    server.listen(port);

CreateServer(8888);

【讨论】:

嗯...这可能会导致一些问题。这是否意味着当您执行server = false 时,服务器对象不会被垃圾收集?我修改了一些代码以进一步显示这个问题。【参考方案2】:

当我决定彻底测试我的代码以查看它是否真的是一个错误时,我正要在节点 github 页面上提交一个问题(我讨厌在用户错误时提交错误报告)。我意识到这个问题只在浏览器中表现出来,因为显然浏览器做了一些奇怪的 HTTP 请求保持活动,它仍然可以访问死端口,因为仍然与服务器连接。

我学到的是:

浏览器缓存使端口保持活动状态,除非服务器上的进程被杀死 默认情况下不保留缓存的实用程序(curl、wget 等)按预期工作 节点中的 HTTP 请求也不会保留与浏览器相同类型的缓存

例如,我用这段代码来证明 node http 客户端无法访问旧端口:

客户端代码:

var http = require('http'),
    client,
    request;

function createClient (port) 
  client = http.createClient(port, 'localhost');

  request = client.request('GET', '/create');
  request.end();

  request.on('response', function (response) 
      response.on('end', function () 
          console.log("Request ended on port " + port);
          setTimeout(function () 
              createClient(port);
          , 5000);
      );
  );


createClient(8888);

和服务器端代码:

var http = require("http");

var server,
    curPort = 8888;

function CreateServer(port)
    if(server)
        server.close();
        server = undefined;
    

    curPort = port;

    server = http.createServer(function (req, res) 
        res.end("You are on port " + curPort);
        if (req.url === "/create") 
            CreateServer(curPort);
        
    );
    server.listen(curPort);
    console.log("Server listening on port " + curPort);

CreateServer(curPort);

感谢大家的回复。

【讨论】:

我会在两天后回来查看,如果我认为其他人的回答对有类似问题的人来说更彻底和有用,我会继续接受。【参考方案3】:

使用集群怎么样?

http://learnboost.github.com/cluster/docs/reload.html

看起来很有趣!

【讨论】:

感谢您的链接,它看起来很有用。这里的问题是它会杀死整个服务器,对吧?如果可能的话,我想将数据保存在内存中(比如我正在将一堆文件流式传输到一堆客户端),因为 IO 非常昂贵。

以上是关于更改端口而不丢失数据的主要内容,如果未能解决你的问题,请参考以下文章

更改 GeoServer 侦听器 IP 地址/端口

迁移 django-model 字段名称更改而不丢失数据

更改 Live App 的数据库而不丢失数据

通过迁移更改表结构而不丢失数据?

Nginx中处理重定向端口丢失问题

通过地址重写, 解决ingress在使用非标准端口(80, 443)时, 引起的重定向丢失端口问题