Smack 4.1.0 GCM CCS 在一段时间后停止响应

Posted

技术标签:

【中文标题】Smack 4.1.0 GCM CCS 在一段时间后停止响应【英文标题】:Smack 4.1.0 GCM CCS stops responding after a while 【发布时间】:2016-04-04 08:48:36 【问题描述】:

已经为聊天模块实现了 gcm ccs,我能够发送和接收消息。下面是主要的连接模块,

        config = XMPPTCPConnectionConfiguration.builder()
                .setServiceName("gcm-pesu.googleapis.com")
                .setPort(GCM_PORT)
                .setHost(GCM_SERVER)
                .setCompressionEnabled(false)
                .setConnectTimeout(30000)
                .setSecurityMode(SecurityMode.ifpossible)
                .setSendPresence(false)
                .setSocketFactory(SSLSocketFactory.getDefault())
                .build();

        connection = new XMPPTCPConnection(config);
        connection.connect();

        Roster roster = Roster.getInstanceFor(connection);
        roster.setRosterLoadedAtLogin(false);

        connection.addConnectionListener(new LoggingConnectionListener());

        // Handle incoming packets
        connection.addAsyncStanzaListener(new MyStanzaListener(), new MyStanzaFilter());

        // Log all outgoing packets
        connection.addPacketInterceptor(new MyStanzaInterceptor(), new MyStanzaFilter());

        connection.login(mProjectId + "@gcm.googleapis.com", mApiKey);
        logger.info("logged in: " + mProjectId);

        PingManager pm = PingManager.getInstanceFor(connection);
        pm.setPingInterval(300);
        pm.pingMyServer();
        pm.registerPingFailedListener(new PingFailedListener() 
            @Override
            public void pingFailed() 
                connection.disconnect();
                logger.error("GCM CCS, Ping failed !!");
            
        );

我遇到的问题是一段时间后没有从 GCM 接收到客户端设备发送的任何消息。不过,心跳看起来很正常,即使在这种情况下,我也确实从 GCM 获得了乒乓球。这与 SSL 有关吗?

如下处理了连接耗尽的情况,

        String controlType = (String) jsonObject.get("control_type");
        volatile boolean connectionDraining = false;
        if ("CONNECTION_DRAINING".equals(controlType)) 
            connectionDraining = true;
            try 
                connection.disconnect();
                connect();
                connectionDraining = false;
             catch (Exception e) 
                logger.error("Error establishing new connection after draining ", e);
            
        

【问题讨论】:

【参考方案1】:

当其中一个正在耗尽时,实现了通道队列。

            private Deque<Channel> channels;
            protected void handleControlMessage(Map<String, Object> jsonObject) 
            logger.info("Control message : " + jsonObject);
            String controlType = (String) jsonObject.get("control_type");
            if ("CONNECTION_DRAINING".equals(controlType)) 
                connectionDraining = true;
             
        

发送消息时创建新频道

        public void sendDownstreamMessage(String jsonRequest) 
        Channel channel = channels.peekFirst();
        try 
            if (channel.connectionDraining) 
                synchronized (channels) 
                    channel = channels.peekFirst();
                    if (channel.connectionDraining) 
                        channels.addFirst(connect());
                        channel = channels.peekFirst();
                    
                
            
            channel.send(jsonRequest);
         catch (Exception e) 
            logger.error("Message not sent. Error in connecting :", e);
        
    

GCM 将负责关闭另一个。这解决了问题。

【讨论】:

【参考方案2】:

我相信您正面临使用 gcm css 的常见情况,这在文档中不是很明显。 如果你查看文档,Control Messages 你会读到:

CCS 需要定期关闭连接以执行负载平衡。在关闭连接之前,CCS 会发送一个 CONNECTION_DRAINING 消息,表示连接正在耗尽,即将关闭。 “Draining”是指关闭进入连接的消息流,但允许管道中已经存在的任何内容继续。当您收到 CONNECTION_DRAINING 消息时,您应该立即开始向另一个 CCS 连接发送消息,必要时打开一个新连接。但是,您应该保持原始连接打开并继续接收可能来自连接的消息(并确认它们) - CCS 会在连接准备好时处理启动连接。

【讨论】:

也实现了连接耗尽逻辑。在上面的帖子中添加了这一点,请检查是否正确。 当您收到 CONNECTION_DRAINING 消息时,您应该立即开始向另一个 CCS 连接发送消息,必要时打开一个新连接。但是,您应该保持原始连接打开。 ...不要关闭连接,启动一个新连接并等待旧连接被谷歌关闭。

以上是关于Smack 4.1.0 GCM CCS 在一段时间后停止响应的主要内容,如果未能解决你的问题,请参考以下文章

使用 Smack 4.1.0 的 GCM XMPP 服务器 - 需要添加哪些 jar

Google CCS (GCM) - 项目未列入白名单

GCM 和 Smack API

GCM CCS 上游消息是不是强制重新连接到 GCM 网络?

无法使用 XMPPHP 将我的应用服务器连接到 GCM 的 CCS [关闭]

如何在 slimxmpp python 中为 gcm ccs 请求创建 xmpp 节?