4

我们有一个 xmpp 连接服务器,它将套接字连接到 GCM XMPP 端点并开始发送通知。

我们注意到的一件事是在发送一个半大通知(比如说少至 1000 个设备)时,套接字会突然断开连接,并收到以下错误消息:

Client disconnected  socket=b913-512-904dc69, code=EPIPE, errno=EPIPE, syscall=write

例如,这是直播服务器开始向不同注册IDS发送通知时的日志。

  1. info: 发送下游消息 msgId=P#c1uq...socketId=512
  2. info: 发送下游消息 msgId=P#c3tE... socketId=512
  3. info: 发送下游消息 msgId=P#c1TF...socketId=512
  4. info: 发送下游消息 msgId=P#c3sy... socketId=512
  5. info: 发送下游消息 msgId=P#c41N... socketId=512
    ...
    1. info: 发送下游消息 msgId=P#cJbr... socketId=512
    2. info: 发送下游消息 msgId=P#cJXO...socketId=512
      info: 客户端断开socket=b913-512-904dc69, code=EPIPE, errno=EPIPE, syscall=write

这种情况在我们的系统中无时无刻不在发生,使服务质量检查变得相当困难。

我们注意到的另一件事是,有时在调用 时,会返回socket.send(stanza)值,即使套接字确实已连接。这个更糟糕,因为我们必须对消息进行重新排队,并且在发送数百万条消息时它真的很耗费资源。这将在下面解释。false

附加信息:

  1. 从第 1 条消息到第 84 条消息(发生断开连接),不到 100 毫秒过去了。

  2. 我们在 3 台不同的服务器上为此 JID/PASSWORD(在 GCM 的术语中为 senderId、Api_key)打开了大约 52 个套接字。当一个大型通知发送任务出现时(比如 10000 个收件人),所有人都会不时断开连接。

  3. 套接字成功地重新连接,但它们断开了几秒钟,这降低了我们系统的效率和可靠性。

如何设置连接:

const xmpp = require('node-xmpp-client');
let socket = new xmpp.Client({
        port: 5235,
        host: 'gcm-xmpp.googleapis.com',
        legacySSL: true,
        preferredSaslMechanism: 'PLAIN',
        reconnect: true,
        jid: $JID,
        password: $PASSWORD
});
socket.connection.socket.setTimeout(0);
socket.connection.socket.setKeepAlive(true, 10000);
socket.on('stanza', (stanza) => handleStanza(stanza));
...

收到的每条上游消息都会发送确认。
但是我们看到的一件事是,在发送下游消息时,以下内容有时会返回 false,“即使套接字已连接”

// This returns false many times! even when the socket.connection.connected === true! 
socket.send(xmppStanza)

如果发生这种情况,我们将 ack 消息排队等待稍后重试,但继续向 gcm 发送消息。

为什么socket.send有时会返回 false?(这显然不是像 EPIPE 之类的错误,它只是一个错误,意味着刷新套接字不成功,也许套接字变得不可写,即使它已连接?)。

如果确认延迟,GCM 会关闭与延迟确认的连接还是会停止向上游发送?
(AFAIK,它只会停止发送上游,所以这可能与关闭的连接(EPIPE)无关?)

如果有人能对这种行为有所了解,我将不胜感激。

谢谢 !

4

0 回答 0