Der Trick dabei ist, Ihre eigene net.Listener zu implementieren. Ich habe ein Beispiel für einen Listener here (siehe waitConn und WaitListener), der Verbindungen verfolgt (aber nicht beschränkt), die Sie als Inspiration für eine Implementierung verwenden können. Es wird in etwa so geformt sein:
type LimitedListener struct {
sync.Mutex
net.Listener
sem chan bool
}
func NewLimitedListener(count int, l net.Listener) *net.LimitedListener {
sem := make(chan bool, count)
for i := 0; i < count; i++ {
sem <- true
}
return &net.LimitedListener{
Listener: l,
sem: sem,
}
}
func (l *LimitedListener) Addr() net.Addr { /* ... */ }
func (l *LimitedListener) Close() error { /* ... */ }
func (l *LimitedListener) Accept() (net.Conn, err) {
<-l.sem // acquire
// l.Listener.Accept (on error, release before returning)
// wrap LimitedConn
return c, nil
}
type LimitedConn struct { /* ... */ }
func (c *LimitedConn) Close() error {
/* ... */
c.sem <- true // release
}
Wesentlichen, was dies tut, ist eine eigene Implementierung von net.Listener zu schaffen, die Sie Serve geben können, die nur Anrufe der zugrunde liegenden Accept, wenn es den Semaphor erwerben kann; Der so erworbene Semaphor wird erst freigegeben, wenn der (entsprechend verpackte) net.Conn geschlossen ist. Beachten Sie, dass diese Verwendung des Semaphors technisch in Bezug auf die go1.2 memory model; ein einfacherer Semaphor wird in future versions von Go legal sein.
Verwendung nginx als Reverse Proxy ist am einfachsten. http://stackoverflow.com/questions/17776584/webserver-for-go-lang-webservices-using-nginx-or-not – rmmh