Каталог
Поиск
Голосование
Сколько контроллеров в Вашей системе "АВАНГАРДЪ"?

Телефон: +7 (921) 898.45.35, +7 (495) 777.66.75 доб.118325 по рабочим дням с 11 до 17 по Мск.

Skype: mmayorov

Использование KEEPALIVE-сокетов для обнаружения и отключения зависших клиентских соединений InterBase и Firebird

Автор: Овчинников Василий 
mailto: ova@tkvc.ru
17.05.2005, изменено 06.09.2005

Введение

В системах, предназначенных для работы в реальном времени или близком к нему, существует проблема отслеживания на серверной стороне состояния клиентских соединений и принятия мер для их принудительного отключения в случае недоступности клиента вследствие разрыва соединения. Особенно при использовании Classic Firebird SQL Server важно своевременно освобождать ресурсы, занимаемые такими фантомными соединениями.

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

Например, клиент сохраняет измененный набор записей. После выполнения UPDATE, но до выполнения COMMIT модемное соединение разрывается. Обычно клиентское приложение в такой ситуации восстанавливает соединение с сервером, но клиент, продолжая работу с теми же данными, при сохранении которых он получил сообщение об ошибке по причине разрыва соединения, не может сохранить свои изменения, получая со стороны сервера сообщение о конфликте блокировки. Ему мешает его предыдущее соединение, открывшее транзакцию, в контексте которой был выполнен UPDATE, но не был выполнен COMMIT, т.к. соединение со стороны клиента было разорвано.

Точно так же обрывы соединений могут возникать и в локальной сети, если сбоит оборудование – сетевые карты, хабы, коммутаторы – или возникают помехи. В interbase.log/firebird.log обрывы коннектов tcp показываются как ошибки 10054 (Windows. на Unix - 104), обрывы netbeui – как ошибки 108/109.

Для отслеживания и отключения таких «мертвых» соединений InterBase и Firebird использует один из двух механизмов – DUMMY-пакеты (реализован на прикладном уровне начиная с InterBase 5.0 между сервером InterBase/ Firebird и клиентской библиотекой gds32/fbclient, включается в ibconfig/ firebird. conf и в данном документе рассматриваться не будет) и KEEPALIVE-сокеты (используется по умолчанию начиная с InterBase 6.0). Использование KEEPALIVE включается установкой опции сокета SO_ KEEPALIVE при его открытии. Вам не нужно специально заботиться об этом, если вы используете Firebird 1.5 или выше – это реализовано в программном коде сервера Firebird, как для Classic, так и для Superserver. Для Interbase и Firebird (младше 1.5) в варианте Classic (существуют только для Unix|/ Linux) необходима дополнительная настройка (см. п. 3). В этом случае отслеживание состояния соединения возлагается не на сервер Firebird, а на стек TCP операционной системы. Однако для практического использования требуется настройка параметров KEEPALIVE.

Примечание: как показывает практика, устойчивость работы механизма dummy-пакетов, реализованная еще в InterBase 5.0 и неоднократно исправленная в Firebird 1.5. x сильно зависит от операционных систем клиента и сервера, версий стека tcp и множества других условий. То есть, эффективность такой системы в реальной сети стремится к нулю.Ко всему прочему, в Borland Developer Network упоминалось, что для Windows существует проблема с утечкой памяти в adf.sys при использовании dummy-пакетов. Именно поэтому необходимо настраивать механизм KEEPALIVE, за который отвечает стек tcp клиента и сервера.

Описание KEEPALIVE

Поведение KEEPALIVE-сокетов регулируется параметрами, представленными в таблице.

Параметр Описание
KEEPALIVE_ TIME Интервал времени, по истечении которого начинаются пробы KEEPALIVE.
KEEPALIVE_INTERVAL Интервал времени между пробами KEEPALIVE
KEEPALIVE_PROBES Количество проб KEEPALIVE

Стек TCP отслеживает момент прекращения прохождения пакетов между клиентом и сервером, запуская таймер KEEPALIVE. Как только таймер достигнет величины KEEPALIVE_ TIME, стек TCP сервера выполняет первую пробу KEEPALIVE. Проба – это пустой пакет c флагом ACK, отправляемый клиенту. Если на стороне клиента все в порядке, то стек TCP на клиентской стороне посылает ответный пакет с флагом ACK и стек TCP сервера, получив ответ, сбрасывает таймер KEEPALIVE. Если клиент не отвечает на пробу, то пробы со стороны сервера продолжают выполняться. Их количество равно KEEPALIVE_ PROBES и выполняются они через интервал времени KEEPALIVE_ INTERVAL. Если клиент не ответил на последнюю пробу, то по истечении еще одного интервала времени KEEPALIVE_ INTERVAL стек TCP операционной системы сервера закрывает соединение и Firebird высвобождает все ресурсы, занимаемые обслуживанием данного соединения.

Таким образом, разорванное клиентское соединение будет закрыто по истечении времени KEEPALIVE_ TIME+ ( KEEPALIVE_ PROBES+1)* KEEPALIVE_ INTERVAL.

Значения параметров по умолчанию достаточно велики, что делает их практическое применение неэффективным. Параметр KEEPALIVE_ TIME, например, имеет значение по умолчанию 2 часа и в Linux и в Windows. Реально достаточно одной-двух минут для принятия решения о принудительном отключении недоступного клиента. С другой стороны, настройки KEEPALIVE по умолчанию иногда приводят к принудительному обрыву соединений в сетях Windows, которые неактивны в течение этих самых двух часов (сомнения по поводу необходимости наличия в приложениях таких соединений – это уже другой вопрос).

Ниже мы рассмотрим настройку этих параметров для операционных систем семейства Windows и операционной системы Linux.

Настройка KEEPAILVE в Linux

Параметры KEEPALIVE в Linux можно изменить либо прямым редактированием файловой системы / proc либо вызовами sysctl.

Для первого случая надо редактировать:

 /proc/sys/net/ipv4/tcp_keepalive_time 
 /proc/sys/net/ipv4/tcp_keepalive_intvl
 /proc/sys/net/ipv4/tcp_keepalive_probes

Для второго случая выполнить команды:

 sysctl –w net.ipv4.tcp_keepalive_time=value 
 sysctl –w net.ipv4.tcp_keepalive_intvl=value
 sysctl –w net.ipv4.tcp_keepalive_probes=value 

Время задается в секундах.

Для автоматической установки этих параметров в случае перезагрузки сервера добавьте в / etc/ sysctl. conf:

 net.ipv4.tcp_keepalive_intvl = value 
 net.ipv4.tcp_keepalive_time = value
 net.ipv4.tcp_keepalive_probes = value 

Слово < value> замените на нужные вам величины.

Если вы используете Firebird Classic ранее версии 1.5, то в /etc/xinet.d/firebird пропишите следующее :
FLAGS=REUSE KEEPALIVE

Настройка KEEPALIVE в Windows 95/98/ME

Ветка реестра

HKEY_ LOCAL_ MACHINE\ System\ CurrentControlSet\ Services\ VxD\ MSTCP

Все про настройку TCP здесь:http://support.microsoft.com/default.aspx?scid=kb;en-us;158474

Параметры :

  • KeepAliveTime = миллисекунды
    Тип: DWORD
    Для Windows 98, тип STRING.
    Определяет время неактивности соединения в миллисекундах по истечении которого начинаются KEEPALIVE-пробы. Значение по умолчанию – 2 часа (7200000).
  • KeepAliveInterval = 32-значное число 
    Тип : DWORD
    Для Windows 98, тип STRING.
    Определяет время в миллисекундах между повторами KEEPALIVE-проб . Как только истек интервал KeepAliveTime через каждый интервал времениKeepAliveInterval (в миллисекундах) посылаются KEEPALIVE-пробы максимальным количеством MaxDataRetries. Если ответ не придет, соединение закрывается. Значение по умолчанию 1 секунда (1000).
  • MaxDataRetries = 32-значное число
    Тип: STRING
    Определяет максимальное количество KEEPALIVE-проб. Значение по умолчанию 5.

Настройка KEEPALIVE в Windows 2000/NT/XP

Ветка реестра 
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\.
Все про настройку TCP:

2000/ NT: http://support.microsoft.com/kb/120642/en-us

XP: http://support.microsoft.com/kb/314053

Вместо MaxDataRetries используется параметр

TCPMaxDataRetransmissions.
Остальные параметры называются так же, как для Windows 9x

Настройка KEEPALIVE в Windows (для клиентов)

Данная настройка необязательна, но, возможно, позволит уменьшить количество сообщений о потере соединения при использовании ненадежных линий связи. Добавьте в ветку реестра

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

параметр DisableDHCPMediaSense=1 . См. описание данного параметра здесь: 
http://support.microsoft.com/?scid =kb%3Bru%3B239924&x=13&y=14
   Пример

Рассмотрим пример настройки Firebird SQL Server 1.5.2 CS под ОС Linux.

    • Убедимся, что в firebird.conf отключен механизм DUMMY-пакетов (параметр закомментирован)

……………..
#DummyPacketInterval=0 
…………….

  • Убедимся в наличии конфигурационного файла /etc/xinet.d/firebird

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

  • Изменяем параметры стека TCP

sysctl –w net.ipv4.tcp_keepalive_time = 15

sysctl –w net.ipv4.tcp_keepalive_intvl = 10

sysctl –w net.ipv4.tcp_keepalive_probes = 5

  • Устанавливаем соединение к любой базе данных на сервере с любого сетевого клиента.
  • Смотрим трафик на сервере используя любой фильтр пакетов.
    При указанной конфигурации параметров /proc/sys/net/tcp_ keepalive_* через 15 секунд с момента наступления тишины в канале сервером выполняется проба. Если клиент жив, то серверу высылается ответный пакет. Еще через 15 секунд проверка повторяется и т.д.
  • Если клиента отключить физически (выключить коммутатор или модем – мало ли, что может случиться в действительности), то на пробу сервера ответ от клиента не приходит, и сервер начинает с 10-ти секундным интервалом посылать пробы. Если на пятую пробу клиент не ответил, то еще через 10 секунд серверный процесс выгружается, освобождая ресурсы и блокировки. Если клиент подал признаки жизни и откликнулся хотя бы и на пятую пробу (худший случай), то снова выдерживается 15-сек тайм-аут и опять начинаются пробы. И т.д.

Заключение

В заключение хотелось бы привести практические рекомендации по выбору величин параметров KEEPALIVE.

Во-первых, определите для себя необходимую величину параметра KEEPALIVE_ TIME. Чем больше будет его значение, тем позже начнутся KEEPALIVE-пробы. Если вы постоянно наблюдаете на своем сервере множество зависших коннектов, и вам приходится их удалять вручную, то следует уменьшить величину KEEPALIVE_ TIME.

Во-вторых, значения параметров KEEPALIVE_ INTERVAL и KEEPALIVE_ PROBES должны удовлетворять вашим требованиям по своевременному отключению уже обнаруженных системой зависших соединений. Если ваши пользователи устанавливают соединения с сервером через ненадежные каналы связи, то вам, возможно, захочется увеличить количество проб и интервал между ними для того, чтобы пользователь успел обнаружить обрыв и восстановить соединение с сервером. В случае, если клиентоы используют выделенное подключение к сетям общего пользования (Интернет) или используют доступ к SQL-серверу по локальной сети, возможно уменьшение количества и интервала между KEEPALIVE-пробами.

Общие рекомендации могут звучать так: если вы на практике получаете большое количество сообщений от клиентов об ошибках сохранения результатов работы по причине конфликта блокировки без видимых на то причин, т.е. при отсутствии конкурирующих соединений, работающих с теми же данными, то вам надо увеличивать реакцию системы на отключение зависших коннектов. Практически величина KEEPALIVE_ TIME может составлять от 1 минуты и более – вы сами должны оценить время выполнения самой длительной транзакции в системе, чтобы не перегружать сетевой трафик KEEPALIVE-проверками нормально работающих соединений, запустивших длительные транзакции. Величина KEEPALIVE_ INTERVAL - от 10 секунд и более, а величина KEEPALIVE_ PROBES - от 5 проверок и более. Помните, что большое количество проверок и малый интервал между ними могут существенно увеличить сетевой трафик при большом количестве одновременно работающих пользователей.

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

И, наконец, еще несколько примеров общих конфигураций. Под временем простоя будем подразумевать время, в течение которого пользователи не смогут обновить данные, обновление которых начато транзакцией, открытой зависшим соединением. Итоговое время – это время, по истечении которого зависшее соединение будет закрыто.

  • Клиенты используют модемные соединения, в системе преобладают короткие транзакции, время простоя ограничено 3 минутами.
KEEPALIVE_TIME 1 минута
KEEPALIVE_PROBES 3
KEEPALIVE_INTERVAL 30 секунд
ИТОГО 3 минуты
  • Клиенты используют доступ по локальной сети, в системе преобладают короткие транзакции, время простоя ограничено 2 минутами.
KEEPALIVE_TIME 30 сек
KEEPALIVE_PROBES 5
KEEPALIVE_INTERVAL 10 сек
ИТОГО 90 секунд
  • Клиенты используют любые соединения, время простоя не регламентируется.
KEEPALIVE_TIME 15 мин
KEEPALIVE_PROBES 4
KEEPALIVE_INTERVAL 1 мин
ИТОГО 20 минут
  • Клиенты используют любые соединения, в системе возможны длительные транзакции, время простоя ограничено 15 минутами.
KEEPALIVE_TIME 12 мин
KEEPALIVE_PROBES 7
KEEPALIVE_INTERVAL 15 сек
ИТОГО 14 минут

Надеемся, приведенных примеров будет достаточно для правильной настройки механизма KEEPALIVE стека TCP.


Впервые опубликовано с разрешения автора на www.ibase.ru, 2005.

Оригинал статьи

English  Русский 
Валюта:
(пусто)
 
Блог / Новости
Flag Counter
Империалъ, Ооо