Артём Гавриченков (ximaera), ведущий разработчик сети фильтрации трафика Qrator, описывает типичные ошибки программирования при написании серверных приложений на основе TCP-сокетов в рамках конференции «Российские интернет-технологии» (2-3 апреля 2012, Москва).
Разбирается (вероятно, неисчерпывающий) ряд заблуждений и узких мест, приводящих к проблемам с производительностью и уязвимостям безопасности TCP-приложений; приводится ряд примеров, когда ошибки, неочевидные на этапе программирования, при эксплуатации приводили к финансовым и репутационным потерям у авторов и пользователей приложения. Даются рекомендации по отладке и оптимизации приложений, основанных на TCP, а также операционных систем, в которых эксплуатируются такие продукты.
Среди прочего, разбираются такие аспекты работы обработчика TCP-запросов, как:
• предотвращение атак, аналогичных slow POST в Nginx и Lighttpd;
• предотвращение ошибок, аналогичных проблеме со скачиванием файлов в браузере Internet Explorer;
• возможные изменения в дизайне самописных TCP-based протоколов с целью их ускорения;
• использование опции TCP (таких, как TCP_NODELAY) для ускорения работы специфических приложений.
специализированные http-демона (Сергей Боченков, Александр Панков)
Порядок преодоления болота на маршруте: как не надо писать приложения, основанные на протоколе TCP
1. Порядок преодоления болота на маршруте
Как не надо писать приложения, основанные на протоколе TCP
Артём Гавриченков
2. Основано на реальных событиях
• NOT AN AD!
• Распределённая сеть Qrator
●
"кастомный" TCP/IP "снизу"
●
"кастомный" протокол управления "сверху"
●
опыт работы с большим числом Web-серверов и Web-
браузеров, включая самописные
●
2 года дебаг^W совершенствования продукта
5. Проблемы
• TCP не обеспечивает гарантированную доставку
сообщения за гарантированное время. Так лучше?
• Первоочерёдная задача – проектирование
таймаутов
• Ресурсы (включая время) на любое действие
пользователя должны быть ограничены
• Бездействие – это тоже действие
6. Таймауты
• между recvfrom()
• между запросами
• время запроса
• время сессии
• время жизни любой проектируемой сущности
• Long polling может быть плохой идеей
7. Пример
• Slowloris (Apache): DoS сервера с одного ПК
• Slow HTTP POST
●
Apache, IIS, Lighttpd: DoS сервера с одного ПК
●
Nginx: DDoS сервера с ботнета
9. Content-Length
●
Ресурсы на любое действие пользователя
должны быть ограничены
●
В "кастомный протокол" должно закладываться
ограничение на размер передаваемых данных
●
Сервер и клиент должны контролировать это
ограничение
10. errno(3)
●
Закрытие соединения не означает успешную
передачу данных
●
После recvfrom(), sendto(), etc. проверяйте errno
●
ENOMEM
●
ECONNRESET
●
EANYTHING
11. Пример
●
Internet Explorer: скачивание файла успешно
заканчивается при ECONNRESET
●
Статус соединения не проверяется
●
Content-Length не проверяется
12. Лимиты памяти
●
Используемые ресурсы должны быть ограничены
сверху
●
ENOMEM
●
Используемые ресурсы должны быть ограничены
снизу
●
Нет ресурсов → idle wait → ECONNRESET
13. Latency
●
Троекратное рукопожатие занимает время
●
Нужно реализовывать persistent-соединения
●
сразу, чтобы не городить костыли потом
16. Оптимизация
● Текстовые протоколы удобны для отладки
● Отлаживать придётся
● Использование бинарных протоколов, как
правило, – преждевременная оптимизация
● Потом, всегда есть BSON и Google Protocol Buffers
17. Оптимизация
●
Опции TCP-сокета:
●
TCP_NODELAY: отключение алгоритма Нейгла,
ускорение при малых порциях данных
●
TCP_CORK (Linux): для отсылки порций данных
в одном TCP-сегменте
●
"socket corking"