3 回答
TA贡献1850条经验 获得超11个赞
如果您不想实现自己的包装器,可以使用该netutil.LimitListener函数进行环绕net.Listener:-
connectionCount := 20
l, err := net.Listen("tcp", ":8000")
if err != nil {
log.Fatalf("Listen: %v", err)
}
defer l.Close()
l = netutil.LimitListener(l, connectionCount)
log.Fatal(http.Serve(l, nil))
TA贡献2037条经验 获得超6个赞
这个技巧是实现你自己的net.Listener。我在这里有一个监听器示例(请参阅 waitConn 和 WaitListener),它跟踪连接(但不限制它们),您可以将其用作实现的灵感。它将被塑造成这样:
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
}
本质上,这样做是创建您自己的 net.Listener 实现,您可以将其提供给Serve,它仅在可以获取信号量时调用底层 Accept;如此获取的信号量仅在(适当包装的)net.Conn关闭时才释放。请注意,从技术上讲,这种信号量的使用对于 go1.2内存模型是正确的;在Go 的未来版本中,更简单的信号量将是合法的。
TA贡献1752条经验 获得超4个赞
借助通道,您可以限制活动连接的数量。
1.在服务器启动时创建一个通道并将相同数量的限制计数(在您的情况下为 20)值放入该通道。
2.在处理一个请求时从通道中删除一个值。
网络上的一个例子
type limitHandler struct {
connc chan struct{}
handler http.Handler
}
func (h *limitHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
select {
case <-connc:
h.handler.ServeHTTP(w, req)
connc <- struct{}{}
default:
http.Error(w, "503 too busy", StatusServiceUnavailable)
}
}
func NewLimitHandler(maxConns int, handler http.Handler) http.Handler {
h := &limitHandler{
connc: make(chan struct{}, maxConns),
handler: handler,
}
for i := 0; i < maxConns; i++ {
connc <- struct{}{}
}
return h
}
- 3 回答
- 0 关注
- 299 浏览
添加回答
举报