Browse Source

Add concurrency

DarthSim 7 years ago
parent
commit
9163e3f4ed
4 changed files with 28 additions and 4 deletions
  1. 1 0
      README.md
  2. 8 2
      config.go
  3. 1 1
      main.go
  4. 18 1
      server.go

+ 1 - 0
README.md

@@ -85,6 +85,7 @@ You can easily generate key and salt with `openssl enc -aes-256-cbc -P -md sha25
 * IMGPROXY_BIND - TCP address to listen on. Default: :8080;
 * IMGPROXY_READ_TIMEOUT - the maximum duration (seconds) for reading the entire request, including the body. Default: 10;
 * IMGPROXY_WRITE_TIMEOUT - the maximum duration (seconds) for writing the response. Default: 10;
+* IMGPROXY_CONCURRENCY - the maximum images to be processed simultaneously. Default: 100;
 
 #### Security
 

+ 8 - 2
config.go

@@ -62,8 +62,8 @@ type config struct {
 	Bind         string
 	ReadTimeout  int
 	WriteTimeout int
-
-	TTL int
+	Concurrency  int
+	TTL          int
 
 	MaxSrcDimension int
 
@@ -80,6 +80,7 @@ var conf = config{
 	Bind:            ":8080",
 	ReadTimeout:     10,
 	WriteTimeout:    10,
+	Concurrency:     100,
 	TTL:             3600,
 	MaxSrcDimension: 4096,
 	Quality:         80,
@@ -94,6 +95,7 @@ func init() {
 	strEnvConfig(&conf.Bind, "IMGPROXY_BIND")
 	intEnvConfig(&conf.ReadTimeout, "IMGPROXY_READ_TIMEOUT")
 	intEnvConfig(&conf.WriteTimeout, "IMGPROXY_WRITE_TIMEOUT")
+	intEnvConfig(&conf.Concurrency, "IMGPROXY_CONCURRENCY")
 
 	intEnvConfig(&conf.TTL, "IMGPROXY_TTL")
 
@@ -129,6 +131,10 @@ func init() {
 		log.Fatalf("Write timeout should be greater than 0, now - %d\n", conf.WriteTimeout)
 	}
 
+	if conf.Concurrency <= 0 {
+		log.Fatalf("Concurrency should be greater than 0, now - %d\n", conf.Concurrency)
+	}
+
 	if conf.TTL <= 0 {
 		log.Fatalf("TTL should be greater than 0, now - %d\n", conf.TTL)
 	}

+ 1 - 1
main.go

@@ -9,7 +9,7 @@ import (
 func main() {
 	s := &http.Server{
 		Addr:           conf.Bind,
-		Handler:        httpHandler{},
+		Handler:        newHttpHandler(),
 		ReadTimeout:    time.Duration(conf.ReadTimeout) * time.Second,
 		WriteTimeout:   time.Duration(conf.WriteTimeout) * time.Second,
 		MaxHeaderBytes: 1 << 20,

+ 18 - 1
server.go

@@ -16,7 +16,13 @@ import (
 	"time"
 )
 
-type httpHandler struct{}
+type httpHandler struct {
+	sem chan struct{}
+}
+
+func newHttpHandler() httpHandler {
+	return httpHandler{make(chan struct{}, conf.Concurrency)}
+}
 
 func parsePath(r *http.Request) (string, processingOptions, error) {
 	var po processingOptions
@@ -134,9 +140,20 @@ func checkSecret(s string) bool {
 	return strings.HasPrefix(s, "Bearer ") && subtle.ConstantTimeCompare([]byte(strings.TrimPrefix(s, "Bearer ")), []byte(conf.Secret)) == 1
 }
 
+func (h *httpHandler) lock() {
+	h.sem <- struct{}{}
+}
+
+func (h *httpHandler) unlock() {
+	defer func() { <-h.sem }()
+}
+
 func (h httpHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
 	log.Printf("GET: %s\n", r.URL.RequestURI())
 
+	h.lock()
+	defer h.unlock()
+
 	t := time.Now()
 
 	if !checkSecret(r.Header.Get("Authorization")) {