Как справиться с внезапным всплеском новых подключений HTTPS?

У меня есть парк серверов Java Vertx за балансировщик нагрузки, который обрабатывает пиковый трафик. В одну минуту он может обрабатывать 150 000 об / мин, в следующую минуту он может обрабатывать 2 мм об / мин, а затем сразу же снова снижается до 150 000 об / мин. Я обнаружил, что во время этих всплесков весь парк может перестать отвечать на запросы в течение нескольких минут и обрывать соединения, в то время как давление процессора и памяти на любой из блоков едва достигает 50% использования.

Чтобы проверить, что именно является причиной сбоя, я настроить один тестовый сервер, который соответствует спецификациям одного в моем производственном парке, чтобы посмотреть, сколько я могу на него выложить, прежде чем он сработает. Мой тест включает использование 10 других машин, каждая из которых открывает 500 https-соединений с сервером и отправляет 1-миллиметровые запросы размером около 2 Кбайт на каждый запрос. Это всего 5k одновременных открытых подключений, отправка в общей сложности 10-миллиметровых запросов для примерно 20 ГБ данных.

После открытия подключений я могу отправлять около 700 тыс. Запросов в минуту. Я отслеживаю доступность серверов, просто отправляя запрос в конечную точку работоспособности и записывая время ответа. Время отклика быстрое, десятки миллисекунд. Я доволен этими результатами.

Но прежде чем начнется поток данных, эти 10 машин должны сначала установить 5 тыс. Соединений. В это время сервер не отвечает и может даже выйти из строя, когда я пытаюсь проверить конечную точку работоспособности. Я считаю, что именно это вызывает перебои в работе моего производственного парка - внезапное увеличение количества новых подключений. После того, как соединения установлены, у сервера не возникает проблем с обработкой всех входящих данных.

Я обновил nofile ulimit, net.core.netdev_max_backlog, net.ipv4.tcp_max_syn_backlog и net.core.somaxconn, но он по-прежнему зависает при получении пакета из 5 тыс. новых запросов на подключение с интервалом в несколько секунд.

Могу ли я что-нибудь сделать, чтобы установить новые подключения быстрее?

Изменить:

Фактический сервер работает в докере контейнер. Мои сетевые настройки не применяются к контейнеру. Собираюсь попробовать это в следующий раз и посмотреть, имеет ли это значение.

Edit Edit:

Это все в SSL. Создание такого количества соединений, которые быстро выполняются через простой HTTP, практически мгновенно. Так что мне нужно выяснить, как быстрее устанавливать TLS-соединения.

Править Править Править:

Я обнаружил, что узким местом был собственный обработчик ssl безопасности Java. Переход на netty-tcnative (также известный как собственный OpenSSL) в значительной степени решил мою проблему с HTTPS.

6
задан 2 July 2020 в 01:32
2 ответа

Eskerrik asko @ MichaelHampton zure laguntzagatik.

Nire arazoari irtenbide bat aurkitu diot, eta espero dut besteei lagundu diezaiekeela (bereziki Java erabiltzen ari bazara).

Entzun dut iradokizun asko fitxategiak konexio gehiago ahalbidetzeko handitzeko, baina hasiera batean berriro esan nahiko nuke arazoa ez dela zerbitzaria konexio gehiago egiteko gai ez dela, ez da gai konexioak nahikoa azkar eta konexioak erortzen.

Arazo hau konpontzeko nire lehen saiakera konexio ilara handitzea izan zen net.ipv4.tcp_max_syn_backlog , net.core.somaxconn eta berriro aplikazioaren zerbitzariaren konfigurazioa egoki denean. Vertx-entzat hau da: server.setAcceptBacklog (...); . Horrek ilaran konexio gehiago onartzea ekarri zuen, baina ez zuen konexioak azkarrago ezarri. Konektatzen ari den bezeroaren ikuspuntutik, jada ez ziren konexioak berrezarri gainezkatzeagatik, konexioak ezartzea askoz ere gehiago behar izan zen. Hori dela eta, konexio ilara handitzea ez zen benetako irtenbidea eta arazo bat beste batekin trukatu besterik ez nuen.

Konexio prozesuan botila lepoa non zegoen murriztu nahian, erreferente berdinak probatu nituen HTTPrekin HTTPSren ordez eta aurkitu nuen arazoa guztiz desagertu zela. Nire arazo partikularra TLS Handshake bera eta zerbitzariak asetzeko gaitasuna izan zen.

Nire aplikazioan gehiago sakondu nuenean, aurkitu nuen Javas SSLHandler lehenetsia jatorrizko batekin (OpenSSL) ordezkatzeak asko konektatzen zuela bidez konektatzeko abiadura HTTPS.

Hona hemen nire aplikazio zehatzerako egin ditudan aldaketak (Vertx 3.9.1 erabiliz).

  1. Gehitu mendekotasun txikiak
<!-- https://mvnrepository.com/artifact/io.netty/netty-tcnative -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-tcnative</artifactId>
    <version>2.0.31.Final</version>
    <classifier>osx-x86_64</classifier>
    <scope>runtime</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/io.netty/netty-tcnative -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-tcnative</artifactId>
    <version>2.0.31.Final</version>
    <classifier>linux-x86_64-fedora</classifier>
    <scope>compile</scope>
</dependency>

Lehenengo mendekotasuna osxek exekuzio garaian probatzea da. Bigarrena centos linux-entzat konpilatzean. linux-x86_64 beste zapore batzuetarako ere eskuragarri dago. boringssl erabiltzen saiatu naiz openssl ez delako onartzen ALPN baina ordu asko igaro ondoren ezin izan dut funtzionatu, beraz bizitzea erabaki dut http2 oraingoz. Konexio gehienekin 1- bidaltzen dute soilikHau deskonektatu aurretik 2 eskaera txiki ez dira niretzat arazoa, hala ere. Horren ordez boringssl erabiliko bazenu, hori nahiago izango duzu seguruenik.

  1. Ez dudalako mendekotasunaren bertsio uberik erabiltzen. Zentosentzako osasunaren mendekotasunak instalatu behar nituen. Hau Dockerfile fitxategian gehitu zen
RUN yum -y install openssl
RUN yum -y install apr
  1. Vertx zerbitzariari Java bertsioaren ordez OpenSSL erabiltzeko esateko, ezarri zerbitzarian OpenSSL aukerak (nahiz eta objektu lehenetsia besterik ez izan)
httpServerOptions.setOpenSslEngineOptions(new OpenSSLEngineOptions());
  1. Azkenean, nire exekuzio scriptean, gehitu nuen io.netty.handler.ssl.openssl.useTasks = true aukera Javan. Honek ssl kudeatzaileari eskaerak kudeatzerakoan zereginak erabiltzeko esaten dio, blokeatu ez dadin.
java -Dio.netty.handler.ssl.openssl.useTasks=true -jar /app/application.jar

Aldaketa hauen ondoren, konexioak askoz azkarrago ezartzeko gai naiz gainkarga txikiagorekin. Aurretik hamar segundo behar izan zituenak eta maiz konexioak berrezartzea eragin zuenak 1-2 segundo behar ditu berrezarri gabe. Hobea izan liteke, baina ni nengoen aldetik hobekuntza handia.

5
ответ дан 4 January 2021 в 07:23

Хорошее исправление!

Так что, похоже, это уровень SSL, он, безусловно, должен выполнять гораздо больше обработки в терминах сетевых рукопожатий и криптографических преобразований, требующих ресурсов. Если ваш SSL не может переложить часть обработки на оборудование, SSL определенно может увеличить нагрузку на ваши серверы, и, как вы выяснили, не все библиотеки SSL созданы одинаковыми!

Эти проблемы являются отличным кандидатом для внешнего обратного прокси. . В идеале это может быть размещено перед вашим приложением и обрабатывать все SSL-соединения с клиентами, а затем делать http для вашей серверной части.

У вашего исходного приложения немного меньше задач, так как ваш внешний обратный прокси-сервер может поглотить все работа SSL и управление TCP-соединениями.

Apache и NGNIX могут это делать и имеют довольно много вариантов для балансировки нагрузки этих соединений с наименее загруженным внутренним сервером.

Вы обнаружите, что NGNIX может выполнять завершение SSL намного быстрее, чем Java, и даже если Java может, вы распределяете обработку управления подключением между машинами, тем самым уменьшая нагрузку (память / cpu / disk io) на ваш внутренний сервер. Вы получаете побочный эффект упрощения конфигурации серверной части.

Обратной стороной является использование вами http между вашим прокси и приложениями, что в некоторых сверхзащищенных средах нежелательно.

Удачи!

2
ответ дан 4 January 2021 в 07:23

Теги

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