2014-12-19 31 views
1

我试图在golang中为视频流编写缓存代理。在golang中缓存网络流?

我的问题是,如何分配多个连接之间的大块数据的流式副本?

或者如何存储(缓存)并安全(快速)访问多个goroutines中的数据?

我尝试了几个选项,使用互斥锁和通道,但它们不起作用。 这里有几个与错误一起工作的示例。

这被简化版本:

... 
var clients []*client 
func new_client(conn net.Conn) { 
    client := &client{ 
     conn: conn, 
    } 
    clients = append(clients, client) 
} 
... 
func stream(source io.Reader) { 
    buf := make([]byte, 32*1024) 
    for { 
     n, _ := source.Read(buf) 
     for _, client := range clients { 
      wn, e := client.conn.Write(buf[0:n]) 
      // blocks here for all clients if one of clients stops reading 
     } 
    } 
} 

问题的这个版本是当一个客户端停止读取但犯规关闭连接,调用写()开始到框。在goroutine(使用客户端上的互斥锁)中调用Write()函数没有帮助 - 与通道(下一个示例)具有相同的延迟,此外,go不保证goroutines的执行顺序。

我试图修复它是这样的:

 for _, client := range clients { 
      client.conn.SetWriteDeadline(time.Now().Add(1 * time.Millisecond)) 
      wn, e := client.conn.Write(buf[0:n]) 
     } 

它有助于阻止,但速度缓慢的客户无法及时阅读,增加超时 - 返回延迟。

我也尝试过这样的事情:

... 
var clients []*client 
func new_client(conn net.Conn) { 
    client := &client{ 
     buf_chan: make(chan []byte, 100), 
    } 
    clients = append(clients, client) 
    for { 
     buf <- client.buf_chan 
     n, e := client.conn.Write(buf) 
    } 
} 
... 
func stream(source io.Reader) { 
    buf := make([]byte, 32*1024) 
    for { 
     n, _ := source.Read(buf) 
     for _, client := range clients { 
      client.buf_chan <- buf[0:n] 
     } 
    } 
} 

但在这个版本 - 有发送之间有一些延迟到通道和接收在另一端,所以在播放视频流开始变得拖延,滞后。

对于某些软件包可能会提出建议,或者针对这类任务设计模式?

感谢您的帮助!

回答

0

在频道版本中,慢速客户端也可能增加延迟。由于缓慢的客户端可能会使其buf_chan变满,因此写入其buf_chan将会被阻止。 Wrappper选择能避免它:

select { 
case client.buf_chan <- buf[0:n]: 
default: 
//handle slow client ...  
} 
+0

感谢,我监测buf_chan运河缓冲区的大小,它的百达1(0)读之后,我做到了缓冲只是为了测试,我认为有延迟的问题是其他地方 – user1579228