Sunday, October 3, 2010

libcurl + FTP + NAT = LOVE и адов угар

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

Но его реализация в сабже добавляет масла в огонь: чудесный код из дебрей libcurl, представленный ниже, может ждать до минуты после каждой успешной операции (!!!!!) пока Control Connection не подтвердит что закачка прошла успешно, или не отвалится:
\libcurl\curl-7.20.1\lib\ftp.c
static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
bool premature)
{
//..
if((ftp->transfer == FTPTRANSFER_BODY) && ftpc->ctl_valid &&
pp->pending_resp && !premature) {
/*
* Let's see what the server says about the transfer we just performed,
* but lower the timeout as sometimes this connection has died while the
* data has been transfered. This happens when doing through NATs etc that
* abandon old silent connections.
*/

long old_time = pp->response_time;

pp->response_time = 60*1000; /* give it only a minute for now */ // WTF here
pp->response = Curl_tvnow(); /* timeout relative now */

result = Curl_GetFTPResponse(&nread, conn, &ftpcode);

pp->response_time = old_time; /* set this back to previous value */

if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
failf(data, "control connection looks dead");
ftpc->ctl_valid = FALSE; /* mark control connection as bad */
conn->bits.close = TRUE; /* mark for closure */
}
}
_Winnie C++ Colorizer

Не правда ли, это прекрасно?

Как раз сейчас наблюдаю интересную картину, когда Сontrol Connection (не без помощи сил Тьмы NAT) на определенных файлах отваливается ровно через раз, а я получаю минутное ожидание на каждый второй read. Особенно смешно, что сам read проходит практически мгновенно.

Конечно, установка злостных значений для SIO_KEEPALIVE_VALS немного улучшает ситуацию, CURL оказывается не выставляет keep-alives вообще; но все равно, некий батхерт остается.

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

П.С А это всё select-based схема, в случае, если бы CURL базировалась на IOCP, такого архитектурного косяка впринципе не могло бы существовать

П.П.С Вообще, мне libcurl скорее нравится чем нет, если бы не такие скелеты в шкафу, да еще если бы у нее на уровне дизайна была бы предусмотрена асбтракция "Connection", была бы чудо библиотека

No comments: