Статьи

Повышение производительности SSL в MySQL

Это сообщение  написано Эрни Сухрада из MySQL Performance Blog.

ПРИМЕЧАНИЕ. Это первая часть серии из двух частей, посвященных влиянию на производительность использования шифрования данных в полете.

Некоторые из вас могут вспомнить мой вебинар по безопасности в середине августа; один из последующих вопросов, которые мне задавали, касался влияния производительности на соединение SSL. Мой ответ был 25%, основываясь на некоторых данных 2011 года, которые я видел на веб-сайте yaSSL, но я включил предостережение о том, что оно зависит от рабочей нагрузки, потому что наиболее дорогой частью использования SSL является установление соединения. Вскоре после этого я получил запрос на проведение более конкретных тестов, связанных с использованием SSL в MySQL, и сегодня я собираюсь показать результаты.

Во-первых, среда тестирования. Все тесты проводились на процессоре Intel Core i7-2600K 3,4 ГГц (8 ядер, включая HT) с 32 ГБ оперативной памяти и CentOS 6.4. Дисковая подсистема представляет собой двухдисковый RAID-0 твердотельных накопителей Samsung 830, хотя, поскольку мы занимаемся только измерением накладных расходов, добавляемых с помощью соединений SSL, мы будем проводить тесты только для чтения с набором данных, который полностью вписывается в буферный пул. Версия MySQL, используемая для этого эксперимента, — Community Edition 5.6.13, а инструменты тестирования — sysbench 0.5 и Perl. Мы проводим два теста, каждый из которых предназначен для имитации одного из самых распространенных шаблонов использования MySQL. Сначала мы исследуем пул соединений, часто встречающийся в мире Java, где некоторый небольшой набор соединений устанавливается, например, контейнером сервлета, а затем просто передается приложению по мере необходимости,и один запрос на соединение, типичный для мира LAMP, где сценарий, отображающий данную страницу, может подключиться к базе данных, выполнить несколько запросов и затем отключиться.

Тест 1: пул соединений

Для первого теста я запустил sysbench в режиме только для чтения с уровнями параллелизма 1, 2, 4, 8, 16 и 32 потоков, сначала без шифрования, а затем с включенным SSL и длиной ключей 1024, 2048 и 4096. биты. Было подготовлено 8 таблиц sysbench, каждая из которых содержит 100 000 строк, в результате чего общий объем данных составил около 256 МБ. Размер моего буферного пула InnoDB составлял 4 ГБ, и перед проведением каждого официального запуска измерения я запускал прогон прогона для заполнения буферного пула. Каждый официальный тестовый прогон длился 10 минут; это может показаться коротким, но, в отличие от, скажем, флэш-накопителя PCIe, я бы не ожидал, что наблюдаемая переменная действительно сильно изменится со временем или потребуется время для стабилизации. Основной используемый синтаксис sysbench показан ниже.

#!/bin/bash
for SSL in on off ;
do
  for threads in 1 2 4 8 16 32 ;
  do
    sysbench --test=/usr/share/sysbench/oltp.lua --mysql-user=msandbox$SSL --mysql-password=msandbox \
       --mysql-host=127.0.0.1 --mysql-port=5613 --mysql-db=sbtest --mysql-ssl=$SSL \
       --oltp-tables-count=8 --num-threads=$threads --oltp-dist-type=uniform --oltp-read-only=on \
       --report-interval=10 --max-time=600 --max-requests=0 run > sb-ssl_${SSL}-threads-${threads}.out
  done
done

Если вы не знакомы с sysbench, важно знать о нем для наших целей: он не подключается и не отключается после каждого запроса или после каждой транзакции. Он устанавливает N подключений к базе данных (где N — количество потоков) и выполняет запросы через них до завершения теста. Такое поведение обеспечивает наше моделирование пула соединений. Исходя из того, что мы знаем о том, где SSL является самым медленным, предполагается, что снижение производительности здесь должно быть самым низким. Сначала давайте посмотрим на сырую пропускную способность, измеряемую в запросах в секунду:

SysBench пропускная способность

Средняя пропускная способность и стандартное отклонение (оба измеряются в запросах в секунду) для каждой конфигурации теста показаны ниже в табличном формате:

 

Количество потоков
Размер ключа SSL
1 2 4 8 16 32
SSL выключен 9250,18 (1005,82) 18297,61 (689,22) 33910,31 (446,02) 50077,60 (1525,37) 49844,49 (934,86) 49651,09 (498,68)
1024-бит 2406,53 (288,53) 4650,56 (558,58) 9183,33 (1565,41) 26007,11 (345,79) 25959,61 (343,55) 25913,69 (192,90)
2048-бит 2448,43 (290,02) 4641,61 (510,91) 8951,67 (1043,99) 26143,25 (360,84) 25872,10 (324,48) 25764,48 (370,33)
4096-битовый 2427,95 (289,00) 4641,32 (547,57) 8991,37 (1005,89) 26058,09 (432,86) 25990,13 (439,53) 26041,27 (780,71)

 

Таким образом, учитывая, что это 8-ядерный компьютер, а IO не является фактором, мы ожидаем, что максимальная пропускная способность будет на 8 потоках, поэтому ожидается снижение производительности. Мы также видим, что, по-видимому, не имеет большого значения, какая длина ключа используется, что также в значительной степени ожидается. Однако я определенно не думал, что затраты на шифрование будут такими высокими.

Следующий график — это задержка 95-го процентиля из того же теста:

SysBench-ответ времени

И в табличном формате необработанные числа (среднее и стандартное отклонение):

 

Количество потоков
Размер ключа SSL
1 2 4 8 16 32
SSL выключен 1,882 (0,522) 1,728 (0,167) 1,764 (0,145) 2,459 (0,523) 6,616 (0,251) 27,307 (0,817)
1024-бит 6,151 (0,241) 6,442 (0,180) 6,677 (0,289) 4,535 (0,507) 11,481 (1,403) 37,152 (0,393)
2048-бит 6,083 (0,277) 6,510 (0,081) 6,693 (0,043) 4,488 (0,503) 11,222 (1,502) 37,387 (0,393)
4096-битовый 6,120 (0,268) 6,454 (0,119) 6,690 (0,043) 4,557 (0,727) 11,194 (1,359) 37,26 (0,307)

 

За исключением 8 и 32 потоков, задержка при использовании SSL постоянна и составляет около 5 мс независимо от длины ключа или количества потоков. Я не удивлен, что в 32 потоках наблюдается большой скачок задержки, но у меня нет непосредственного объяснения улучшения показателей задержки SSL в 8 потоках.

Тест 2: Время подключения

Для второго теста я написал простой Perl-скрипт, чтобы просто подключиться и отключиться от базы данных как можно быстрее Мы знаем, что это настройка соединения, которая является самой медленной частью SSL, и предыдущий тест уже примерно показал нам, что мы можем ожидать от накладных расходов на шифрование SSL для отправки данных после установления соединения, поэтому давайте посмотрим, сколько накладных расходов добавляет SSL время соединения. Основной скрипт для этого достаточно прост (показана версия без SSL):

#!/usr/bin/perl
use DBI;
use Time::HiRes qw(time);
$start = time;
for (my $i=0; $i<100; $i++) {
  my $dbh = DBI->connect("dbi:mysql:host=127.0.0.1;port=5613",
                         "msandbox","msandbox",undef);
  $dbh->disconnect;
  undef $dbh;
}
printf "%.6f\n", time - $start;

Как и в тесте № 1, я выполнил тест № 2 без шифрования и шифрования SSL размером 1024, 2048 и 4098 бит, и я провел 10 испытаний каждой конфигурации. Затем я взял прошедшее время для каждого теста и преобразовал его в число соединений в секунду. На графике ниже показаны результаты каждого прогона:
подключение к пропускной

Вот средние и стандартные отклонения:

 

шифрование Среднее число соединений в секунду Среднеквадратичное отклонение
Никто 2701,75 165,54
1024-бит 77,04 6,14
2048-бит 28,183 1,713
4096-битовый 5,45 0,015

Да, верно, 4096-битные соединения SSL устанавливаются на
3 порядка медленнее, чем незашифрованные соединения. Действительно, накладные расходы на соединение для любого уровня использования SSL довольно высоки по сравнению с незашифрованным тестом и, конечно, намного выше, чем мое первоначальное цитируемое число 25%.

Анализ и прощальные мысли

Итак, что мы от этого уберем? Первое, конечно, это то, что издержки SSL намного выше, чем 25%, особенно если ваше приложение использует что-то близкое к шаблону «одно соединение на запрос». Для системы, которая устанавливает и поддерживает долго работающие соединения, начальные издержки соединения становятся несущественными, независимо от степени шифрования, но все еще довольно большое снижение производительности по сравнению с незашифрованным соединением.

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

Но что, если пул соединений не подходит, SSL-производительность MySQL недостаточна, и вам все еще нужно полное шифрование данных в полете? Запустите компонент шифрования вашей системы на более низком уровне — VPN с аппаратным шифрованием будет самым быстрым подходом, но даже такая простая вещь, как SSH-туннель или OpenVPN *, может * быть быстрее, чем SSL в MySQL. Я буду исследовать некоторые из этих решений в следующем посте.

И наконец … если сомневаетесь, запустите свои собственные тесты. У меня нет объяснения, почему числа yaSSL так сильно отличаются от этих (возможно, yaSSL — более быстрая библиотека SSL, чем openSSL, или, возможно, они использовали другой шифр — если вам интересно, исходное число 25% пришло из слайдов 56-58 данной презентации ), но в любом случае это действительно иллюстрирует, почему важно запускать тесты на своем собственном оборудовании и с вашей собственной рабочей нагрузкой, когда вы заинтересованы в выяснении того, насколько хорошо что-то будет работать, а не принимать чужое слово для этого.