Внимание! Статья и ее содержимое кануло в историю. Не рекомендуется использовать данный функционал. Диприкейтед!
Но все же ее будет очень интересно почитать :)
Все дело в том, что на больших конфигурациях (ERP, Бухгалтерия) это работать не будет по причине ограничения памяти в 4ГБ в IIS для процесса w3wp.exe. На маленьких конфигурациях работать будет (и долго работает по правде говоря).
Рекомендую ознакомиться с новым TCP прокси-сервером по ссылке. В нем нет ограничений, большие конфигурации хорошо работают. В скором времени напишу об этом статью, на этом месте появится ссылка. А вот и ссылка.
Для чего, зачем и почему
Во всех командах разработки рано или поздно возникает потребность привязки изменений кода к номерам задач. В итоге команды приходят к решению в виде комментариев в хранилище 1С. Но часто ли разработчики соблюдают это правило? Также может срабатывать человеческий фактор: можно ошибиться буквой, цифрой, задачей, ее статусом, исполнителем, системой, местом работы. Приходится перевыкладывать хранилище через gitsync, переделывать связи, тратить лишнее время и силы.
Так же хочется в работу добавить эстетики. Например, при подключении к хранилищу через HTTP почему бы не убрать уродливые "*.1ccr" и не сделать красивый адрес хранилища?
При подключении через tcp на разных версиях 1С надоело угадывать, на каком порту какая версия находится.
Плюс есть, например у меня, потребность начать синхронизацию с git-репозиторием по факту помещения очередной версии в хранилище. Прилепим вызов синхронизации? Запросто!
Появилась еще одна возможность встроиться в механизм транспорта между конфигуратором и хранилищем 1С, а по пути проверять комментарии, вызывать сторонние сервисы и делать прочие полезности. И все это на знакомом нам, одинэсникам, языке программирования и веб-сервере.
Краткое описание
На Windows сервере располагаются файловые хранилища конфигураций 1С. Для доступа к ним на том же сервере настроен tcp-сервер хранилища 1С (crserver.exe). Так же настроен доступ к хранилищу по HTTP на IIS. Предполагаем, что после внедрения, доступ к хранилищам остается только по HTTP. Хранилища более не будут доступны по tcp или файловым шарам.
В IIS добавляется расширение от Microsoft "URL Rewrite" для запрета доступа к оригинальной публикации хранилища (чтобы нельзя было действовать в обход "прокси"), а так же для красивых адресов хранилищ.
На сервер устанавливается OneScript. Будем использовать его механизм HTTP-сервисов. В IIS добавляется публикация на OneScript. Внутри публикации создается файл .os, в нем на OneScript происходит обработка запросов конфигуратора. Запросы можно парсить, проверять комментарии, возвращать нативную для конфигуратора ошибку, во время запроса вызывать сторонние сервисы (например gitsync), осуществлять маршрутизацию между версиями 1С и т.д.
Не все так страшно, как кажется!
Длинное описание
Настройка доступа tcp
Справка на ИТС тут, статья от WiseAdvice здесь.
Допустим, все наши хранилища лежат на сервере в D:\Confstores\
1С рекомендует настраивать следующим образом:
crserver.exe -instsrvc | -rmsrvc -usr <пользователь> -pwd <пароль>
-start | -stop
-port <порт> -d <каталог>
Этот метод нам не подходит.
При вызове с ключом -initsrvc старая служба заменяется новой. Нам же нужно запустить сразу несколько версий 1С. Поэтому лучше воспользоваться sc.exe, где в параметрах указывать нужные версии. Каждую версию вешаем на свободный tcp порт:
sc.exe create <имя сервиса, например "1c_storage_8_3_21_1624"> binPath="C:\Program Files\1cv8\8.3.21.1624\bin\crserver.exe -srvc -port 1542 -d D:\ConfStores"
Например, так:
Отлично! Теперь мы можем подключаться из любой используемой версии 1С по соответствующему порту:
tcp://<имя_сервера>:<порт>/<имя_хранилища>
Например tcp://server:1542/erp
Доступ по HTTP
Справка ИТС по ссылке.
Создадим несколько публикаций на IIS, каждая их которых смотрит на свои tcp-порты в соответствии с версиями.
Для каждой версии должно быть по 2 файла:
Содержание web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpRuntime maxRequestLength="102400" />
</system.web>
<system.webServer>
<handlers>
<add name="8_3_21_1484" path="storage.1ccr" verb="*" modules="IsapiModule" scriptProcessor="C:\Program Files\1cv8\8.3.21.1484\bin\wsisapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="bitness64" />
</handlers>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4294967295" />
</requestFiltering>
</security>
</system.webServer>
</configuration>
maxAllowedContentLength="4294967295" - запросы конфигуратора и ответы ему могут быть довольно большими, поэтому увеличиваем допустимый размер передаваемых данных до максимального
Каждый файл должен быть под "свою" версию. Внутри 2 места для исправления: "add name="8_3_21_1484"" и путь к wsisapi.dll
Содержание storage.1ccr:
<?xml version="1.0" encoding="UTF-8"?>
<storage connectString="tcp://localhost:2543"/>
Ссылается на текущий сервер, на порт 2543. Не забудьте поменять порт на тот, который вы указали для текущей версии при настройке доступа по tcp.
Добавим под каждую версию свой пул приложения (Application pool) в IIS:
Далее в Sites -> Default Web Site надо найти папки, которые мы создавали ранее, через контекстное меню нажать "Convert to application". Не забудьте выбрать нужный Application pool, иначе по умолчанию установится DefaultAppPool:
Теперь можно пробовать подключаться к хранилищу по http:
http://<имя_сервера>/<имя_публикации>/storage.1ccr/<имя_хранилища>
Например http://server/pool_8_3_21_1484/storage.1ccr/erp
Учим IIS понимать OneScript
Для начала его нужно установить. Проверка: в cmd набрать слово oscript:
Для управления обменом с хранилищем будем использовать механизм http-сервисов OneScript.
Как это работает в двух словах: при обращении по адресу http://<имя_сервера>/<имя_публикации>/<имя_файла>.os после всех настроек будет вызываться указанный нами далее файл *.os, в котором обязательно должна быть экспортная функция ОбработкаВызоваHTTPСервиса(Запрос).
Эта функция должна возвращать ответ типа HTTPСервисОтвет (например, Новый HTTPСервисОтвет(200), где 200 - код состояния HTTP).
Между запросом и ответом и будет выстроена вся наша деятельность: анализ тела запроса, вызов сервисов, подмена ответа либо отправка оригинального ответа конфигуратора.
Чтобы сделать публикацию HTTP-сервиса OneScript, нам понадобится сделать:
1. Новую папку в "C:\inetpub\wwwroot". В нашем примере предлагаю называть ее storage. Внутри структура будет следующая:
2. В папку bin нужно поместить файлы, которые можно взять из bin установленного OneScript:
ASPNETHandler.dll
DotNetZip.dll
ICSharpCode.AvalonEdit.dll
Newtonsoft.Json.dll
OneScript.DebugProtocol.dll
OneScript.DebugServices.dll
OneScript.Language.dll
ScriptEngine.dll
ScriptEngine.HostedScript.dll
ScriptEngine.NativeApi.dll
ScriptEngine.NativeApi32.so
ScriptEngine.NativeApi64.dll
ScriptEngine.NativeApi64.so
3. Файл web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.os" type="OneScript.ASPNETHandler.ASPNETHandler, ASPNETHandler" />
</httpHandlers>
<customErrors mode="Off" />
<httpRuntime maxRequestLength="102400" />
</system.web>
<system.webServer>
<handlers>
<add name="OneScript" path="*.os" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="File" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="OneScript32" path="*.os" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" resourceType="File" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
</handlers>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4294967295" />
</requestFiltering>
</security>
</system.webServer>
<appSettings>
<add key="CachingEnabled" value="true" />
<add key="handlerLoadingPolicy" value="strict" />
</appSettings>
</configuration>
Здесь, грубо говоря, описано, какими dll обрабатывать файлы с расширением .os, допустымые размеры данных, а так же пара настроек для движка OneScript в конце.
4. Под описание storage.os выделяю отдельный следующий раздел.
5. В IIS конвертировать публикацию storage в приложение, определить для него отдельный Application pool с pipeline mode - classic и .NET CLR Version v4.0
Создание скрипта .os
В общем случае скрипт выглядит так:
Функция ОбработкаВызоваHTTPСервиса(Запрос) Экспорт
Возврат Новый HTTPСервисОтвет(200);
КонецФункции
При вызове http-сервиса, например через браузер, IIS будет искать какие dll запускать для файла с расширением .os, dll будут искать функцию ОбработкаВызоваHTTPСервиса и на возврате ожидать HTTPСервисОтвет.
Отсюда и далее буду сворачивать код в спойлеры, иначе будет занимать слишком много места.
Чтобы из файла сделать прокси хралища 1С, допишем всего пару строк:
Здесь все тривиально: получили запрос, отдали в хранилище, получили ответ, отправили конфигуратору.
Пространство для маневра открывается невообразимое :)
Моей изначальной целью был контроль комментариев. Конфигуратор при помещении версии в хранилище использует метод "DevDepot_commitObjects", а при изменении старой версии "DevDepot_changeVersion". Допишу функцию разбора запроса конфигуратора для извлечения интересующих меня атрибутов. Так же сразу произведу задел на маршрутизацию по версиям 1С:
Здесь чуть сложнее: запрос конфигуратора парсится на предмет вызываемого метода хранилища, версии платформы, комментария и имени хранилища. Если у нас настроена обрабатываемая версия 1С, отправим запрос конфигуратора по адресу именно этой версии. Можем, кстати, например, заблокировать помещение/изменение версий для всех версий 1С, кроме последней, а из прошлых версий 1С оставить только чтение. Это актуально, когда на dev контуре последний релиз, а на prod еще старый (и мы не понимаем как работает этот черный ящик хранилища и пишем в него только последней версией 1С, а читаем любыми версиями, в конце концов файловый доступ к хранилищу позволяет делать так).
По поводу нативного ответа. Понятия не имею что означает вся эта требуха из гуидов и DLL. Я ее как-то распарсил, догадался как завернуть, и оно работает в таком виде на десятке хранилищ. Подозреваю, что от версии к версии может меняться.
Выглядит нативный ответ например так:
Итоговое решение со всеми проверками будет выглядеть примерно следующим образом:
Далее вы самостоятельно можете исправить/добавить код по вашим требованиям. Например не только проверять номер задачи на принадлежность системе, а еще и статус задачи. Или исполнителя. При долгих операциях, не требующих их ожидания, можно воспользоваться механизмом фоновых заданий OneScript (мы же не хотим чтобы разработчик ждал по 10 минут помещения в хранилище?).
Но, пока что вы не сможете этим воспользоваться... Потому что надо сделать перенаправление запроса (далее).
Перенаправление запросов
В чем проблема:
На этом этапе у нас уже есть несколько публикаций в IIS:
https://<имя_сервера>/storage_8_3_20_1789/storage.1ccr https://<имя_сервера>/storage_8_3_21_1484/storage.1ccr https://<имя_сервера>/storage_8_3_21_1624/storage.1ccr https://<имя_сервера>/storage/storage.os
Первые три мы можем использовать в конфигураторе. В строке подключения к хранилищу надо указать
https://<имя_сервера>/storage_8_3_20_1789/storage.1ccr/<имя хранилища>
Они будут работать напрямую с хранилищем, а нам это не интересно. Мы хотим чтобы запросы проходили через наш OneScript файл.
Но вот к скрипту мы пока что подключиться не сможем, конфигуратор не поймет такое:
https://<имя_сервера>/storage/storage.os/<имя_системы>
И выдаст ошибку "хранилище не вижу, работать не буду". Все дело в том как конфигуратор парсит строки подключения. Например если вы укажете через tcp:
tcp://server/base
То конфигуратор поймет, что нужно подключиться к хосту server и в XML-содержимое запроса поместить имя хранилища "base".
Для HTTP подключения конфигуратор ищет имя системы обязательно по паттерну ".1ccr". Поэтому попытка заменить ".1ccr" на ".os" не увенчается успехом. Конфигуратор не знает что такое ".os". Однако же есть третий вариант:
http://server/base
Конфигуратор понимает что подключаться нужно по протоколу http, а выясняет имя хранилища как для tcp.
Я решил сделать так, чтобы у меня были красивые имена
http://server/base
Которые транслировались бы в
https://server/storage/storage.os
И поможет нам в этом...
URL rewrite
Официальное расширение от Microsoft для работы со строками запросов внутри веб-сервера IIS. Загрузить можно здесь. Установка "далее-далее-готово" на сервере, где расположен веб-сервер.
После установки оно появится тут:
UPD от 19.12.2023: при установке URL Rewrite должен установиться компонент Application request routing (на картинке слева посередине). Если он не установился автоматически (такое бывает), необходимо его установить самостоятельно отсюда https://www.iis.net/downloads/microsoft/application-request-routing (ссылки на загрузку внизу страницы). После установки ARR нужно перезайти в IIS, зайти в ARR на уровне сервера, справа Server proxy settings, установить галочку Enable proxy, нажать ОК.
Теперь можно зайти на свой Default web site и начать создавать правила:
На скриншоте их 4:
1. Красивые имена указанных хранилищ перенаправляются к файлу .os
2. 3. 4. Запрет прямого обращения к оригинальным публикациям.
Правило перенаправления выглядит следующим образом:
Дословно означает следующее: когда пришел запрос (например http://server/ERP), то:
- взять часть запроса после первого одиночного слэша
- сравнить ее с регулярным выражением ^ERP$|^BAZA1$|^UT$ (^ - начало строки, слово ERP или слово BAZA1 или слово UT, $ - конец строки) - красным добавил исправление 13.03.2023, без этого например база ERP_OLOLO тоже попадала в условие
- Ignore case - no comment
- Action type - Rewrite: подменить строку запроса на ту, которая указана в Rewrite URL (тело запроса при этом никуда не денется, просто поедет немного по другому пути)
Соответственно под такое правило у нас попадут строки подключения:
http://server/erp, http://server/baza1, http://server/ut - то есть имена ваших хранилищ. После добавления этого правила можно указывать строку в таком формате в конфигураторе.
Бинго! Запросы к хранилищу обрабатываются с помощью OneScript.
Напоследок осталось запретить подключаться напрямую к "настоящим" публикациям хранилищ. Добавить 3 правила под каждую версию 1С:
Здесь, в отличие от предыдущего правила, в Conditions добавляется {REMOTE_ADDR} Does not match the pattern 127.0.0.1. То есть правило должно работать всегда, кроме случая, когда сам сервер обращается к себе (чем перенаправление и является). Так же в Action type выбираем Custon Response со статусом кода 403 "Отказ доступа".
Заключение
Весь этот "троллейбус из буханки" работает уже полгода. За время работы были только проблемы с памятью в процессе IIS "w3wp.exe", обслуживающем Application pool для публикации прокси. Это вылечили функциями очистки мусора в скрипте. 15 разработчиков, ферма Bamboo, и много аналитиков каждый день обращаются через этот прокси к 10 хранилищам конфигураций. Разницы по скорости и ожиданиям запросов с tcp нет. В некоторых моментах даже быстрее tcp. Видимо, tcp-серверу легче держать подключение с одним хостом, чем со многими.
Обязательность указания комментариев очень помогает в сборке релизов. Огромный плюс от ухода с версионности: достаточно добавить версию на одном сервере, а работать будет у всех сразу. Вызов синхронизации с git - одно удовольствие :)
В этой статье я хотел описать не как правильно делать, а как можно.
Как правильно - вы решите для себя сами.
Буду рад обсудить материал в комментариях :)