2017-03-13 13 views
0

Redigo는 redis 데이터베이스의 골라 클라이언트입니다. 구조체 Pool을 사용하여 연결 풀을 유지 관리합니다. 이 구조체는 애플리케이션을 퍼팅하고 병렬로 연결하기위한 뮤텍스 잠금을 유지합니다.redigo 연결 풀 - 부실 연결을 제거 할 때 잠금 해제 이유

type Pool struct { 
    // ... 
    IdleTimeout time.Duration 
    mu  sync.Mutex 
    // Stack of idleConn with most recently used at the front. 
    idle list.List 
} 

get 메서드에서 연결 풀은 먼저 부실 (유휴 시간 초과) 연결을 제거합니다. 부실 연결이 발견되면 풀에서 잠금을 해제하고 잠금을 해제 한 다음 연결을 닫고 잠금을 다시 획득하려고 시도합니다.

func (p *Pool) get() (Conn, error) { 
    p.mu.Lock() 

    // Prune stale connections. 

    if timeout := p.IdleTimeout; timeout > 0 { 
     for i, n := 0, p.idle.Len(); i < n; i++ { 
      e := p.idle.Back() 
      if e == nil { 
       break 
      } 
      ic := e.Value.(idleConn) 
       if ic.t.Add(timeout).After(nowFunc()) { 
        break 
       } 
      p.idle.Remove(e) 
      p.release() 
      // Why does pool unlock and try to acquire lock again? 
      p.mu.Unlock() 
      // Close this stale connection. 
      ic.c.Close() 
      p.mu.Lock() 
     } 
    } 

풀이 잠금 해제되고 잠금 해제를 다시 시도하는 이유는 무엇입니까? 나는 연결을 닫는 것이 꽤 많은 시간을 들여서이 뮤텍스를 기다리고있는 다른 goroutine의 속도를 늦출 것이라고 생각합니다.

여기에 전체 Pool get method

+0

귀하의 추측이 맞다고 생각합니다. 연결을 끊으면 알 수없는 시간이 걸릴 수 있습니다. 이 시간 동안 풀의 모든 사용을 잠그는 것은 현명하지 않은 것처럼 보입니다. –

답변

0

닫기 연결이 뮤텍스에 대기중인 다른 goroutine이 느려지 며 꽤 많은 시간을 비용 수 있습니다. @ Cerise Limón이 말했듯이 - 이번에는 수영장 사용을 잠그는 것이 현명하지 못한 것처럼 보입니다.

뮤텍스를 잠금 해제 한 후 대기중인 goroutine 중 하나가 뮤텍스를 가져옵니다. get 메서드에 대한 goroutine은 여전히 ​​부실 연결을 제거해야하지만 put 메서드에 대한 연결은 풀에 연결하여 최대한 빨리 다른 작업을 수행 할 수 있습니다.

+0

"연결을 닫으면 꽤 ​​많은 시간이 걸릴 수 있습니다."-이 작업에는 약간의 정교함이 필요합니다. 후드에서 그것은'err : = c.fd.Close()'로 구현됩니다. 어떤 상황에서 이것이 느릴 수 있습니까? – zerkms

+0

@zerkms 솔직히 net/fd_unix.go에있는 기본 'netFD.Close'를 이해할 수 없습니다. 이론적으로, tcp가 정상적으로 종료 될 때, 각 측 (클라이언트와 서버)은 FIN을 전송하고 다른 측으로부터 ACK를 수신합니다. 이 시간 동안 네트워크 대기 시간과 패킷 손실이 발생할 수 있습니다. – lorneli