Как убрать зависшие коннекты?

Access Violation, некорректное выполнение запросов или вызовов API, ошибки утилит командной строки, в общем все, что вам мешает работать

Модераторы: kdv, dimitr

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Как убрать зависшие коннекты?

Сообщение Василий Овчинников » 04 мар 2005, 16:30

Есть сервер FB 1.5.1 CS Linux. То же самое, что опишу ниже, тестировалось и с FB 1.5.1 SS под Windows. Никаких отличий не замечено. Прошу у всех совета, как поступить в такой ситуации.

Имеются базы данных, с которыми клиенты работают через Интернет по TCP/IP через неустойчивые модемные линии. Естественно, соединения эти, бывает, рвутся и FB CS под Linux, который висит отдельным процессом на каждое соединение, не догадываясь о том, что клиент "умер" и надо откатить все транзакции, открытые этим клиентом в базе данных, и завершить работу, продолжает обслуживать такое соединение. Ситуация осложняется тем, что в случае обрыва соединения, выполнившего UPDATE, но не успевшего сделать COMMIT, записи эти так и остаются недоступными для изменения другими пользователями, пока не удалишь процесс, определив его номер и выполнив kill на сервере, что тоже не так просто, когда несколько пользователей работают одновременно. То, что UPDATE не позволяется - это правильно и все с ним ясно, так и должно быть. Хотелось бы навести порядок с автоматическим отключением таких некорректно оборваных соединений.

Есть в firebird.conf параметры
CONNECTION_TIMEOUT и
DUMMY_PACKET_INTERVAL, как раз и предназначенные для исправления таких ситуаций.

CONNECTION_TIMEOUT призван сообщить серверу обрывать неактивные соединения по истечении указанного периода неактивности. DUMMY_PACKET_INTERVAL - это период посылки пакетов на проверку физической доступности клиентской стороны, опять же при недоступности клиента соединение должно быть закрыто.

Так вот, сколько я ни пытался варьировать значения этих параметров, у меня не получилось заставить сервер определить наличие таких физически оборванных соединений и закрыть их, освободить блокировки записей, выставленные ими, в течение 30 сек. Меня бы это вполне устроило, т.к. есть несколько критичных таблиц, в которые надо писать в режиме реального времени и без больших задержек, которые в случае обрыва соединения при открытой пишущей транзакции получаются неопределенно большими. Т.е. пока я серверный процес не убью своими руками на сервере, нормальная работа с базой не продолжится. Даже тот же клиент, который по диал-ап соединяется с базой (IP-адреса динамические), не сможет продолжить работу с теми же данными, с которыми он начал работать до обрыва соединения, потому как еще жив процесс, обслуживающий его уже "мертвое" соединение, а том осталась открытая транзакция, выполнившая UPDATE, но не выполнившая COMMIT).

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 04 мар 2005, 16:31

дурацкий вопрос - символ # перед параметрами в конфиге удалял?

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 05 мар 2005, 08:40

kdv писал(а):дурацкий вопрос - символ # перед параметрами в конфиге удалял?
Прощаю. :D
Конечно, удалял.
FB SS под Виндой после изменения параметров перезагружал, а FB CS под Linux - не перезагружал, т.к. не требется, потому как на каждое соединение свой экземпляр сервера загружается и настройки при загрузке этого процесса зачитываются заново.
Надо заметить, что на FB CS процесс, обслуживающий отвалившееся соединение, через какое-то время иногда все же завершает работу. Но как регулировать этот промежуток времени - совершенно не ясно. У меня получалось на однотипных ситуациях от трех-пяти минут (процесс сам выгружался) до "окончания терпения", когда своими руками убивать процесс приходилось. Ситуация проигрывалась именно та, которая описывалась выше. Открывается транзакция, выполняется UPDATE, а дальше клиента просто отключаю от сети. Реально у клиентов может оборваться (и обрывается) телефонное соединение с провайдером. Далее наблюдаю по netstat состояние соединений на сервере и начинаю "пляски с бубном", гадая через какой промежуток времени закроется коннект, и закроется ли он вообще.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 05 мар 2005, 10:31

не обратил внимания, что 1.5.1. В 1.5.2 что-то еще на эту тему правили.

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 05 мар 2005, 10:34

kdv писал(а):не обратил внимания, что 1.5.1. В 1.5.2 что-то еще на эту тему правили.
Хорошо, посмотрю, что будет в 1.5.2. И список исправлений к нему почитаю. Только уже после 8 Марта.
Тему не закрываю и еще вернусь обязательно .

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 05 мар 2005, 12:27

Василий Овчинников писал(а):
kdv писал(а):дурацкий вопрос - символ # перед параметрами в конфиге удалял?
Надо заметить, что на FB CS процесс, обслуживающий отвалившееся соединение, через какое-то время иногда все же завершает работу. Но как регулировать этот промежуток времени - совершенно не ясно.
Процесс в это время в каком состоянии и кушает ли процессор? Обрыв ничем не занятого соединения проходил всегда и проходит сейчас, что через dummy_packets, что через so_keepalive, гладко. А вот если он чем-то был сильно занят в момент обрыва (в том числе сборкой мусора), то снимался только когда заканчивал своё дело и хотел доложить что-то клиенту. Иногда (очень редко) не снимался даже по наступлению этого события. После замены по умолчанию dummy_packets на so_keepalive в 1.5 ситуация с этим ухудшилась, но директивное включение через конфиг dummy_packets ставило всё на свои места. 1.5.1 в этом плане не тряс. Попробуй действительно 1.5.2 с обоими механизмами (параметры so_keepalive надо настраивать в конфиге TCP/IP, по умолчанию там несколько часов).

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 09 мар 2005, 10:35

Merlin писал(а): Процесс в это время в каком состоянии и кушает ли процессор? Обрыв ничем не занятого соединения проходил всегда и проходит сейчас, что через dummy_packets, что через so_keepalive, гладко.
Процесс молчит, загрузка процессора 0%, трафик по порту 3050 нулевой.
Кстати, для всех заинтересовавшихся данной темой, прошу сюда
http://sql.ru/forum/actualthread.aspx?b ... 24374&pg=3
Там люди справились с родственной проблемой, исследуя пути отключения мертвых коннектов. Но только под виндами. Справились с помощью dummy_packet_interval=60.
Я попробую рыть в этом же направлении, однако, рыл уже, что весьма меня настораживает.
So_keepalive пока менять не буду, т.к. видим на обнадеживающих примерах, что все должно работать без его изменения, да и прочие разные другие сервисы это затронет. т.к. настройка эта едина для всего сервера.
(Да, да... Не ругайтесь сильно, знаю, что плохо это, но сервер у меня не только SQL крутит, но еще и apache, и домен почтовый, и фтп, ибо железка могучая и пока со всем этим легко справляется, т.к. загрузка процессора никогда еще выше 5% не превышала)

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 09 мар 2005, 12:26

В продолжение темы:

Итак, все тот же FB CS 1.5.1 под Linux 7.3. На клиентах winXP SP1- клиент от того же FB 1.5.1, но из виндовой установки.

В firebird.conf проставляю
ConnectionTimeout=30
DummyPacketInterval = 10

Запускаю программу на клиенте (использую для работы FIBPlus для Delphi), фетчу записи, одну из них начинаю редактировать транзакцией с такими вот параметрами

write
rec_version
no_wait
read_commited

и отключаю компьютер от сети.

На сервере смотрю трафик по порту 3050 и вижу, что через 10 секунд с наступления тишины на соединении начинается посылка пакетов (думаю, это и есть те самые dummy-пакеты) на клиента. Пакеты посылаются через увеличивающийся интервал. Клиент на них не отвечает, естественно, т.к. физически отключен, и через минуту пакеты перестают посылаться на клиента. Не ясно, почему через минуту, т.к. ConnectionTimeout=30 секунд, а не 60.

Все бы хорошо, но после наступления тишины в канале
[сервер-"мертвый" клиент]

"netstat -tp" показывает:
.......
tcp 0 30240 192.168.0.200:gds_db slava.localkvc:1181 ESTABLISHED
25501/fb_inet_server
.......

т.е. сервер никуда не делся, не выгрузился, и выгружаться не собирается (?). Убиваю таких только через kill.

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

Приведу еще статистику по базе, с которой провожу эксперименты:
---------------------------------------------------------------------------
Database header page information:
Flags 0
Checksum 12345
Generation 18045
Page size 2048
ODS version 10.1
Oldest transaction 869
Oldest active 17997
Oldest snapshot 17997
Next transaction 18039
Bumped transaction 1
Sequence number 0
Next attachment ID 0
Implementation ID 19
Shadow count 0
Page buffers 0
Next header page 0
Database dialect 3
Creation date Feb 3, 2005 16:02:23
Attributes force write
Variable header data:
Sweep interval: 20000
---------------------------------------------------------------------------

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 10 мар 2005, 17:33

Продолжаем разговор:

Поставил FB CS 1.5.2.

Ничего не изменилось :(

Смотрю трафик и наблюдаю за поведением сервера:
с того момента, как клиент "замолчал", через 10 сек начинается опрос доступности клиента со стороны сервера часто-реже-еще реже-совсем редко, т.е. пакеты идут через увеличивающийся временной интервал. Транзакция клиентом открыта, он в это время редактирует данные у себя на локале.
Отключаю физически клиента. После отключения клиента на серверные запросы типа "жив ли ты" ответы от клиента перестают приходить на сервер. Через некоторое время (разное в разных экспериментах) сервер перестает посылать запросы клиенту. Ждал в районе 5 мин. Никакой сетевой активности по порту 3050 сервер в сторону клиента не предпринимает.
Подключаю клиента и, о чудо!, соединение закрывается. А должно бы было закрыться через 30 секунд с момента недоступности клиентской стороны, если я правильно понимаю логику настроек
ConnectionTimeout и DummyPacketInterval в firebird.conf.
А ведь по модему с тем же IP клиент два раза подряд не придет :-(
Да, придет с таким же IP, если тот статический. А если динамический?

Пробовал в настройки ядра Linux ставить такие:
sysctl net.ipv4.tcp_keepalive_intvl=10
sysctl net.ipv4.tcp_keepalive_time=30

Т.е. использование so_keepalive_time тоже не помогает

Как сервер-то заставить выгружаться в случае обрыва соединения?
Прошу совета!!! Может это только в FB CS для Linux такая беда? Может FB SS спасет? Не хотелось бы, т.к. сервер двухпроцессорный, жалко добро разбазаривать.

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 10 мар 2005, 18:47

Каким-либо способом без обрыва сетевого шнурка это воспроизводится? С localhost-коннектом через ручное закрытие сокета, например?

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 11 мар 2005, 09:56

dimitr писал(а):Каким-либо способом без обрыва сетевого шнурка это воспроизводится? С localhost-коннектом через ручное закрытие сокета, например?
Вопрос, конечно, интересный...
Подскажите, как вручную закрыть сокет в linux? Я попробую, но...
Через localhost - это что ж, через isql коннектиться к базе, параметры транзакции там указывать, да?.. Нерадостно как-то. Клиентская часть у меня только под винду есть. Опять же как вручную сокет в linux закрыть, не убивая процесса? Не умею :-(

Быть может имеет смысл попробовать по localhost под виндой с FB CS 1.5.2?..
Эксперементировать-то особо времени нету, но, "надо, Федя. Надо!"
Как вручную в таком случае обрубить сокет под WinXP? Утилиты какие-нибудь есть полезные?

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 11 мар 2005, 11:57

У меня нет линух-сервера, чтобы проверить эту проблему. Поэтому ее нужно упростить либо до одной машины, либо до виндовой сети. Если воспроизведется на WinXP, то это просто чудесно.

В виндах принудительно оборвать сокет можно с помощью TCPView от SysInternals.

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 14 мар 2005, 14:12

dimitr писал(а):У меня нет линух-сервера, чтобы проверить эту проблему. Поэтому ее нужно упростить либо до одной машины, либо до виндовой сети. Если воспроизведется на WinXP, то это просто чудесно.

В виндах принудительно оборвать сокет можно с помощью TCPView от SysInternals.
Провел серию экспериментов в винде.
Воспроизвести ситуацию с обрывом соединения, когда и сервер и клиент работают на одной и той же машине, не получается. При закрытии клиентского сокета закрывается и серверный сокет СРАЗУ, и ОДНОМОМЕНТНО, без моего волевого участия. Потому опыт в таких условиях НЕ воспроизводится.

Разнес клиента и сервер на разные машины. Сервер - FB CS 1.5.2 для Windows. На обеих машинах WinXP SP1. И... Удача (сомнительная в моем случае)! Сервер при обрыве клиентского коннекта корректно закрывает свое соединение в течение указанного ConnectionTimeout.

Предварительный вывод:
В FB CS 1.5.2 и 1.5.1 для Linux есть баг с обработкой ConnectionTimeOut и DummyPacketInterval
В FB CS 1.5.2 для Windows с этим проблем нет.

Что скажут разработчики? К кому обратиться?

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 14 мар 2005, 17:47

Там код для всех платформ идентичный, насколько я помню. Но все же перепроверю.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 14 мар 2005, 18:08

чую, есть какая-то гадость во взаимодействии линуксовых и виндовых сокетов, или гадость с сокетами в линуксе, специфическая.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 14 мар 2005, 18:28

Я уже несколько раз говорил на эту тему о своих бдениях. С момента выхода 1.5. У меня при выдёргивании шнурка по so_keepalive процесс умирает только если он ничего при этом не делал. Если же это неудачный запрос, который молотит дольше интервала тайм-аута, то он потом остаётся. А вот по dummy_packets всё как и раньше, практически не бывает зомбаков. Ну там случайно один раз в полгода, это уже видимо какие-то осевые проколы всё-таки.

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 15 мар 2005, 10:46

kdv писал(а):чую, есть какая-то гадость во взаимодействии линуксовых и виндовых сокетов, или гадость с сокетами в линуксе, специфическая.
Быть может повторюсь, т.к. я такую же тему завел на forums.demo.ru/epsylon.public.interbase
Линух у меня с ядром 2.4.18-3smp

Я проиграю все то же самое с 2.4.21-smp, ибо есть другой сервер рядом. Правда, он тоже в эксплуатации и особых экспериментов на нем не поставишь. Был бы сервак-на-слом для экспериментов - так бы я смело поставил 2.4.(че-там-самое-последнее), чтоб исключить все уже исправленные глюки ядра и пробовал бы с ним, но увы мне, увы...

Кстати (не бейте сильно, т.к. не знаю ничего о внутренних механизмах FB!!!), а не связаны ли все мои беды с поддержкой SMP в FB? Ибо сервер-то с линухом двухпроцессорный!

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 15 мар 2005, 11:25

намекнули про no_nagle, то есть, линуксовый сервер накапливает данных на пакет. может быть, поэтому пакет клиенту так и не отправляется.

Василий Овчинников
Сообщения: 14
Зарегистрирован: 04 мар 2005, 15:33

Сообщение Василий Овчинников » 15 мар 2005, 11:38

kdv писал(а):намекнули про no_nagle, то есть, линуксовый сервер накапливает данных на пакет. может быть, поэтому пакет клиенту так и не отправляется.
если честно, то впервые слышу про такое (no_nagle)
Обращусь к первоисточникам. Почитаю man.
Да, только что провел все те же эксперименты на ядре 2.4.21 - тот же эффект. :-(

Еще намекнули про параметр wait для xinetd при запуске FB - тоже попробую

А данные клиенту - да, накапливаются. Даже netstat, когда показывает запись по зависшему серверному процессу, показывает в колонке SendQ (очередь отправки) цифири больше нуля.

v6y
Сообщения: 78
Зарегистрирован: 12 мар 2005, 17:45

Сообщение v6y » 15 мар 2005, 11:58

Василий Овчинников писал(а): Еще намекнули про параметр wait для xinetd при запуске FB - тоже попробую
А wait, IMHO, лучше не трогать. Выписка из man:
wait
This attribute determines if the service is single-threaded or multi-
threaded
. If its value is yes the service is single-threaded; this means
that xinetd will start the server and then it will stop handling requests
for the service until the server dies
. If the attribute value is no, the
service is multi-threaded and xinetd will keep handling new service
requests
.

Ответить