Почему приложение зависает при использовании ReverseProxy? - PullRequest
0 голосов
/ 26 апреля 2020

Я работаю над приложением с обратным прокси-сервером и встроенным балансом нагрузки.

Когда я выполняю тесты с высокой нагрузкой, мое приложение зависает с таймаутами, возвращаемыми в инструмент тестирования.

I Воспроизведение этого поведения с минимальным кодом ниже.

proxy.go файл:

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
    "time"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Pong")
}

func newMux() *http.ServeMux {
    serverURL, _ := url.Parse("http://127.0.0.1:5000")
    proxy := httputil.NewSingleHostReverseProxy(serverURL)
    sm := http.NewServeMux()
    sm.HandleFunc("/", handler)
    sm.HandleFunc("/proxy", proxy.ServeHTTP)
    return sm
}

func main() {
    server := http.Server{
        Addr:         ":1447",
        Handler:      newMux(),
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 10 * time.Second,
    }
    log.Fatal(server.ListenAndServe())
}

backend.go файл:

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func newMux() *http.ServeMux {
    sm := http.NewServeMux()
    sm.HandleFunc("/", handler)
    return sm
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello")
}

func main() {
    server := http.Server{
        Addr:         ":5000",
        Handler:      newMux(),
        ReadTimeout:  5 * time.Second,
        WriteTimeout: 10 * time.Second,
    }
    log.Fatal(server.ListenAndServe())
}

Я делаю тесты с wrk2 инструмент с помощью этой команды:

wrk2 -t12 -c100 -d30s -R20000 http://127.0.0.1:1447/

Шаги, применяемые для подтверждения проблемы:

  1. Скомпилируйте и запустите backend.go на 5000 порту
  2. Запустите wrk2 -t12 -c100 -d30s -R20000 http://127.0.0.1:5000/, чтобы проверить обнаженный бэкэнд с 20k RPS в течение 30 секунд
  3. Через 30 секунд wrk2 покажет эту статистику 597996 requests in 30.00s, 68.44MB read
  4. Скомпилируйте и запустите proxy.go на 1447 порту
  5. Запустите wrk2 -t12 -c100 -d30s -R20000 http://127.0.0.1:1447/proxy, чтобы прокси-запросы на бэкэнд с 20k RPS продолжительностью 30 секунд
  6. Через 30 секунд wrk2 показывает эту статистику 33699 requests in 30.06s, 3.89MB read; Socket errors: connect 0, read 0, write 0, timeout 960

Я не могу понять это поведение - почему выполнение теста прямо на backend.go нормально без тайм-аутов, но проксирование запросов грубый возврат ReverseProxy почти на 94% времени ожидания?

Сравнительный тест на одном MacBook Pro в середине 2013 года с 8 ГБ ОЗУ и 2,6 ГГц Intel Core i5. Текущие настройки ulimit:

> ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 8192
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1392
virtual memory          (kbytes, -v) unlimited
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...