Serve serves incoming connections from the given listener. Serve blocks until the given listener returns permanent error.
(ln net.Listener)
| 1960 | // |
| 1961 | // Serve blocks until the given listener returns permanent error. |
| 1962 | func (s *Server) Serve(ln net.Listener) error { |
| 1963 | var lastOverflowErrorTime time.Time |
| 1964 | var lastPerIPErrorTime time.Time |
| 1965 | |
| 1966 | maxWorkersCount := s.getConcurrency() |
| 1967 | |
| 1968 | s.mu.Lock() |
| 1969 | s.ln = append(s.ln, ln) |
| 1970 | if s.done == nil { |
| 1971 | s.done = make(chan struct{}) |
| 1972 | } |
| 1973 | if s.concurrencyCh == nil { |
| 1974 | s.concurrencyCh = make(chan struct{}, maxWorkersCount) |
| 1975 | } |
| 1976 | s.mu.Unlock() |
| 1977 | |
| 1978 | wp := &workerPool{ |
| 1979 | WorkerFunc: s.serveConn, |
| 1980 | MaxWorkersCount: maxWorkersCount, |
| 1981 | LogAllErrors: s.LogAllErrors, |
| 1982 | MaxIdleWorkerDuration: s.MaxIdleWorkerDuration, |
| 1983 | Logger: s.logger(), |
| 1984 | connState: s.setState, |
| 1985 | } |
| 1986 | wp.Start() |
| 1987 | |
| 1988 | // Count our waiting to accept a connection as an open connection. |
| 1989 | // This way we can't get into any weird state where just after accepting |
| 1990 | // a connection Shutdown is called which reads open as 0 because it isn't |
| 1991 | // incremented yet. |
| 1992 | s.open.Add(1) |
| 1993 | defer s.open.Add(-1) |
| 1994 | |
| 1995 | for { |
| 1996 | c, err := acceptConn(s, ln, &lastPerIPErrorTime) |
| 1997 | if err != nil { |
| 1998 | wp.Stop() |
| 1999 | if err == io.EOF { |
| 2000 | return nil |
| 2001 | } |
| 2002 | return err |
| 2003 | } |
| 2004 | s.setState(c, StateNew) |
| 2005 | s.open.Add(1) |
| 2006 | if !wp.Serve(c) { |
| 2007 | s.open.Add(-1) |
| 2008 | s.rejectedRequestsCount.Add(1) |
| 2009 | s.writeFastError(c, StatusServiceUnavailable, |
| 2010 | "The connection cannot be served because Server.Concurrency limit exceeded") |
| 2011 | c.Close() |
| 2012 | s.setState(c, StateClosed) |
| 2013 | if time.Since(lastOverflowErrorTime) > time.Minute { |
| 2014 | s.logger().Printf("The incoming connection cannot be served, because %d concurrent connections are served. "+ |
| 2015 | "Try increasing Server.Concurrency", maxWorkersCount) |
| 2016 | lastOverflowErrorTime = time.Now() |
| 2017 | } |
| 2018 | |
| 2019 | // The current server reached concurrency limit, |