Header RSS-подписка на обновления сайта eMail-подписка на обновления сайта

Нужен ли нам сервис SQL Server Browser? Часть 2/3.

SQL Browser и экземпляр по умолчанию.


Так же мы предлагаем аренду кофемашин Nuova Simonelli с нашим бариста на мероприятия Кофемолка-дозатор с электронной панелью c двухстрочным дисплеем имеет съемный прозрачный пластиковый загрузочный бункер в верхней части (вместимость - 1,6кг), электронный дозатор с мгновенным помолом. Производительность -10 кг/день, скорость помола - 900 оборотов в минуту. Диаметр жернова - 75мм. 366bef3a

Экземпляр по умолчанию имеет стандартный порт 1433.

Для начала запустим SQL Server Configuration Manager и убедимся, что тестируемый нами сервис выключен:

SQL_Browser_is_stopped

В той же утилите убедимся, что сам экземпляр по умолчанию запущен и слушает запросы клиентов. Если вы меняли порт этого экземпляра (что маловероятно, но не исключено), верните его в стандартное значение 1433.

Конфигурируем наш тест-клиент

1
2
3
const string instName=null;
const string ipNum="192.168.81.3";
const int portNum=1433;

и запускаем его. Разумеется — успех:

Try connect to: 192.168.81.3,1433
Connection is established!

Пробуем подключится без указания порта (через присвоение константе portNum значения 0) и снова полный OK. Итак, факты говорят нам о том, что для «стандартного» экземпляра по умолчанию (то бишь «садящегося» на порт 1433) сервис SQL Browser тотально не нужен. Не менее очевидный факт говорит о том, что этот самый стандартный порт клиент может как указывать в строке подключения, так и игнорировать его.

Что будет если в указанной ситуации все-таки запустить сервис SQL Browser? Ничего! Ну то есть на его запуск и поддержку в рабочем состоянии уйдет некая доля RAM/CPU нашего сервера (впрочем, это будут сущие крохи) но во всем остальном изменений будет ровно 0. Финальный результат будет тот же (успешное подключение клиента) и достигаться с технической точки зрения он будет точно так же — прямым и безусловным обращением к порту 1433. Иными словами, при подключении к экземпляру по умолчанию никакие «посредники» ни нам, ни нашим клиентам не требуются. И низкоуровневая сетевая библиотека реализующая физическое подключение попросту игнорирует факт наличия обсуждаемого сервиса даже не пытаясь отправить последнему хотя бы один сетевой пакет. Точка.

Наконец, любопытно отметить, что для нашего «сетевого, но локального» подключения целевой сервер можно задать пятком способов. То есть, константе ipNum можно с равным успехом присвоить такие строки:

  • 192.168.81.3
  • WINR2
  • 127.0.0.1
  • . (то есть просто точка)
  • localhost
  • (local)

И, представьте себе, любой вариант приведет к успешному подключению к требуемому экземпляру по умолчанию! Правда, тут стоит сделать небольшое ответвление от основной канвы нашей беседы и рассмотреть пару настроек сетевого протокола сервера не имеющих никакого отношения к SQL Browser, но имеющих прямое отношение к только что приведенному списку и заявлению «работает все!» относительно него.

Listen All и индивидуальные IP-адреса.

Вы, несомненно, знаете, как открыть окно свойств протокола TCP/IP для того или иного экземпляра:

TCP_IP_Properties

Указанное окно состоит из двух закладок — Protocol и IP Addresses. Опции настроек в них фигурирующие более-менее ясны и понятны, но автор регулярно получает от своих слушателей два вот каких вопроса.

Во-первых, что делает и на что влияет опция Listen All на первой закладке:

Listen_All_option

А, во-вторых, что на второй закладке делают разделы опций называемые IPx (где x — целое число начиная с 1) и на что влияют опции Active и Enabled в пределах каждого такого раздела:

IPx_sections

Действительно, данные опции затрагиваются столь редко, что найти им вменяемое объяснение тяжело даже в англоязычной SQL-литературе. Вот и в нашей беседе менять их значения нет ровным счетом никакой необходимости, они просто нам «под руку подвернулись». А история с ними такая.

Сразу после запуска сервис любого экземпляра опрашивает все физические сетевые адаптеры того компьютера где этот самый сервис был запущен на предмет всех IP-адресов под которые данные сетевые адаптеры были в свое время (очевидно — в момент их инсталляции) сконфигурированы. После чего под каждый такой адрес заводится раздел IPx как это показано на последнем рисунке. Под какой именно адрес заведен данный раздел видно из значения опции IP Address в границах самого раздела. Скажем на той же последней иллюстрации видно, что раздел IP1 заведен для обслуживания адреса 192.168.81.3. А всего на машине автора с ее единственным сетевым адаптером сервис SQL Server обнаружил четыре сетевых адреса и, как легко догадаться, завел четыре раздела IP1-IP4, а именно:

  • раздел IP1 обслуживает адрес 192.168.81.3
  • раздел IP2 обслуживает адрес ::1
  • раздел IP3 обслуживает адрес 127.0.0.1
  • раздел IP4 обслуживает адрес fe80::100:7f:fffe%12

Обсуждать каждый сетевой адрес и причину его возникновения не станем, иначе мы уедем «вбок» от нашей основной темы уж очень сильно. Отметим лишь, что адреса второй и четвертый, выглядящие несколько непривычно и выбивающиеся из канонического формата a.b.c.d являются стопроцентными и настоящими IP-адресами. Просто они записаны в формате IPv6, а не в гораздо более распространенном (пока еще) IPv4. :)

Теперь возвращаемся на закладку Protocol и опцию этой закладки Listen All. Если последняя имеет значение Yes то все разделы IPx, со всеми их опциями, не играют никакой роли. :) Да, забавно, но вот так. В этом случае настройки берутся из особого раздела на закладке IP Addresses, а именно из раздела IPAll:

IPAll_section

Итого, если Listen All установлен в Yes, то именно в этом, показанном только что разделе, следует произвести выбор между динамическим и статическим назначением номера порта, а так же указать конкретную цифру если выбран второй вариант. На разделы IPx можно вообще не обращать внимания, и лучше их даже свернуть, благо у каждого такого раздела есть предусмотрительно заготовленная кнопка «плюс-минус» именно для этих целей. Ну а все вместе это означает: клиент может подключаться к серверу по любому адресу, причем номер порта будет единым для всех адресов. Помните, что в конце предыдущего раздела автор заметил, что к экземпляру по умолчанию наш «тест-клиент» может подключаться (помимо прочего) и по адресу 192.168.81.3, и по адресу 127.0.0.1? Так вот это — одно из следствий установки опции Listen All в значение Yes. Кстати говоря, это значение разбираемой опции по умолчанию.

Ну а если для той же опции выбрать прямо противоположное значение No? А вот тогда игнорируется уже как раз раздел IPAll на закладке IP Addresses, а «в игру» вступают разделы IPx. Ведь когда мы можем захотеть выбрать No для Listen All? Когда, очевидно, один из зарегистрированных на сетевой плате адресов нам «не нравится». Ну вот не хотим мы принимать подключения по 192.168.81.3, и все тут! По 127.0.0.1 — да с нашим удовольствием, а по 192.168.81.3 — ни-ни. Такой разворот вопроса, конечно, не шибко характерен для реальных условий реальных IT-систем, но, не менее несомненно, что указанное желание может возникнуть у того или иного DBA/системного администратора. В этом случае последний устанавливает Listen All в No, после чего ему не остается ничего другого как поработать с каждым из зарегистрированных IP-адресов персонально. А именно, для каждого отдельного IP-адреса требуется решить:

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

Да, вы все поняли правильно. Есть возможность принимать подключения по 192.168.81.3 на порт 1433, а по 127.0.0.1 — на порт 17098, а то и вовсе на порт назначаемый динамически. Для этого, как легко убедиться из предпоследней и последней иллюстраций, каждый IPx раздел имеет свои собственные опции TCP Dynamic Port/TCP Port. Вот именно через них мы и проводим подобный выбор.

Что же касается первого решения (активен ли данный IP-адрес в принципе) то кажется более-менее очевидным, что для указания нашего выбора в этом вопросе вполне достаточно одной опции с вариантами Yes/No, On/Off, Enable/Disable и иже с ними. Что же делают в каждом IPx разделе две опции — Active и Enabled, причем у каждой своя пара возможных значений Yes/No? :idea: Тут дело в немного корявом юзер-интерфейсе обсуждаемого окна настроек. Первая опция (Active) не должна была быть оформлена в виде выпадающего комбобокса, ибо никакого выбора она не предоставляет. Это исключительно информационное поле, говорящее нам о технической готовности самого сетевого адаптера обслуживать указанный IP-адрес (если в этом поле значится Yes), либо об отсутствии такой готовности (если там же стоит No). Значение этой опции проставляется окном диалога автоматически и наш выбор не влияет абсолютно ни на что. Если адаптер готов обслуживать адрес, а вы выставите Active в No и щелкните OK, то тут же открыв ту же самую закладку вы убедитесь, что Active снова имеет значение Yes. Одним словом, Active следовало бы оформить как текстовое поле без возможности редактирования, а проще говоря выбрать для него давно известный интерфейсный элемент label.

Ну а Enabled является уже самым настоящим и реальным переключателем. Выставляя его в Yes мы разрешаем клиентам подключение по указанному адресу, в No — запрещаем.

Допустим, что для нашего экземпляра сервера по умолчанию Listen All имеет дефолтовое же значение Yes. Запустим наш тест-клиент и убедимся, что последний прекрасно устанавливает соединение как по 192.168.81.3, так и по 127.0.0.1:

Try connect to: 127.0.0.1
Connection is established!

Try connect to: 192.168.81.3
Connection is established!

Переведем Listen All в No, опцию Enabled для секции IP1 тоже в No, а Enabled для секции IP3 в Yes. Не забудем рестартовать сервис экземпляра по умолчанию, что бы новые настройки были «подхвачены». Подключение по 127.0.0.1 (IP3) осталось, подключение по 192.168.81.3 (IP1) более невозможно:

Try connect to: 127.0.0.1
Connection is established!

Try connect to: 192.168.81.3
Error detected: A network-related or instance-specific error occurred while
establishing a connection to SQL Server. The server was not found or was not
accessible. Verify that the instance name is correct and that SQL Server is configured
to allow remote connections. (provider: TCP Provider, error: 0 - No connection
could be made because the target machine actively refused it.)

Не забудьте по окончанию опытов вернуть Listen All в гораздо более привычное ей значение Yes!

Экземпляр по умолчанию имеет нестандартный порт.

Возвращаемся в основную «колею» рассказа. Как мы убедились парой разделов назад, если экземпляр по умолчанию занимает предписанный ему IANA 1433-й порт, то клиент подключается к нему прекрасно и услуги обсуждаемого сервиса SQL Browser совершенно не требуются. Вопрос более интересный — что если тот же экземпляр предпочтет выбрать (не сам конечно, а через управляющего им DBA) нестандартный порт? А то и вовсе возьмет DBA да и сконфигурирует динамическую настройку порта в момент запуска сервиса — что тогда?

Убедившись, что сервис SQL Browser продолжает бездействовать, изменим порт прослушиваемый экземпляром по умолчанию на, допустим, 15888. Как нам хорошо известно из предыдущего раздела такие изменения следует производить на закладке IP Addresses окна свойств протокола TCP/IP, а именно в разделе IPAll последней:

Change_TCP_port

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

1
2
3
const string instName=null;
const string ipNum="192.168.81.3";
const int portNum=0;

Результат, в общем-то, ожидаем:

Try connect to: 192.168.81.3
Error detected: A network-related or instance-specific error occurred while
establishing a connection to SQL Server. The server was not found or was not
accessible. Verify that the instance name is correct and that SQL Server is configured
to allow remote connections. (provider: TCP Provider, error: 0 - No connection
could be made because the target machine actively refused it.)

И то сказать, что же мы хотим от сетевой библиотеки клиента? Что бы та наугад перебирала все доступные порты удаленного сервера с мыслью «авось повезет»? Нет уж — не соизволил клиент явно указать порт, а на предполагаемом порту 1433 ничего не нашлось — проблемы клиента. То есть наши с вами.

Что ж — запустим в работу «виновника торжества»

SQL_Browser_is_running

и будем надеяться, что он подскажет клиенту правильный, хоть и нестандартный порт. Запускаем клиента еще раз, однако результат тот же самый что был при остановленном сервисе SQL Browser — неуспех подключения. Тогда пробуем сконфигурировать клиента с явным указанием номера порта:

1
2
3
const string instName=null;
const string ipNum="192.168.81.3";
const int portNum=15888;

И, наконец-то:

Try connect to: 192.168.81.3,15888
Connection is established!

Однако, надо думать, что если порт указан явно, то никакое мапирование и не требуется? В подтверждении этой идеи останавливаем SQL Browser и убеждаемся, что мы молодцы и все поняли правильно — клиент продолжает подключаться к нашему нестандартному экземпляру по умолчанию и при выключенном сервисе SQL Browser.

Попробуем назначить нашему экземпляру по умолчанию порт динамически, во время старта сервиса. Для этого в том же разделе IPAll стираем все значения для опции TCP Port, а для TCP Dynamic Port выставляем 0:

Change_TCP_port_to_dynamic

И снова рестартуем сервис экземпляра по умолчанию. Убеждаемся, что история полностью повторяется — ни с запущенным, ни с остановленным сервисом SQL Browser клиент не способен подключиться к экземпляру по умолчанию если только он не укажет верный порт. Кстати, раз уж речь об этом зашла, скажите-ка — а откуда вы, как DBA, возьмете номер порта назначенного экземпляром самому себе динамически, дабы затем сообщить это число тому же программисту клиента? Не сомневаюсь, что вы привели как минимум один способ решения этой нехитрой задачи, но скорее всего, вы предложили несколько вариантов. Автор и сам знает их порядка пяти, но остановимся на самом простом — вновь откроем окно свойств протокола TCP/IP → закладка IP Addresses → раздел IPAll. На этот раз мы там видим вовсе не 0 установленный как раз перед рестартом сервиса, а вот такую цифру:

Discovery_dynamic_port_number

Вот и требуемый порт нашелся — 1069, на сей раз. Разумеется, если мы сконфигурируем наш тест-клиент вот так:

1
2
3
const string instName=null;
const string ipNum="192.168.81.3";
const int portNum=1069;

то сообщение

Try connect to: 192.168.81.3,1069
Connection is established!

будет ожидать нас вне зависимости от того, работает ли сервис SQL Browser или же он остановлен. Более того, если бы в рамках экспериментов текущего раздела мы «копнули» бы чуть глубже, и с помощью той или иной утилиты посмотрели бы какие сетевые пакеты шлет наш клиент к SQL Browser и какие пакеты получает в ответ, то выяснили бы очень занятную вещь: никакие не шлет и уж тем более никакие не получает.

Слов было сказано немало, а финальный вывод умещается в одну строку: сетевые клиентские библиотеки Microsoft при подключении к экземпляру по умолчанию тотально игнорируют сам факт существования такого программного продукта как сервис SQL Browser. Причем конкретный порт (в том числе и стандартный 1433) прослушиваемый указанным экземпляром на это игнорирование никак не влияет. Точка и end of story.

Экземпляр по умолчанию и выделенное административное соединение (DAC).

Про специальное, «админское», подключение к серверу, оно же dedicated administrator connection, оно же DAC знают, конечно же, все. Мы не будем останавливаться на вопросах «когда» и «в каких случаях» — наша статья не об этом. Мы сфокусируемся на вопросе как реализовать это подключение, то бишь как нам соединится с сервером именно по DAC, а не по линии для простых «юзеров».

Всеми нами любимый BOL в статье Служба браузера SQL Server сообщает, что:

Браузер SQL Server предназначен для выполнения трех задач: 1. просмотра списка доступных серверов; 2. соединения с нужным экземпляром сервера; 3. соединения с конечными точками через выделенное административное соединение (DAC).

Как вы помните, в начале статьи автор отвел 99% функционала сервиса SQL Browser на задачу номер 2 из последнего списка и 1% на задачу 1. А сколько же приходится на третью задачу? Ведь похоже, без обсуждаемого нами в настоящий момент сервиса мы просто не сможем воспользоваться DAC? Ну — давайте смотреть. Напомню, что в настоящий момент упомянутый сервис у нас выключен.

Для примера возьмем того клиента подключение к DAC через которого реализуются, наверно, чаще всего. Поскольку мы будем пытаться «DAC-подключиться» к экземпляру по умолчанию и при этом на том же самом компьютере, на котором запускается указанная утилита, то синтаксис для такого подключения будет архипростым:

sqlcmd -A

Запускаем и...

c:\>sqlcmd -A
1>

Все отлично подключено и утилита готова принимать наши команды и отправлять их по DAC-каналу. Ладно, а если мы хотим в Management Studio произвести такое же подключение? Попробуем:

DAC_Connection_from_Management_Studio

И снова все прекрасно, все подключено. Так в чем смысл замечания BOL? Какая связь между SQL Browser и DAC-подключением? А дело, как выясняется, в следующем.

Как было пояснено в начале статьи, в «давние-стародавние» времена, в организации IANA под нужды программного продукта SQL Server были зарегистрированы не один порт, а два: 1433 (про него нам добавить решительно нечего) и 1434. Как вы думаете, а вот этот второй — зачем регистрировался? Да что б по нему «DAC-коннекшен» устанавливался! То есть DAC это не какой-то там резервный сетевой адаптер, плюс отдельный сетевой кабель, плюс вспомогательный сервис... Все значительно скромнее — просто отдельный порт. Подключились к экземпляру по умолчанию через 1433? Так это обычное «юзерское» подключение. Подключились к тому же самому через 1434? Так это «необычное» DAC-подключение. Наш тест-клиент тоже может запросто необычно подключиться, надо лишь его настроить:

1
2
3
const string instName=null;
const string ipNum="WINR2";
const int portNum=1434;
Try connect to: WINR2,1434
Connection is established!

Небезынтересно отметить, что в этом последнем эксперименте имя целевого сервера указанное как WINR2/127.0.0.1/.(точка)/(local) «прокатывает» а вот указанное как 192.168.81.3 — нет. Связано это с тем, что DAC подключения принимаются только от локальных клиентов. А от удаленных (пусть даже с приставкой «псевдо-») — нет. Впрочем, сервер можно настроить так, что бы запросы на DAC-подключения принимались и от последних тоже, но это уже отдельная история.

Итак, пока прослушивание DAC-запросов идет для экземпляра по умолчанию через порт 1434 наш многострадальный сервис SQL Browser вновь оказывается «не при делах». Уже начинается закрадываться вопрос — а он вообще когда-нибудь включится в работу? Ну это мы еще посмотрим, а пока что отметим — теоретически допускается возможность, что экземпляр по умолчанию выберет для прослушивания порт иной, чем 1434. Автор, строго говоря, не видел такого ни для одного экземпляра по умолчанию за всю свою 12-ти+ годичную SQL-карьеру. Все имели «DAC-порт» под номером 1434. Кроме того, если такое случится, становится непонятным — а к чему IANA «напрягалась», порты там всякие регистрировала? Однако считается, что такое не исключено. Так вот только в этом (мифическом, с точки зрения автора) случае у SQL Browser появляется шанс «выйти на сцену». Потому что тогда, та же утилита sqlcmd обнаружив у себя в командной строке флаг -A, но не обнаружив DAC на положенном ему месте, то бишь на порту 1434, обратится-таки к указанному сервису с сакраментальным вопросом «а где он»? На что получит вполне вежливый ответ — «а на порту 12707 он» (это пример, конечно). После чего DAC-соединение будет успешно установлено. Однако, даже в этом случае, сама вероятность возникновения которого исчезающе мала, можем ли мы утверждать, что SQL Browser совершенно необходим нам для реализации DAC-подключения? Не можем мы такого утверждать! Потому что:

  • мы пройдем (обыкновенно на диске C: сервера) по пути который не то что бы легко запомнить, но легко «вывести дедуктивно». Например на машине автора это путь c:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\. Иными словами это та папка куда SQL Server складывает свои так называемые журналы ошибок (error logs);
  • в этой папке непременно будет файл ERRORLOG без всяких расширений — последняя версия журнала;
  • открыв указанный файл в любом plain-text «читалке» мы учиняем там поиск по словосочетанию Dedicated admin connection support и, скорей всего, находим ровно одну строку вот такого, примерно, содержания: Dedicated admin connection support was established for listening locally on port xxxxx, где xxxxx — искомая нами цифра Например тот самый порт 12707.

После чего SQL Browser вновь оказывается не у дел, ибо в нашем тест-клиенте мы пишем:

1
2
3
const string instName=null;
const string ipNum="WINR2";
const int portNum=12707;

в утилите командной строки мы пишем

sqlcmd -S127.0.0.1,12707

ну а в студии так и вовсе:

DAC_Connection_from_Management_Studio_with_port_specification

И все прекрасно подключается и без SQL Browser. Главное помните, что DAC — это не что-то такое из области нанотехнологий :) . Это самое обычное подключение только по особому порту. Если мы знаем номер последнего — дело в шляпе и никакой SQL Browser нам помешать (а равно и помочь) не в силах. И еще раз подчеркну, что почти наверняка последние описываемые телодвижения будут просто лишними, поскольку 99.9% всех существующих экземпляров по умолчанию ожидают DAC-подключений на порту 1434, а в этом случае все происходит совершенно автоматически.

В завершении текущего раздела отметьте себе, что в отличии от нормального порта «для юзеров», порт для DAC-подключения невозможно назначить статически. Ну, по крайней мере, официально невозможно. Всякие недокументированные «хаки» никто не отменял разумеется, однако это не тот случай что бы уделять им хоть сколько-нибудь пристальное внимание. Удовлетворитесь портом 1434 и не выдумывайте, мой вам совет. Так вот «DAC-порт» всегда выбирается динамически, однако, как было отмечено выше, именно для экземпляра по умолчанию он, то есть сервис того самого экземпляра, обязан динамически выбирать порт 1434 (то есть по факту привязка все же статична), ибо IANA и все такое... Кстати, аналогичное поведение прослеживается и для именованных экземпляров. Если при первом в жизни старте такого экземпляра для DAC-подключения был динамически выбран порт с номером X, то этот X сохраняется при всех последующих перезапусках того же экземпляра, если только не будет самых серьезных оснований (как пример — сторонний софт взял и захватил тот же порт X под свои нужды) это число изменить. И еще одно, кстати — существует довольно широко распространенное заблуждение, что все экземпляры SQL Server на одном физическом компьютере используют для DAC-подключений один и тот же порт, а именно 1434. Так вот — отнюдь, и если подумать становится понятным что это невозможно и чисто технически. Ситуация идентична «нормальным» портам, то есть у каждого экземпляра свой, персональный порт для выделенных административных соединений. Впрочем к обсуждению именованных экземпляров мы как раз и переходим.