英文:
How to limit the connections count of an HTTP Server implemented in Go?
问题
我正在尝试在Golang中实现一个HTTP服务器。
我的问题是,我必须限制任何特定时间的最大活动连接数为20。
英文:
I am trying to implement an HTTP Server in Golang.
My problem is, I have to limit the maximum active connections count at any particular time to 20.
答案1
得分: 22
你可以使用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))
英文:
You can use the netutil.LimitListener
function to wrap around net.Listener
if you don't want to implement your own wrapper:-
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))
答案2
得分: 5
这个技巧是实现自己的net.Listener。我有一个示例的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中,一个更简单的信号量也是合法的。
英文:
The trick with this is to implement your own net.Listener. I have an example of a listener here (see waitConn and WaitListener) that tracks connections (but doesn't limit them), which you can use as the inspiration for an implementation. It will be shaped something like this:
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
}
Essentially what this is doing is creating your own implementation of net.Listener that you can give to Serve that only calls the underlying Accept when it can acquire the semaphore; the semaphore so acquired is only released when the (suitably wrapped) net.Conn is Closed. Note that technically this use of the semaphore is correct with respect to the go1.2 memory model; a simpler semaphore will be legal in future versions of Go.
答案3
得分: -1
通过使用通道,您可以限制活动连接的数量。
-
在服务器启动时创建一个通道,并将相同数量的限制计数(在您的情况下为20)值放入通道中。
-
在处理一个请求时,从通道中移除一个值。
以下是来自网络的一个示例:
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", http.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
}
希望对您有所帮助!
英文:
With the help of channel you can limit the count of active connections.
1.At the server start up time create a channel and put equal number of limit count(in your case 20) values into the channel.
2.Remove one value from the channel while serving one request.
One example from the web
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论