Closed wuhelong closed 2 years ago
对是有问题研究中
因为超时有1两分钟, 客户端有可能已经重新启动了,如果使用相同ID就会导致出错
type signals int32
var heartbeatSignals = new(interface{})
var clearBeforeSignals int32 = 0
// Publish the hprose push topic
func (service *BaseService) Publish(
topic string,
timeout time.Duration,
heartbeat time.Duration) Service {
if timeout <= 0 {
timeout = service.Timeout
}
if heartbeat <= 0 {
heartbeat = service.Heartbeat
}
t := newTopic(heartbeat)
service.topicLock.Lock()
service.topics[topic] = t
service.topicLock.Unlock()
return service.AddFunction(topic, func(id string) interface{} {
message := t.get(id)
cid := signals(atomic.AddInt32(&clearBeforeSignals, 1))
if message == nil {
message = make(chan interface{})
t.put(id, message)
fireSubscribeEvent(topic, id, service)
}
select {
case message <- cid:
default:
}
receiveMessage:
select {
case result := <-message:
if result == heartbeatSignals {
goto receiveMessage
}
if result == cid {
goto receiveMessage
}
switch result.(type) {
case signals:
return nil
}
return result
case <-time.After(timeout):
go func() {
select {
case message <- heartbeatSignals:
break
case <-time.After(t.heartbeat):
service.offline(t, topic, id)
}
}()
return nil
}
}, Options{})
}
这样可以不
这个应该不是单纯改服务器能解决的,需要客户端配合才行。比如当第一个客户端还未超时,第二个客户端连上来时,服务器端返回一个特定异常,第一个客户端如果收到这个异常时,就不再重试。如果第一个客户端已经关掉了,当然也就收不到这个异常,也不会重试,这样的话,就可以解决你说的问题了。但是这需要客户端和服务器端都做修改才行,每种语言的实现都需要修改才能通用。
在不做修改的情况下,客户端最好是不要用同样的 id 比较好。
当前我使用AccessToken作为ID每个设备是有不同ID的,只是想避免同一客户端多次发送订阅会导致的故障。当前实现,如果在android系统客户端因为内存不足被系统停止,然后在服务器超时前客户端重新启动并发起订阅使用之前的相同AccessToken就会出错,服务器发送的消息会被之前已经断开的连接接收,新的连接无法接收到消息。
是会有这个问题,所以如果要用同一个 ID,还不产生问题,只能服务器和客户端都做修改才行。最近打算写 Hprose 3.0,这个推送到时候一起升级吧。
还有什么好的建议,欢迎提出哈。
这是一个好消息 如果提供一个机制可以在方法被调用时取得上下文会比较好,例如在调用方法时如果第一个参数是预定义的上下文类型,就把上下文发送过去 比如现在如果想获得调用方IP当前好像不能实现(新手如果可以请指正) 如果可以集成身份验证就更好了 谢谢
方法调用时,服务器端的方法可以将最后一个方法定义为上下文对象,客户端不需要传入,服务器端会自动把上下文对象传入。所以,你在服务器端的方法中可以方便的存取上下文。只不过现在服务器端上下文和客户端上下文是独立的。Hprose 3.0 会增加一个客户端和服务器端共享的上下文,相当于http的Header,但是它是独立于Http的,在任何底层协议上都可以传递。
当前以及支持了吗?刚刚我测试好像不可用
当前还不支持,Hprose 3.0 目前还在方案设计阶段:https://github.com/hprose/hprose/issues/6 你可以来贡献你的想法和解决方案。
使用Hprose时,最近正好用到了推送的功能,看到了这个问题,现在还没出3.0,我在想,可以通过业务上的处理来暂时规避掉这个问题。只要在订阅的ID中的AccessToken前面或者后面加一段uuid,这样既保证了每次订阅的ID里都有固定的Token信息,也保证了不会出现完全重复的id导致交替连接的情况。
现在 3.0 已经出来了,这个问题可以关闭了。
超时之后客户端会重新发起请求,这样修改之后,第二个请求会让第一个请求立即返回 nil,而第一个请求返回之后,会立即发起重试,重试的请求又会立刻让第二个请求立即返回 nil,然后就会两个请求不断的交替返回 nil 了。这样不对吧。
所以,第一次推送请求没有超时之前,不应该发起第二次请求才对。