3
func handleForServer1(res http.ResponseWriter, req *http.Request) {
    rPayload := parseRequestBody(req)
    serve("http://server1:8080", res, req)
}

func handleForServer2(res http.ResponseWriter, req *http.Request) {
    rPayload := parseRequestBody(req)
    serve("http://server2:8080", res, req)
}

func serve(dest string, res http.ResponseWriter, req *http.Request) {
    url, _ := url.Parse(dest)
    p := httputil.NewSingleHostReverseProxy(url)

    req.URL.Host = url.Host
    req.URL.Scheme = url.Scheme
    req.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))
    req.Host = url.Host

    p.ServeHTTP(res, req)
}

I have a code like above. I'm wondering if there's a way to find out how many concurrent connections does handler "handleForServe2" has?

Goal for that code is making a reverse proxy function. But, also I'd like to add balance loading based on concurrent connections per server that is connected to.

Thank you so much!

Gon
  • 733
  • 3
  • 8
  • 23
  • 1
    See [Process Management for the Go Webserver](https://stackoverflow.com/a/37531953/1705598). – icza Apr 19 '19 at 14:38

1 Answers1

3

One way could be to approximate this number by explicitly counting the number of concurrent invocations. This may not be sufficient, as it can only tell you how many times handleForServe2 is being invoked. To illustrate:

mu sync.RWMutex
concurrentInvocations := 0

func handleForServer2(res http.ResponseWriter, req *http.Request) {
    mu.Lock()
    concurrentInvocations++
    mu.Unlock()

    defer func() {
       mu.Lock()
       concurrentInvocations--
       mu.Unlock()
    }()

    rPayload := parseRequestBody(req)
    serve("http://server2:8080", res, req)
}
ticker := time.NewTicker(5 * time.Second)
for {
   select {
     case <- ticker.C:
       mu.RLock()
       fmt.Printf("Current %d concurrent requests\n", concurrentInvocations)
       mu.RUnlock()
   }
}

Now at anytime, you should be able to see the number of concurrent invocations of handleForServer2. If this is sufficient, it probably needs to be extended to keep track of each server/handler's capacity.

dm03514
  • 54,664
  • 18
  • 108
  • 145
  • 1
    1. Thanks for your comment dm30514, I have a question. In your example, you have used RWMutex. Do we have to use some Mutex? 2. For second example, you have RLock then print number and Unlock. Even for reading the count, do you have to lock it? – Gon Apr 19 '19 at 16:32
  • Maybe :p. Not strictly for your exact example. Are you executing `handleForServer2` in the context of a go HTTP server (i was assuming you were)? If so, then yes some sort of synchronization is required. This is because go's http Server will invoke each handler in a separate go routine (concurrently). For the second example, I was just trying to show that synchronization is required for using the variable too. Like you pointed out if this is the only reader than I think `RLock` is silly because it won't ever have concurrent reads :) – dm03514 Apr 19 '19 at 16:43
  • Thank you so much! – Gon Apr 19 '19 at 18:55