LINUX.ORG.RU
ФорумTalks

почему Linux создаёт TCP-сокеты — по умолчанию без SO_KEEPALIVE?

 , ,


2

3

добрый день!

пишу эту тему в раздел «talks» (а не в раздел «программирование») — потому что ну не думаю что это проблема всяких там языков программирования.

и так вопрос: почему Linux создаёт TCP-сокеты — по умолчанию без SO_KEEPALIVE?

из-за этого — очень много людей создают утечки ресурсов в своих серверных программах. (в клиентских программах тоже могут быть проблемы если не использовать SO_KEEPALIVE, например скрипт может зависнуть и ни когда в жизни не развиснуть сам).

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

программист — он же думает как: что будто «мудрое Ядро поумолчанию сделало для него безопасный сокет, который в случае чего просто закроется и всё» (и ни каких проблем, якобы)... а на самом деле бывают понимаешь ли случаи что ни фига.

для меня конечно опция SO_KEEPALIVE — является давно уж не новостью.. но вот после того как недавно я посмотрел в несколько исходных кодов (таймеры там проверяются не во всех случаях, и при этом SO_KEEPALIVE тоже не используется) — решил задать этот вопрос на LOR.

ну LOR же точно должен знать ответ...

какая здесь сакральная причина? :-)

★★★★★

Последнее исправление: user_id_68054 (всего исправлений: 2)

С SO_KEEPALIVE tcp сессия будет висеть сильно дольше и ты уверен что тебе нужны всегда такие долго живущие сессии?

catap ★★★★★
()

наверное потому, что так требует RFC

и это не только в Линуксе, а во всех остальных ОС так

Harald ★★★★★
()
Ответ на: комментарий от catap

дольше чем что? можете привести примеры? (ну и там вообще написать: речь о миллисекундах или о секундах или о минутах?)

например в случае отсутствия SO_KEEPALIVE может так получиться что сессия висит бесконечно (пока не убьёшь программу вручную: ведь программа думает что она имеет якобы подключенный сокет)

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от Harald

и это не только в Линуксе, а во всех остальных ОС так

ну тыг Linux мог бы отличиться в лучшую сторону от всех остальных :)

наверное потому, что так требует RFC

а как там написано (?) — каким способом операционная система должна «понять» что подключённый сокет [например уже двое суток] на самом деле ни фига не является подключённым? у операционной системы — есть какие-то альтернативные средства кроме SO_KEEPALIVE?

например: если неактивный TCP-сокет без SO_KEEPALIVE — бездействует уже около 4 часов — почему бы операционная система его просто бы не закрыла бы? без всяких сетевых проверок? нет ничего такого в RFC?

----------

почему этим должно заниматься Ядро а не прикладной уровень — ну очевидно потому что TCP имеет состояние, и за отслеживание его состояния отвечает Ядро [программа просто доверяется Ядру на тему того что якобы состояние ещё не утеряно, а уж как там это состояние проверяется — это должно оосбо не беспокоить программу]

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 1)
Ответ на: комментарий от user_id_68054

например: если неактивный TCP-сокет без SO_KEEPALIVE — бездействует уже около 4 часов — почему бы операционная система его просто бы не закрыла бы? без всяких сетевых проверок? нет ничего такого в RFC?

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

почему этим должно заниматься Ядро а не прикладной уровень

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

принципиальная проблема в том что tcp, собственно, в первыю очередь рассчитан на долгоживущие соединения. хотя современное развитие приняло другой вектор и сейчас это скорее анахронизм, и наверное стоило бы включать keepalive по умолчанию, если бы не три «но». а) у keepalive есть ощутимый недостаток — если destination будет временно недоступен, то кипэлайв это обнаружит и разорвет сессию, и обрабатывать это прийдется на прикладном уровне (большинство приложений will simply bail out at this point). б) на сколько устанавливать таймер кипэлайвов? неясно. именно по этим двум причинам многие приложения предпочитают более гибкий контроль с кипэлайвами на уровне прикладного протокола. в) _огромное_ количество легаси кода и интерфейс, заложенный в стандарт. единственный путь — новый интерфейс. обьявлять новый протокол только для варианта TCP с keepalive по-умолчанию? ну не глупо ли? плюс смотри SCTP.

val-amart ★★★★★
()
Ответ на: комментарий от val-amart

кстати именно такое использование было более популярно во времена Reno и именно по-этому это поведение по умолчанию.

[судя по всему речь о TCP Reno]..

что-то я запутался :) — какое поведение и когда-и-где было популярно?

выполнение определенных действий по таймеру это усложнение и доп расходы

мне кажется в ядре [в сетевой подсистеме] там уже столько всего по таймеру делается — что то не так важно если появится +ещё что-то новое :-) . кучу всех этих сетевых манипуляций связано с таймерами.

ну не обязятельно прям всё строго делать всё по таймеру (строго для всех TCP-сессий).. если так важна производительноть то можно было бы например «схалявить» следующим образом:

например проверять случайно каждые случайно-взятые 5%-от-всех-долгоживущих-открытых TCP-сессий, через каждые 2 часа, на предмет того что TCP-сессия точно не является сломанной (в случае обнаружения сломанной сессии — закрывать).

а) у keepalive есть ощутимый недостаток — если destination будет временно недоступен, то кипэлайв это обнаружит и разорвет сессию, и обрабатывать это прийдется на прикладном уровне

ну будет дисконнект,и всё делов-то [ну может с генерацией ошибки]. темболее это «временно» может затянуться на много минут. SO_KEEPALIVE не сразу отключает как только обанужит обрыв, а ещё долго пытается это опровергнуть:).

б) на сколько устанавливать таймер кипэлайвов? неясно. именно по этим двум причинам многие приложения предпочитают более гибкий контроль с кипэлайвами на уровне прикладного протокола.

ответ на этот вопрос — очень простой :) . сколько устанавливать таймер SO_KEEPALIVE — совершенно не важно совершенно. так как всё равно угодить на всех не получится — то нужно что бы это работало хотя бы как-то.

если программа сильно «умная» настолько что ей важны эти промежутки времени — то пусть такая «умная» программа умышленно отключает SO_KEEPALIVE (сразу же после инициализации сокета) и использует свои методы контроля разрывов.

в) _огромное_ количество легаси кода и интерфейс, заложенный в стандарт

а когда включили tcp_fastopen — почему же тогда не думали о legacy и интерфейсах? типа «программы расчитаны на медленное открытие, а мы тут бац и не тормозим при коннекте :)»

плюс смотри SCTP

ну а что-там в крадце опиши [то что касается найшей темы] — отслеживание физических обрывов — включено в SCTP умолчанию? если да — то это радует :)

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 3)
Ответ на: комментарий от val-amart

сеть устроена сложнее, почему прикладные программисты так любят прикидываться дурачками и надеятся что все сделают за них?

наверно потому что — если нагуглить любой пример в интернете по работе с интернет-TCP-сокетами — то в таком примере — автор примера заведомо допустит ошибку (и даже не скажет об этой ошибке в комментариях к примеру).

например:

http://docs.python.org/3.4/library/asyncio-protocol.html#protocol-example-tcp...

ни где тут не сказано: «будьте осторожны! если echo-клиент вместо посылки данных — просто некорректно разорвёт сессию — то будет эта сессия висеть у echo-сервера — как утечка ресурсов!»

ну наверно авторы примеров — расчитывают что мол программисты сами не дураки и сами догадываются обо всех этих возможных проблемах...

а потом смотришь реальный код реальных программ — и оказывается что программисты — реально ждут что после открытия сокета сразу придут данные (и ни каких таймеров) и только это.

ну и вот ...что я тут хочу сказать...

почему прикладные программисты так любят прикидываться дурачками

...не уверен я что это действительно прикидывание :)

более того — себя я тоже считаю дурачком. так как я не понимаю почему эту ситуацию ни как не хотят исправить :-) ..

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 2)
Ответ на: комментарий от user_id_68054

ну будет дисконнект,и всё делов-то

1. Кодер, достаточно «ленивый» для тривиальной установки параметров сокета, будет слишком ленив для правильной обработки обрыва соединения.

2. Программы, написанные в предположении о том, что сеть работает мгновенно и абсолютно надёжно, не следует запускать в условиях, когда соединение может оборваться само по себе.

Хотя, что-то, типа переменных окружения = умолчательные параметры сокета, позволило бы в некоторых случаях «исправить» поведение некоторых простых программ. Нынешние sysctl, похоже, делают слишкном много(действуют на все программы) и слишком мало (keepalive не включают). Странный набор.

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

у меня как у всякого уважающего себя админа есть набор самописных so-шек пригодных для ld_preload как раз на такой случай, которые меняют дефолтные параметры bind(), listen() и connect(). чего уж проще.

val-amart ★★★★★
()
Последнее исправление: val-amart (всего исправлений: 1)
Ответ на: комментарий от val-amart

набор самописных so-шек пригодных для ld_preload как раз на такой случай, которые меняют дефолтные параметры bind(), listen() и connect()

а прикольно кстате, да

user_id_68054 ★★★★★
() автор топика
Последнее исправление: user_id_68054 (всего исправлений: 1)

У меня есть подозрение, что keepalive с дефолтными параметрами поломает например wifi-роуминг, когда при перемещении по зданию сеть вполне может пропасть и минут на 10.

Ещё помню выдергивал провод из бука с ssh-сессией, шел в другую комнату и продолжал работать.

Keep alive реально нужен очень немногим.

sergej ★★★★★
()
Ответ на: комментарий от sergej

А, забыл ещё gprs. Качество связи у нас такое, что keepalive сделает мобильный интернет неработоспособным. Ну или придется выкручивать таймауты к значениям близким к 4м часам :)

sergej ★★★★★
()
Ответ на: комментарий от sergej

Ещё помню выдергивал провод из бука с ssh-сессией, шел в другую комнату и продолжал работать.

если случайно нажмёшь на любую кнопку во время offline — то сразу проихойдёт «проверка» TCP-канала.

ну а keepalive мне кажется — тут сильно не испортил бы ситуацию (по крайне мере со значениями по умолчанию).

кстате говоря вроде бы ssh-сервер как раз использует keepalive (но нужно уточнить в исходном коде) — так-что возможно ты как раз затестил именно то как keepalive ни чего НЕ портит.

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

Нет, на натах с маленьким таймаутом я специально использую

ssh ... -o TCPKeepAlive=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=5

хотя хватило бы наверное и -o TCPKeepAlive=yes

И если я нажму кнопку, то проверка пройдет очень не сразу. Он довольно долго будет пытаться доставить пакет.

sergej ★★★★★
()
Ответ на: комментарий от sergej

хотя хватило бы наверное и -o TCPKeepAlive=yes

очевидно это настройки клиента SSH :-)..

..а SSH-сервер?

если сервер безвозвратно потеряет клиента — то всё равно через 2~4 часов он выкинеть его сокет (а не оставит пожизненно висеть до перезагрузки :))

user_id_68054 ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

Да, вроде TCPKeepAlive = yes по умолчанию. Но пожизненно его и без keepalive никто держать не будет. У TCP есть какой-то бешеный таймаут на установленные соединения.

sergej ★★★★★
()
Ответ на: комментарий от sergej

Хотя этот бешеный таймаут не в tcp, а в реализации файрвола. Если никто данные не посылает и не ждет, то м быть оно и зависнет. Надо перечитать rfc, уже забыл всё...

sergej ★★★★★
()
Ответ на: комментарий от sergej

Если никто данные не посылает и не ждет, то м быть оно и зависнет.

если ждать — то тоже зависнет. (так же как и если не ждать).

но если послать данные — то разрыв обнаружится в течении пару минут :)

user_id_68054 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.