Работа нескольких серверов приложений NAV 2009

NOTE – there is an updated post reg. Multiple Service Tiers in NAV 2009 SP1 here.

Перед чтением этой заметки прочитайте вначале статью про сервер приложений :)

И у партнеров-внедренцев, и у клиентов достаточно распространена ситуация, когда есть несколько БД. Например, одна для разработки, вторая боевая. Или, например, у компании-внедренца крутятся все базы его клиентов, для оперативного реагирования на ошибки и прочая.

Естественно, мы можете поставить локальные сервера приложений на все эти компьютеры, а потом менять CustomSettings.config для указания новой БД каждый раз, когда будете логиниться в базу, однако, это плохой совет.

Хороший совет в данном случае будет звучать так:

Поднять один или несколько SQL Server’ов с нужными БД;

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

На каждую машину устанавливается клиентское приложение, которое может подключиться к этим серверам приложений.

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

Простота! (Легкотня!)

Сразу, чтобы не затягивать- добавить сервер приложений ничуть не сложнее, чем скопировать папку Service в другую папку (например, назовем ее Test) и зарегистрировать в системе новую службу на основе exe-файла в этой папке, используя команду SC:

SC CREATE testServiceTier binpath= «C:\Program Files\Microsoft Dynamics NAV\60\test\Microsoft.Dynamics.Nav.Server.exe» start= auto obj= «NT Authority\NetworkService»

Это сработает, если вы внесете изменения в файл CustomSettings.config – использовать порт, отличный от 7046. Так зачем писать об этом такую длинную заметку?

Не так просто, как кажется!

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

Необходим алгоритм именования серверов приложений (непротиворечивый!), который гарантирует, что при создании нового сервера приложений (СП, Service Tier – ST) он не унаследует настройки от других ST по случайному стечению обстоятельств.

И, наконец (но это не значит, что это неважно) – обычно вам нужен еще Web Service Listener, который бы работал совместно с вашим ST (если вы намереваетесь использовать веб-сервисы).

Взглянув на все это, я решил и сделал набор .BAT-файлов, которые делают это автоматически. Можете делать с ними все, что хотите, но мне бы хотелось, чтобы все улучшения, связанные с этими файлами вы высылали мне. В этом случае мы вместе в очередной раз осчастливим все общество (сообщество Navision).

Я НЕ эксперт по части батников, хотя МНОГОМУ научился, пока их писал. Так что не будьте строги.

Первые три .BAT-файла, которые я написал:

CreateService.bat, DeleteService.bat and RecreateOriginalService.bat

Думаю, имена говорят сами за себя. Эти батники имеют ссылки на еще один .BAT-файл, на небольшой .VBS скрит и шаблон для настроек сервера CustomSettings.template. Все они описаны ниже (надеюсь, вы не спешите и доберетесь до конца).

Их надо поместить в папку, где с установленным NAV (обычно C:\Program Files\Microsoft Dynamics NAV\60\). Далее, в первую очередь надо запустить файл RecreateOriginalService.bat.

RecreateOriginalService.bat

@ECHO OFF
IF NOT «%1» == «» GOTO usage
SET NAVPATH=%~dp0
IF EXIST «%NAVPATH%service\Microsoft.Dynamics.Nav.Server.exe» GOTO NavPathOK
ECHO.
ECHO Не могу найти установочную папку сервиса
ECHO.
ECHO %NAVPATH%service\
ECHO.
ECHO Возможно, вы уже запускали recreateoriginalservice.bat
goto :eof
:NavPathOK
IF NOT EXIST «%NAVPATH%service.org\Microsoft.Dynamics.Nav.Server.exe» GOTO orgok
ECHO.
ECHO Папка уже существует
ECHO.
ECHO %NAVPATH%service.org\
ECHO.
ECHO Возможно, вы уже запускали recreateoriginalservice.bat
GOTO :eof
:orgok
C:
CD «%NAVPATH%»
SC stop MicrosoftDynamicsNavWS
CALL SLEEP.BAT 3
SC stop MicrosoftDynamicsNavServer
CALL SLEEP.BAT 3
SC delete MicrosoftDynamicsNavWS
SC delete MicrosoftDynamicsNavServer
RENAME Service Service.org
CALL createservice DynamicsNAV dummy dummy auto
COPY /Y customsettings.template service.org\customsettings.config
GOTO :eof
:usage
ECHO.
ECHO Формат вызова:
ECHO.
ECHO recreateoriginalservice.bat
ECHO.

Несколько замечаний к «сорцу»:

%~dp0 возвращает папку, в которой находится .BAT-файл (со обратном слэшем на конце C:\Program Files\Microsoft Dynamics NAV\60\)

SLEEP.BAT — маленький .BAT-файл, который просто «усыпляет» компьютер на несколько секунд;

SC stop <service> — пытается остановить сервис (если сервис находится в режиме STOP_PENDING)

SC delete <service> — пытаетеся удалить сервис (если сервис не остановлен, команда переведет сервис в режим DELETE_PENDING, который иногда может потребовать перезагрузки сервера).

CustomSettings.template – исходный CustomSettings.Config с небольшими правками.

CreateService.bat вызывается с двумя элементарными параметрами – см.ниже.

Как работает этот файл: он удаляет установленный по умолчанию ST, меняет имя папки сервиса на Service.org и снова добавляет оригинальный ST (используя настроечный файл CustomSettings.config, который был в в папке сервиса). После этого он копирует в нее новый шаблон CustomSettings.config с полями, по которым позднее отрабатывает авто-замена в CreateService.bat. CreateService создаст службу в папке, названной так же, как имя инстанса. В итоге, после запуска RecreateOriginalService.bat вы увидите в папке NAV 2 новые папки: DynamicsNAV и Service.org вместо оригинальной папки Service.

RecreateOriginalService.bat проверяет, не отрабатывал ли он уже – т.ч., пожалуйста, не создавайте ST с именем Service. Если получше посмотрите на батник – поймете, почему. Также нельзя создавать ST с названием Classic, Database, RoleTailored Client или OutlookAddin – ну уж смотрите сами, если что – пеняйте на себя.

Sleep.bat

Как мы уже увидели, RecreateOriginalService.bat использует .BAT-файл SLEEP.BAT. Основная задача этого файла – подождать несколько секунд. К сожалению, нет одинакового «заводского» способа сделать это одинаково во всех версиях Windows, поэтому прилось написать свою реализацию:

@ping 127.0.0.1 -n 2 -w 1000 > nul
@ping 127.0.0.1 -n %1% -w 1000 > nul

Работает отлично – но выглядит странно (поэтому и вынесен в отдельный .BAT-файл).

В Vista, Windows Server 2003 и 2008 есть команда TIMEOUT, но она не работает в XP.

CustomSettings.template

Файл-шаблон CustomSettings.template – копия исходного CustomSettings.config с тремя изменениями:

<add key=»DatabaseServer» value=»#DBSERVER#»></add>
<add key=»DatabaseName» value=»#DATABASE#»></add>
<add key=»ServerInstance» value=»#INSTANCE#»></add>

Идет замещение ключей DatabaseServer, DatabaseName и ServerInstance тремя т.н. «переменными».

При вызове CreateService.bat вместо «переменных» будут подставлены значения, переданные в командной строке, т.ч. редактировать конфиги уже не придется (это очень полезная вещь при тестировании на нескольких серверах приложений).

CreateService.bat

Вот тут самое интересное…

@ECHO OFF
IF «%1» == «» GOTO usage
SET SERVICE=%1
SET DBSERVER=%2
SET DATABASE=%3
SET START=%4
SET WHICH=%5
IF «%START%» == «» SET START=demand
IF «%START%» == «auto» goto startok
IF «%START%» == «demand» goto startok
IF «%START%» == «disabled» goto startok
ECHO.
ECHO Недопустимое значение четвертого параметра
GOTO usage
:startok
IF «%WHICH%» == «» SET WHICH=both
IF «%WHICH%» == «both» goto whichok
IF «%WHICH%» == «servicetier» goto whichok
IF «%WHICH%» == «ws» goto whichok
ECHO.
ECHO Недопустимое значение пятого параметра
GOTO usage
:whichok
SET type=own
IF «%WHICH%» == «both» SET type=share
SET NAVPATH=%~dp0
IF EXIST «%NAVPATH%service.org\Microsoft.Dynamics.Nav.Server.exe» GOTO NavPathOK
ECHO.
ECHO Не могу найти исходную папку сервиса
ECHO.
ECHO in %NAVPATH%service.org\
ECHO.
ECHO Возможно, вам надо запустить recreateoriginalservice.bat
goto :eof
:NavPathOk
IF EXIST «%NAVPATH%%SERVICE%\Microsoft.Dynamics.Nav.Server.exe» GOTO serviceexists
C:
CD «%NAVPATH%»
MKDIR «%SERVICE%»
IF ERRORLEVEL 1 GOTO nodir
XCOPY service.org %SERVICE% /s/e
SET SERVICEDIR=%NAVPATH%%SERVICE%
replacestringinfile.vbs #INSTANCE# %SERVICE% «%SERVICEDIR%\customsettings.config»
IF ‘%DBSERVER%’ == » GOTO editconfig
replacestringinfile.vbs #DBSERVER# %DBSERVER% «%SERVICEDIR%\customsettings.config»
IF ‘%DATABASE%’ == » GOTO editconfig
replacestringinfile.vbs #DATABASE# %DATABASE% «%SERVICEDIR%\customsettings.config»
GOTO configdone
:editconfig
NOTEPAD %SERVICEDIR%\customsettings.config
:configdone
SC CONFIG NetTcpPortSharing start= demand
SET DEP=
if «%WHICH%» == «ws» goto onlyws
SC CREATE MicrosoftDynamicsNavServer$%SERVICE% binpath= «%SERVICEDIR%\Microsoft.Dynamics.Nav.Server.exe $%SERVICE%» DisplayName= «NAV Server %SERVICE%» type= %type% start= %START% obj= «NT Authority\NetworkService» depend= NetTcpPortSharing
SET DEP=/MicrosoftDynamicsNavServer$%SERVICE%
if «%WHICH%» == «servicetier» goto notws
:onlyws
SC CREATE MicrosoftDynamicsNavWS$%SERVICE% binpath= «%SERVICEDIR%\Microsoft.Dynamics.Nav.Server.exe $%SERVICE%» DisplayName= «NAV Server %SERVICE% WS» type= %type% start= %START% obj= «NT Authority\NetworkService» depend= HTTP/NetTcpPortSharing%DEP%
:notws
IF «%START%» == «demand» GOTO :eof
IF «%START%» == «disabled» GOTO :eof
if «%WHICH%» == «ws» goto startws
SC START MicrosoftDynamicsNavServer$%SERVICE%
if «%WHICH%» == «servicetier» goto :eof
:startws
SC START MicrosoftDynamicsNavWS$%SERVICE%
goto :eof
:serviceexists
ECHO.
ECHO Служба уже существует
ECHO.
GOTO :eof
:nodir
ECHO.
ECHO Не могу создать папку сервиса

ECHO.
GOTO :eof
:usage
ECHO.
ECHO Формат вызова:
ECHO.
ECHO CreateService servicetiername [databaseserver] [«databasename»] [demand^|auto^|disabled] [both^|servicetier^|ws]
ECHO.
ECHO.

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

Первый параметр – имя сервера приложений, и он же – имя папки, в которой находится exe-файл и файл конфигурации для этого ST (поэтому он не может быть дефалтным).

Возможно, вам кажется, что хост и имя БД тоже обязательны, но если взглянуть в .BAT-файл, то видно, что в этом случае открывается блокнот с открытым конфигом, в котором вас попросят заполнить недостающую инфу. Так что параметры эти при вызове батника – не обязательные. (вот почему RecreateOriginalService.bat вызывает CreateService с параметрами DynamicsNAV dummy dummy – нам не нужен блокнот! – и помните про исходный файл конфига – он ведь тоже здесь, т.ч. никаких замен делать нельзя).

CreateService.bat может создавать как сервера приложений (Service Tiers), так и Web Service listeners, по умолчанию создается и то, и то. Можно указать опцию старта по умолчанию — автостарта, старта вручную, или вообще – выключен.

ST, созданные в результате работы CreateService.bat называются: MicrosoftDynamicsNavServer$<instancename> и MicrosoftDynamicsNavWS$<instancename> , а описанием у них будет Nav Server <instancename> и Nav Server <instancename> WS – для того, чтобы в списке служб они шли друг за другом.

Web Service listener создается со ссылкой на ST (если вы создаете оба-два), поэтому перезапуск ST влечет за собой автоматический перезапуск WS. Оба сервиса создаются со ссылкой (dependency) на NetTcpPortSharing.

Для замены переменных в шаблоне конфига на те, что указаны в командной строке, я написал небольшой скрипт — replacestringinfile VB Script (см. ниже).

Наверное, лучшим способом описать работу CreateService.bat будут несколько примеров его использования, а затем вы вновь сможете обратите к исходному коду (см.выше).

C:\Pro….60\>CreateService.bat test

Создает Service Tier и Web Service listener с именем инстанса test и открывает блокнот для указания имени сервера и базы данных (databaseserver и database). Оба сервиса стартуют вручную, и работают вместе.

C:\Pro….60\>CreateService.bat test localhost «Demo Database NAV (6-0)»

Создает Service Tier и Web Service listener с именем инстанса test, использующим демо-базу на localhost. Оба сервиса стартуют вручную, и работают вместе.

C:\Pro….60\>CreateService.bat test localhost «Demo Database NAV (6-0)» auto servicetier

Создает Service Tier и Web Service listener с именем инстанса test, использующим демо-базу на localhost. Сервис ST работает со своим отдельным процессом и стартует автоматически.

C:\Pro….60\>CreateService.bat test localhost «Demo Database NAV (6-0)» demand ws

Создает Service Tier и Web Service listener с именем инстанса test, использующим демо-базу на localhost. Сервер приложений запускается в собственном процессе и должен быть запущен вручную.

C:\Pro….60\>CreateService.bat test mydbserver «Demo Database NAV (6-0)» auto servicetier
C:\Pro….60\>CreateService.bat test mydbserver «Demo Database NAV (6-0)» auto ws

Создает Service Tier и Web Service listener с именем инстанса test, использующим демо-базу на сервере mydbserver. Обе службы старуют автоматически и используют свои отдельные процессы.

for /L %p in (1,1,50) DO ( createservice.bat test%p localhost «Demo Database NAV (6-0)» )

Создает 50 серверов приложений и 50 Web Service listener’ ов, работающих на демо-базе на локальной машине. Все пары работают в одном процессе и запускаются по запросу. Да, знаю-знаю, наверное, я единственный человек в мире, который до такого додумался – но это же просто демонстрация – сколько серверов приложения я могу создать.

Результат этого расследование – «лимита нет» — т.е. не пришлось столкнуться ни с каким ограничением (ну, понятное дело, кроме памяти и места на диске), когда я сделал просто огромное количество ST, которые надо запускать вручную.

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

DeleteService.bat

DeleteService тоже хорошая вещь. Основная работа, которую делает этот батинк – перед остановкой сервиса удостовериться, что это действительно сервер приложений, остановить его, удалить его, удалить папки – без запроса разрешения на удаление. Вроде бы работает надежно…

@ECHO OFF
IF «%1» == «» GOTO usage
SET NAVPATH=%~dp0
IF EXIST «%NAVPATH%service.org\Microsoft.Dynamics.Nav.Server.exe» GOTO NavPathOK
ECHO.
ECHO Не могу найти оригинальную папку сервиса
ECHO.
ECHO in %NAVPATH%service.org\
ECHO.
ECHO Возможно, вам надо запустить recreateoriginalservice.bat
goto :eof
:NavPathOk
C:
CD «%NAVPATH%»
IF EXIST «%1\Microsoft.Dynamics.Nav.Server.exe» GOTO serviceexists
ECHO.
ECHO Сервис не существует
GOTO usage
:serviceexists
SC query MicrosoftDynamicsNavServer$%1 | FINDSTR «STOPPED»
IF NOT ERRORLEVEL 1 GOTO dontstop
SC stop MicrosoftDynamicsNavWS$%1
CALL SLEEP.BAT 3
SC stop MicrosoftDynamicsNavServer$%1
CALL SLEEP.BAT 3
:dontstop
SC delete MicrosoftDynamicsNavWS$%1
SC delete MicrosoftDynamicsNavServer$%1
rd %1 /S /Q
GOTO :eof
:usage
ECHO.
ECHO Формат вызова:
ECHO.
ECHO DeleteService servicename
ECHO.

Несколько замечаний по тексту батника:

rd %1 /S /Q – удаляет папки без запроса разрешения

SC query MicrosoftDynamicsNavServer$%1 | FINDSTR «STOPPED» проверяет, остановлена ли служба ST

DeleteService ничего не делает с самой БД – просто удаляет службу и папки, в которые она была установлена.

И еще – если вы создали 50 служб с помощью CreateService – удалить их вот так:

for /L %p in (1,1,50) DO ( deleteservice.bat test%p )

ReplaceStringInFile.vbs

Как вы уже заметили, в CreateService необходимо провести замену «переменных» в файле на их значения – например, #DBSERVER# превращается в localhost и т.п., а спец.команды командной строки для этого нет. К счастью, у нас есть интернет — я нашел отличный VB-скрипт на http://www.motobit.com/tips/detpg_replfile/ , который делает именно то, что мне надо:

Dim FileName, Find, ReplaceWith, FileContents, dFileContents

Find = WScript.Arguments(0)

ReplaceWith = WScript.Arguments(1)

FileName = WScript.Arguments(2)

‘Read source text file

FileContents = GetFile(FileName)

‘replace all string In the source file

dFileContents = replace(FileContents, Find, ReplaceWith, 1, -1, 1)

‘Compare source And result

if dFileContents <> FileContents Then

‘write result If different

WriteFile FileName, dFileContents

Wscript.Echo «Replace done.»

If Len(ReplaceWith) <> Len(Find) Then ‘Can we count n of replacements?

Wscript.Echo _

( (Len(dFileContents) — Len(FileContents)) / (Len(ReplaceWith)-Len(Find)) ) & _

» replacements.»

End If

Else

Wscript.Echo «Searched string Not In the source file»

End If

‘Read text file

function GetFile(FileName)

If FileName<>»» Then

Dim FS, FileStream

Set FS = CreateObject(«Scripting.FileSystemObject»)

on error resume Next

Set FileStream = FS.OpenTextFile(FileName)

GetFile = FileStream.ReadAll

End If

End Function

‘Write string As a text file.

function WriteFile(FileName, Contents)

Dim OutStream, FS

on error resume Next

Set FS = CreateObject(«Scripting.FileSystemObject»)

Set OutStream = FS.OpenTextFile(FileName, 2, True)

OutStream.Write Contents

End Function

Пожалуйста, сходите на этот веб-сайт и оцените статью (если будете использовать скрипт) – я поставил «отлично» :-)

Все это замечательно – но как мне вывести эти службы в выпадающем списке Service Tiers в RTC?

При попытке выбора нового сервера приложений в RTC, вы выбираете пункт меню «Select Server…»:

При этом открывается диалог выбора сервера и фирмы:

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

Если хотите заполнить список, необходимо изменить файл конфигурации клиента, который находится на локальной машине вот по этому пути:

C:\Documents and Settings\<username>\Local Settings\Application Data\Microsoft\Microsoft Dynamics NAV\ на Windows XP и на Windows 2003 Server box, а также
C:\Users\<username>\AppData\Local\Microsoft\Microsoft Dynamics NAV\ на Vista.

Файла конфигурации называется ClientUserSettings.config, а ключ, который надо поменять — UrlHistory. Вам неоходимо изменить ключ следующим образом:

<add key=»UrlHistory» value=»localhost/DynamicsNAV,localhost/test» />

Теперь этот пункт появится в списке.

Вот в таком аспекте

Надеюсь, что с .BAT-файлами управлять серверами приложений станет проще.

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

Ах, да – за то, что вы дочитали статью до конца, вас ждет приз – по ссылке вы можете скачать все .BAT-файлы в виде архива: http://www.freddy.dk/MultipleServiceTiers.zip

Напоследок скажу – для людей, интересующихся установкой сервера БД и серверов приложений в трехзвенной архитектуре NAV полезно будет почитать документацию.

Хорошего дня!

С оригиналом заметки можно познакомиться здесь: http://blogs.msdn.com/b/freddyk/archive/2008/10/29/multiple-service-tiers.aspx

Автор:

В области Navision - с 2003 года. Профессиональные интересы: NAV, MS SQL, .NET, BPMN, IT-менеджмент. Предметная область: логистика, финансы, склады, 3PL.

Количество статей, опубликованных автором: 86.

Добавить комментарий