1.5K Star 12.1K Fork 3.3K

GVP轨迹 / J-IM

 / 详情

imClientChannelContext = jimClient.connect(serverNode); 返回为空

待办的
创建于  
2021-01-21 08:56

我觉得我找到了jim-client的一个bug,但是不知道该怎么改。

public ImClientChannelContext connect(Node serverNode, Integer timeout) throws Exception {
	log.warn("J-IM client connect");
	tioClient = new TioClient((ClientTioConfig) imClientConfig.getTioConfig());
	ClientChannelContext clientChannelContext = tioClient.connect(serverNode, imClientConfig.getBindIp(), imClientConfig.getBindPort(), timeout);
	if(Objects.nonNull(clientChannelContext)){
		log.warn("J-IM client connected success at serverAddress:[{}], bind localAddress:[{}]", serverNode.toString(), imClientConfig.toBindAddressString());
		return (ImClientChannelContext)clientChannelContext.get(ImConst.Key.IM_CHANNEL_CONTEXT_KEY);
	}
	return null;
}

里面的 clientChannelContext.get(ImConst.Key.IM_CHANNEL_CONTEXT_KEY);
这一行 很大的概率返回null

也就是 工程中
channelContext.set(Key.IM_CHANNEL_CONTEXT_KEY, imChannelContext); 执行的顺序 在 clientChannelContext.get(ImConst.Key.IM_CHANNEL_CONTEXT_KEY); 之后,我看到里面操作的是一个map,
private final MapWithLock<String, Object> props = new MapWithLock(new HashMap(8));

应该是多线程导致的

评论 (5)

lanxia 创建了任务
lanxia 关联仓库设置为轨迹/J-IM
lanxia 修改了描述
展开全部操作日志

"不是很大的概率" 是 有一定的概率,跟机器有关系。

再往下跟了一下,我想问题应该在这里

	CountDownLatch countDownLatch = new CountDownLatch(1);
	attachment.setCountDownLatch(countDownLatch);
	asynchronousSocketChannel.connect(inetSocketAddress, attachment, this.clientTioConfig.getConnectionCompletionHandler());
	boolean f = countDownLatch.await((long)realTimeout, TimeUnit.SECONDS);
	if (f) {
		return attachment.getChannelContext();
	} else {
		log.error("countDownLatch.await(realTimeout, TimeUnit.SECONDS) 返回false ");
		return attachment.getChannelContext();
	}

这里有一个睡眠,但是睡的不够

这里有好几个线程,貌似没有做线程的同步

这里有好几个线程,貌似没有做线程的同步

@lanxia 或者说同步做的不好

最后解决了,底层不敢改,只敢改上层的东西。
重写写了一个类 WJimCient(里面基本复制的JimClient中的内容)

/***
 * auth: robin
 * date: 2021/01/21
 * 这里基本复制的JimClient,没直接用JimClient的原因是,
 * clientChannelContext.get("im_channel_context_key") 很大的概率会返回null,
 * 因为里面有个map,赋值是通过多线程来完成的,如果另一个线程没有赋值的话,这里得到的就是null
 *
 */

public class WJimClient {
    private static Logger log = LoggerFactory.getLogger(JimClient.class);
    private TioClient tioClient = null;
    private ImClientConfig imClientConfig;

    public WJimClient(ImClientConfig imClientConfig) {
        this.imClientConfig = imClientConfig;
    }

    public ImClientChannelContext connect(Node serverNode) throws Exception {
        return this.connect(serverNode, (Integer)null);
    }

    public ImClientChannelContext connect(Node serverNode, Integer timeout) throws Exception {
        log.warn("J-IM client connect");
        this.tioClient = new TioClient((ClientTioConfig)this.imClientConfig.getTioConfig());
        ClientChannelContext clientChannelContext = this.tioClient.connect(serverNode, this.imClientConfig.getBindIp(), this.imClientConfig.getBindPort(), timeout);
        if (Objects.nonNull(clientChannelContext)) {
            log.warn("J-IM client connected success at serverAddress:[{}], bind localAddress:[{}]", serverNode.toString(), this.imClientConfig.toBindAddressString());
            ImClientChannelContext t_rtnContext = (ImClientChannelContext)clientChannelContext.get("im_channel_context_key");
            int t_maxCount = 200; //最大循环次数,实际测试中只循环了一次
            while (null == t_rtnContext
            && t_maxCount > 0){//这里是在等待另一个线程写入
                Thread.sleep(50);
                t_rtnContext = (ImClientChannelContext)clientChannelContext.get("im_channel_context_key");
                t_maxCount--;
            }
            System.out.println("robin:count:"+(200-t_maxCount));
            return t_rtnContext;
        } else {
            return null;
        }
    }

    public void stop() {
        this.tioClient.stop();
    }
}

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(1)
60075 lanxiaziyi oschina 1609138580
Java
1
https://gitee.com/xchao/j-im.git
git@gitee.com:xchao/j-im.git
xchao
j-im
J-IM

搜索帮助