haproxy - настройка кеша TCP-соединения для HTTP-сервера

2118
mathieu

Я пытаюсь настроить локальный кэш TCP-подключения, чтобы обеспечить доступ к удаленному HTTP-серверу для нескольких локальных приложений.

Я начал настраивать haproxy для этого:

global log /dev/log local0 pidfile /var/run/haproxy.pid maxconn 4000 daemon stats socket /var/lib/haproxy/stats  defaults log global mode http option http-keep-alive timeout http-keep-alive 60000ms timeout connect 5000ms timeout client 50000ms timeout server 50000ms  frontend http-in option httplog bind 127.0.0.1:4443 default_backend facebook  backend facebook server fb graph.facebook.com:443 maxconn 32 ssl verify none 

что должно позволить мне использовать локальный прокси ( http: // localhost: 4443 ) для общения с https://graph.facebook.com

И да, это вроде работает:

$ curl -4 -x http://127.0.0.1:4443 -vvv 'http://graph.facebook.com/v2.4/me?fields=id%2Cname&access_token=CAACEdEose0cBAPvPqQIAjacV1whsrRfcchVVOXZAgi9ZC56HBVOh5PfI9IZBA12nAmsu9Q9Pznv1e6iZBsnbr4u2nCASnvZBGimBjdWErUXTRQetn0fdV0HLZB68tS0idelR35ybiWnehK5oec9dM9LxjRvFwTpuHSUkeA9nBAyFZBrGf4FcZAXuhT2uj5vjbvYkzupyi4mBFlBGfBEIjpeb' 

Однако, когда я запускаю tcpdump своего локального интерфейса, чтобы посмотреть, что происходит на graph.facebook.com, я вижу, что каждый раз, когда я выполняю вышеизложенное, создается новое TCP-соединение:

19:06:34.409962 IP (tos 0x0, ttl 64, id 51970, offset 0, flags [DF], proto TCP (6), length 60) 192.168.1.80.42560 > 31.13.64.1.https: Flags [S], cksum 0xc6fe (correct), seq 1868596651, win 29200, options [mss 1460,sackOK,TS val 37375657 ecr 0,nop,wscale 7], length 0 19:06:34.486631 IP (tos 0x0, ttl 86, id 0, offset 0, flags [DF], proto TCP (6), length 60) 31.13.64.1.https > 192.168.1.80.42560: Flags [S.], cksum 0xc226 (correct), seq 2991458091, ack 1868596652, win 13980, options [mss 1410,sackOK,TS val 3177564556 ecr 37375657,nop,wscale 8], length 0 19:06:34.486705 IP (tos 0x0, ttl 64, id 51971, offset 0, flags [DF], proto TCP (6), length 52) 192.168.1.80.42560 > 31.13.64.1.https: Flags [.], cksum 0x262d (correct), seq 1, ack 1, win 229, options [nop,nop,TS val 37375733 ecr 3177564556], length 0 19:06:34.486852 IP (tos 0x0, ttl 64, id 51972, offset 0, flags [DF], proto TCP (6), length 569) 192.168.1.80.42560 > 31.13.64.1.https: Flags [P.], cksum 0x2730 (correct), seq 1:518, ack 1, win 229, options [nop,nop,TS val 37375733 ecr 3177564556], length 517 19:06:34.578182 IP (tos 0x0, ttl 86, id 52940, offset 0, flags [DF], proto TCP (6), length 52) 31.13.64.1.https > 192.168.1.80.42560: Flags [.], cksum 0x2474 (correct), seq 1, ack 518, win 59, options [nop,nop,TS val 3177564650 ecr 37375733], length 0 ... 

Отсюда мой вопрос: что я тут не так сделал? Я хотел бы, чтобы мой локальный haproxy-сервер как можно дольше оставался открытым TCP-подключением к graph.facebook.com, чтобы иметь возможность повторно использовать их для нескольких клиентов и запросов, но похоже, что haproxy создает и разрывает TCP-подключения по мере необходимости, несмотря на опция http-keep-alive.

Есть идеи ?

2

1 ответ на вопрос

1
nKn

Согласно документации HAproxy, конкретно в 1.1. The HTTP transaction modelразделе, говорит следующее:

По умолчанию HAProxy работает в туннельном режиме в отношении постоянных соединений: для каждого соединения он обрабатывает первый запрос и перенаправляет все остальное (включая дополнительные запросы) на выбранный сервер. После установления соединение сохраняется как на стороне клиента, так и на стороне сервера. Используйте параметр «http-server-close», чтобы сохранить постоянные соединения клиента при индивидуальной обработке каждого входящего запроса, отправляя их один за другим на серверы в режиме HTTP close. Используйте «параметр httpclose», чтобы переключить обе стороны в режим закрытия HTTP. «option forceclose» и «option http-pretend-keepalive» помогают работать с серверами, которые плохо работают в режиме закрытия HTTP.

Вы определили http-keep-aliveдирективу и не использовали ни один из описанных выше параметров, поэтому вы должны работать в туннельном режиме (кроме того, у меня есть несколько конфигураций HAproxy, очень похожих на вашу, и я могу заверить вас, что это работает, как сказано в документации).

Я думаю, что виновником является то, как вы используете curlдля тестирования вашей конфигурации. Вы передаете ему -xфлаг, который означает, что вы хотите использовать следующий параметр в качестве прокси, однако HAproxy уже действует как это. Поэтому запрос должен быть примерно таким:

curl 'http://127.0.0.1:4443/v2.4/me?fields=id%2Cname&access_token=CAACEdEose0cBAPvPqQ‌​IAjacV1whsrRfcchVVOXZAgi9ZC56HBVOh5PfI9IZBA12nAmsu9Q9Pznv1e6iZBsnbr4u2nCASnvZBGim‌​BjdWErUXTRQetn0fdV0HLZB68tS0idelR35ybiWnehK5oec9dM9LxjRvFwTpuHSUkeA9nBAyFZBrGf4Fc‌​ZAXuhT2uj5vjbvYkzupyi4mBFlBGfBEIjpeb 

Таким образом, вы отправляете запрос непосредственно в HAproxy и не используете HAproxy в качестве прокси (потому что он будет вести себя так же).

Я попробовал согласно предложению, но получаю следующее: <HTTP / 1.1 301 Постоянно перемещено <Местоположение: http://www.facebook.com/ <X-Content-Type-Options: nosniff <Content-Type: text / html < Отладка по X-FB: cPfFb58L4BkZsGHfyVA5TFuZ7b8cgcrY1jWYulBRk + YB22vv8Q9swKTA9jGUnxs58ZEoK1sxY7DqaOfmwyqQxQ == <дата: время: 07: 00: 00: 00: 07: 00: 00: 00: 00: 00: 00: 00: 02: 44 mathieu 9 лет назад 0
Вероятно, какой-то пропущенный вариант с `curl`. Лучший способ проверить это доступ непосредственно к веб-браузер и открытие `HTTP: // your_haproxy_ip: 4443 / v2.4 / мне поля = ID% 2Cname & access_token = CAACEdEose0cBAPvPqQ IAjacV1whsrRfcchVVOXZAgi9ZC56HBVOh5PfI9IZBA12nAmsu9Q9Pznv1e6iZBsnbr4u2nCASnvZBGim BjdWErUXTRQetn0fdV0HLZB68tS0idelR35ybiWnehK5oec9dM9LxjRvFwTpuHSUkeA9nBAyFZBrGf4Fc ZAXuhT2uj5vjbvYkzupyi4mBFlBGfBEIjpeb` nKn 9 лет назад 0
Я написал следующий тестовый скрипт на Python: http://paste.ubuntu.com/12519941/ поэтому я получаю правильный ответ из запроса GET, но tcpdump по-прежнему показывает SYN + RST для facebook.com для каждого запроса http: // paste.ubuntu.com/12519949/ mathieu 9 лет назад 0
Чтобы пояснить приведенный выше комментарий, AFAICT, я вижу, что haproxy поддерживает соединение на стороне сервера, но только в течение времени соединения TCP на стороне клиента. то есть кажется, что он не может поддерживать соединение на стороне сервера открытым для нескольких HTTP-запросов в нескольких TCP-соединениях. mathieu 9 лет назад 0
Это странно. Если запросы выполняются с разницей в интервалах менее 50 секунд, они не должны выполняться по разным TCP-соединениям, они должны использовать одно и то же. Единственное подозрение, которое у меня осталось, заключается в том, что интервалы времени ожидания клиента и сервера мешают друг другу. Еще одним интересным тестом будет попытка использовать сайт, отличный от Facebook, чтобы проверить, работает ли он так же. nKn 9 лет назад 0
тот же тест с простым http-сервером, тот же результат. Конфигурация: http://paste.ubuntu.com/12521224/ Тестовый скрипт: http://paste.ubuntu.com/12521231/ tcpdump для двух последовательных запросов на двух отдельных соединениях tcp на стороне клиента запускает два отдельных соединения tcp с сервером с помощью haproxy: http://paste.ubuntu.com/12521242/ mathieu 9 лет назад 0
Интересно. Какую версию ты используешь? Я попробовал ваш пример с минимальными изменениями и туннель остается открытым для дальнейших запросов. nKn 9 лет назад 0
версия: 1.5.14, FC22 mathieu 9 лет назад 0
Я использую 1.4.24 на Ubuntu 14.04, мне интересно, имеет ли это значение, но, как я уже сказал, в моем случае все работает как положено. nKn 9 лет назад 0
Хорошо, хорошо, я все еще не нашел решения своей проблемы, но я чувствую, что было бы справедливо присудить вам награду, учитывая вашу обширную помощь в отладке этого. mathieu 9 лет назад 0
Спасибо! Дайте мне знать, если я смогу помочь вам с дополнительным тестом nKn 9 лет назад 0

Похожие вопросы