首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Golang超时

Golang超时
EN

Stack Overflow用户
提问于 2015-08-31 16:19:45
回答 1查看 5.2K关注 0票数 1

到目前为止,我一直在这样做:

代码语言:javascript
复制
import (
    _redis "gopkg.in/redis.v3"
    "strconv"
    "time"
)

type Redis struct {
    Connector   *_redis.Client
    PubSub      *_redis.PubSub
}

var redis *Redis = nil

func NewRedis() bool {
    if redis == nil {
        redis = new(Redis)
        redis.Connector = _redis.NewClient(&_redis.Options{
            Addr: config.RedisHostname + ":" + strconv.FormatInt(config.RedisPort, 10),
            Password: "",
            DB: 0,
        })
        Logger.Log(nil, "Connected to Redis")
        err := redis.Init()
        if err != nil {
            Logger.Fatal(nil, "Cannot setup Redis:", err.Error())
            return false
        }
        return true
    }
    return false
}

func (this *Redis) Init() error {
    pubsub, err := this.Connector.Subscribe("test")
    if err != nil {
        return err
    }
    defer pubsub.Close()
    this.PubSub = pubsub
    for {
        msgi, err := this.PubSub.ReceiveTimeout(100 * time.Millisecond)
        if err != nil {
            Logger.Error(nil, "PubSub error:", err.Error())
            err = this.PubSub.Ping("")
            if err != nil {
                Logger.Error(nil, "PubSub failure:", err.Error())
                break
            }
            continue
        }
        switch msg := msgi.(type) {
            case *_redis.Message:
                Logger.Log(nil, "Received", msg.Payload, "on channel", msg.Channel)
        }
    }
    return nil
}

我的连接器是一个redis.Client,它可以工作,因为我也能够发布消息。

当我运行我的程序时,我得到以下错误:PubSub error: WSARecv tcp 127.0.0.1:64505: i/o timeout

你知道我做错了什么吗?我正在使用这个包:https://github.com/go-redis/redis

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-31 20:03:14

有些事情要注意:

  • (实现细节)当redis进入PubSub模式时,在该套接字上发生的唯一事情是PubSub事件,这就是为什么go-redis中的PubSub被抽象成它自己的类型。
  • PubSub客户端可能订阅单个订阅服务器中的多个主题,因此始终存在订阅/取消订阅事件。
  • 接口既有Receive()方法,也有ReceiveTimeout(duration)方法,这两个方法都返回连线上的下一个事件;可以是订阅/取消订阅事件和消息事件;(您不一定知道是哪一个)它们之间唯一的区别是在出现新消息之前永远接收块,而ReceiveTimeout在超时时会出错。

考虑到这一点,除非您的消息一致地超过10/秒(换句话说,消息之间的间隔<100毫秒),否则使用这种短超时是低效的;我认为,由于戈朗有猩猩,您几乎不应该在实际的应用程序中使用ReceiveTimeout,或者像一分钟一样使用足够长的超时时间。

考虑到这一点,接收循环应该如下所示:

代码语言:javascript
复制
    for {
        msgi, err := this.PubSub.Receive()
        if err != nil {
            Logger.Error(nil, "PubSub error:", err.Error())
            return err
        }
        switch msg := msgi.(type) {
            case *_redis.Message:
                Logger.Log(nil, "Received", msg.Payload, "on channel", msg.Channel)
            default:
                Logger.Log(nil, "Got control message", msg)
        }
    }

如果您的应用程序确实需要使用超时,那么您应该使用类型断言来断言表示超时的*net.OpError,并将其与其他更严重的错误区分开来。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32315648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档