Конфигурация по умолчанию для Nginx включает sendfile
— https://github.com/nginx/nginx/blob/release-1.13.8/conf/nginx.conf#L27, поэтому я запутался в вашем заявлении.
Еще в начале 2000-х вы могли видеть, как разработчик Apache представил возможность отключения SendFile ( и вот сообщение списка рассылки для патча< /а>). Также есть старые ошибки, которые могли быть связаны с sendfile, в системе отслеживания ошибок Apache. Из ошибки Apache #12893 мы узнаем, что одна из наблюдаемых ошибок была вызвана тем, что реализация NTFS в ядре Linux просто вообще не поддерживала системный вызов sendfile
:
[...] очевидно, есть какая-то характеристика вашей файловой системы NTFS, которая мешает работе sendfile().
sendfile(8, 9, [0], 9804) = -1 EINVAL (Invalid argument)
В сообщении в блоге под названием "Загадочная история Sendfile и Apache" упоминается вопрос stackoverflow, который вы читаете, выдвигает следующую теорию:
sendfile() передаст не более 0x7ffff000 (2 147 479 552) байт, возвращая количество фактически переданных байтов. (Это справедливо как для 32-разрядных, так и для 64-разрядных систем.)
Есть ограничение в 2 Гб. Теперь вот предположение, в документации apache говорится:
При смонтированном в сети DocumentRoot (например, NFS, SMB, CIFS, FUSE) ядро может быть не в состоянии обслуживать сетевой файл через собственный кэш[2].
Поэтому, когда говорится, что «ядро может быть не в состоянии обслужить файл», я думаю, мы можем иметь в виду внутреннее ограничение на размер файла, которое имеет sendfile.
Интересная теория, но я сомневаюсь, что это ответ, потому что вы можете просто не использовать путь кода sendfile для слишком больших файлов. Обновление: копаясь, я обнаружил, что автор этого поста создал продолжение под названием В тот раз, когда я ошибался в отношении Sendfile() и Apache, в котором упоминается ответ, который вы читаете!
В документации ProFTPD также есть предупреждения о проблемах с файлом отправки:
Были случаи, когда именно файловые системы, а не ядра, были виновниками проблем sendfile(2):
- Сетевые файловые системы (например, NFS, SMBFS/Samba, CIFS)
- Виртуализированные файловые системы (OpenVZ, VMware и даже Veritas)
- Другие файловые системы (например, NTFS и tmpfs в Linux)
Опять же, если вы столкнулись с проблемами при загрузке файлов из ProFTPD, когда эти файлы находятся в сетевой или виртуализированной файловой системе, попробуйте использовать «UseSendfile off» в вашем proftpd.conf.
Много предупреждений "здесь будут драконы". Некоторые из них будут вызваны тем, что файловая система просто не поддерживает sendfile (например, до 2.4.22-pre3 Linux tmpfs не поддерживал sendfile). Файловые системы на основе FUSE (такие как NTFS-3g) также имели бы проблемы в прошлом из-за ошибок FUSE и sendfile (с тех пор, как они были устранены). Хотя список виртуализированных файловых систем является интересным дополнением...
Однако Часто задаваемые вопросы по OrangeFS, похоже, содержат наиболее правдоподобное объяснение:
5.16 Можем ли мы запустить веб-сервер Apache для обслуживания файлов с тома OrangeFS?
Что вы можете! Однако мы рекомендуем отключить параметр EnableSendfile в файле httpd.conf перед запуском веб-сервера. В качестве альтернативы вы можете настроить OrangeFS с опцией -enable-kernel-sendfile. Передача этой опции для настройки приводит к тому, что модуль ядра Orangefs поддерживает обратный вызов sendfile. Но мы рекомендуем, если обслуживаемые файлы не достаточно велики, это может быть не очень хорошей идеей с точки зрения производительности. Apache 2.x+ использует системный вызов sendfile, который обычно передает данные файла через кэш страницы. В последних ядрах 2.6 этого можно избежать, предоставив процедуру обратного вызова sendfile в файловой системе. Следовательно, это гарантирует, что мы не получим устаревшие или несогласованные кэшированные данные в таких ядрах. Однако в более старых ядрах 2.4 системный вызов sendfile передает данные через кэш страниц, и поэтому существует реальная вероятность того, что данные будут обслуживаться устаревшими. Поэтому пользователи системного вызова sendfile должны быть осторожны с этой деталью.
Аналогичное объяснение можно прочитать в системный вызов Linux guest readv возвращает устаревшие (кэшированные) данные файла общей папки с ошибкой Virtualbox< /а>:
Я обнаружил, что программы, читающие файлы с помощью системного вызова read, возвращают правильные данные, а программы, использующие системный вызов readv (например, моя версия gas), считывают устаревшие кэшированные данные.
[...]
использование функции ядра generic_file_read_iter в качестве члена .read_iter структуры file_operations (.read_iter используется при выполнении системного вызова readv). Эта функция БУДЕТ записывать и читать из файлового кеша. Однако функция vbox sf_reg_read, используемая для универсального члена .read и системного вызова чтения, по-видимому, всегда обходит кэш файловой системы Linux.
[...]
Кроме того, я считаю, что аналогичная долгоживущая проблема сообщается как билет #819, только для файла отправки. системный вызов. Кажется, что все эти функции generic_file_* предполагают, что хост контролирует весь доступ к диску.
Вышеизложенное также может объяснить список проблемных файловых систем виртуализации ProFTPD.
Резюме (наилучшее предположение)
Apache не рекомендует использовать sendfile()
с Linux NFS, потому что их программное обеспечение популярно и вызвало множество болезненных для отладки ошибок, связанных с sendfile
, в старых клиентах Linux NFS. Предупреждение устарело, и, вероятно, проще оставить его как есть, чем обновлять со всеми предостережениями.
Если у вас есть файловая система Linux, в которой базовые данные могут быть изменены без аннулирования кеша страниц Linux, неразумно использовать sendfile
с ним в старых ядрах Linux (это объясняет проблемы старых клиентов Linux NFS). С более новыми ядрами, если вышеупомянутая файловая система не реализует собственный хук sendfile
, снова использовать sendfile
неразумно (проблема с общей папкой Virtualbox демонстрирует это).
Недавние (2.6.31 и выше) ядра Linux предоставляют возможность файловым системам, которые могут столкнуться с этой проблемой аннулирования, использовать свою собственную реализацию sendfile
, и, если файловая система справляется, ее можно использовать с sendfile
, исключая ошибки, но будьте осторожны!
person
Anon
schedule
02.01.2018