* Added connection accept rate throttling and worker job queue based request handling.
authorUrban Wallasch <urban.wallasch@freenet.de>
Wed, 10 Apr 2019 17:06:01 +0000 (19:06 +0200)
committerUrban Wallasch <urban.wallasch@freenet.de>
Wed, 10 Apr 2019 17:06:01 +0000 (19:06 +0200)
gogopherd.go

index 4cf1c288fd835e6c6aa6c5a3b0021701f5f13ef1..0b029db930f38ddef27d39f2b005feab3be5f837 100644 (file)
@@ -248,6 +248,34 @@ func handleRequest(conn net.Conn) {
 }
 
 func serveTCP(listener *net.TCPListener) {
+       // connection rate limiter
+       rate := 5
+       burst := 50
+       interval := time.Second / time.Duration(rate)
+       tick := time.NewTicker(interval)
+       defer tick.Stop()
+       throttle := make(chan time.Time, burst)
+       go func() {
+               for t := range tick.C {
+                       select {
+                       case throttle <- t:
+                       default:
+                       }
+               }
+       }()
+       // worker and job queue setup
+       nworker := 5
+       njobs := 50
+       jobs := make(chan net.Conn, njobs)
+       for w := 1; w <= nworker; w++ {
+               go func(id int, jobs <-chan net.Conn) {
+                       for j := range jobs {
+                               tracer.Print("worker id ", id, ": ", j.RemoteAddr())
+                               handleRequest(j)
+                       }
+               }(w, jobs)
+       }
+       // accept connections
        defer listener.Close()
        logger.Print("listening on TCP ", listener.Addr())
        for {
@@ -257,8 +285,9 @@ func serveTCP(listener *net.TCPListener) {
                }
                if checkFatal(err, "Accept") == nil {
                        logger.Print("connect from ", conn.RemoteAddr())
-                       go handleRequest(conn)
+                       jobs <- conn
                }
+               <-throttle
        }
 }