Я занимаюсь разработкой распределенной системы, в которой на сервере будут распределены огромные задачи для клиентов, которые будут их обрабатывать и возвращать результат.
Сервер должен принимать огромные файлы размером порядка 20 Гб.
Сервер должен разбить этот файл на более мелкие части и отправить путь клиентам, которые, в свою очередь, будут проверять файл и обрабатывать их.
я использую read
а также write
выполнить разбиение файла, которое выполняется смехотворно медленно.
Код
//fildes - Source File handle
//offset - The point from which the split to be made
//buffersize - How much to split
//This functions is called in a for loop
void chunkFile(int fildes, char* filePath, int client_id, unsigned long long* offset, int buffersize)
{
unsigned char* buffer = (unsigned char*) malloc( buffersize * sizeof(unsigned char) );
char* clientFileName = (char*)malloc( 1024 );
/* prepare client file name */
sprintf( clientFileName, "%s%d.txt",filePath, client_id);
ssize_t readcount = 0;
if( (readcount = pread64( fildes, buffer, buffersize, *offset ) ) < 0 )
{
/* error reading file */
printf("error reading file \n");
}
else
{
*offset = *offset + readcount;
//printf("Read %ud bytes\n And offset becomes %llu\n", readcount, *offset);
int clnfildes = open( clientFileName, O_CREAT | O_TRUNC | O_WRONLY , 0777);
if( clnfildes < 0 )
{
/* error opening client file */
}
else
{
if( write( clnfildes, buffer, readcount ) != readcount )
{
/* eror writing client file */
}
else
{
close( clnfildes );
}
}
}
free( buffer );
return;
}
Я использую C ++. Я готов использовать другие языки, если они могут работать быстрее.
Вы можете разместить файл в пределах досягаемости веб-сервера, а затем использовать curl
от клиентов
curl --range 10000-20000 http://the.server.ip/file.dat > result
получит 10000 байт (от 10000 до 20000)
Если файл сильно избыточен и сеть работает медленно, вероятно, использование сжатия может значительно ускорить передачу. Например выполнение
nc -l -p 12345 | gunzip > chunk
на клиенте, а затем выполняет
dd skip=10000 count=10000 if=bigfile bs=1 | gzip | nc client.ip.address 12345
на сервере вы можете перенести раздел, выполняющий сжатие gzip на лету, без необходимости создавать промежуточные файлы.
Единственная команда для получения раздела файла с сервера, использующего сжатие по сети:
ssh server 'dd skip=10000 count=10000 bs=1 if=bigfile | gzip' | gunzip > chunk
Является ли rsync через SSH с параметром —partial опцией?
Тогда вам может не понадобиться разделять файлы, так как вы можете просто продолжить, если передача прервана.
Известны ли заранее разделенные размеры файлов или они разделены по некоторому маркеру в файле?
Вы можете поместить файл на общее устройство NFS, и клиент может подключить это устройство в режиме RO. После этого клиент может открыть файл и использовать mmap () или pread () для чтения его фрагмента (части файла). Таким образом, клиенту будет передана только необходимая часть файла.