gifts2017

Базы данных 1С8 для сетевых структур

Опубликовал Осипов Сергей (fixin) в раздел Администрирование - Распределенная БД (УРИБ, УРБД)

В статье собран опыт применения распределенных баз данных в организациях, состоящих из головного офиса и множества однотипных простых подразделений (точек).

Оглавление

Базы данных 1С8 для сетевых структур

Термины

Список точек в центральной базе

Создание новой точки

Удаление закрытых точек

Учебная база

Надежность баз

Безопасность баз

Обмены данными

Обмен данными на точке

Обмен по запросу

Обмен точки с точкой

Программный запуск утилит командной строки

Нюансы ограничения доступа к программам и сайтам

Архитектурные решения

Служебные константы

 

Базы данных 1С8 для сетевых структур

В статье собран опыт применения распределенных баз данных в организациях, состоящих из головного офиса и множества однотипных простых подразделений (точек).

На практике рассматривались организации с 30-70 точками.

Использовалась технология УРБД, т.е. обмен происходил между базами с идентичными конфигурациями. Базы точек были периферийными, центральная база – главной.

Иногда центральная база разделяется на несколько баз – центральную базу, базу склада, базу для отчетов и т.п. Между ними тоже нужно производить обмен.

Термины

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

Продавцы - пользователи точек

Менеджеры – пользователи центральной базы.

Root – вход администратора компьютера на точке

Список точек в центральной базе

Создание новой точки

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

В 1С выгрузка данных осуществляется в монопольном режиме. Выгрузка может идти долго. Существуют способы оптимизации, чтобы выгружалось меньше данных, но в любом случае основные справочники (номенклатура, контрагенты) могут выгружаться целиком, поэтому процедура вряд ли будет короче 30 минут. На практике в разных базах занимает от 30 минут до 2 часов. Поэтому лучше выгружать образ точки ночью, когда никто из пользователей не работает.

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

Удаление закрытых точек

Нельзя оставлять в плане обмена узлы, соответствующие закрытым точкам. На них накапливается информация о регистрации изменений, что увеличивает объем базы, и затормаживает ее работу.

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

Поэтому закрытую точку нужно исключать из обмена данными, и физически удалять из планов обмена.

Учебная база

Очень часто возникает потребность в учебной базе – как для учебных целей, так и просто для тренировки пользователей.

Самый простой вариант – скопировать базу из базы точки и, возможно, сделать некоторые настройки, чтобы она работала без торгового оборудования. Для таких настроек лучше написать скрипт, который будет делать это автоматически. Тогда можно обновлять учебную базу достаточно часто, ведь учебная база должна быть более-менее актуальной.

Вариант, когда учебная база включена в обмен данными

Надежность баз

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

Иногда на базах происходят сбои в работе, которые никак нельзя объяснить. Вроде бы все работает, но глючит. Тестирование и исправление базы, проверка физического состояния базы – первое, что нужно сделать в базах, прежде, чем брать в руки отладчик.

Также в базах на точках нужно отключить кэширование файлов (смотрите в статье про платформу 1С).

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

Безопасность баз

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

Как вариант – можно использовать одноразовые пароли на вход в 1С, но так можно проверить только вход в 1С:Предприятие, а не в конфигуратор.

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

Если нужно что-то изменить в данных, нужно это делать в центральной базе, где перехватить пароль администратора невозможно.

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

Обмены данными

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

Обмен данными на точке

Основные проблемы в обменах данными на точках:

  1. Нужно настроить обмен по расписанию, т.к. продавцы будут забывать и лениться делать обмен.
  2. Нужно автоматизировать прием измененной конфигурации, т.к. продавцов сложно обучить процедуре приема измененной конфигурации.

На практике мы написали скрипт на java-script, который запускался каждые 3 минуты под root на точке. Он создавал внешнее COM-соединение с базой 1С, проверял, запущен ли уже автообмен под пользователем Автообмен. Если не запущен, то проверял, сколько времени прошло с момента последнего обмена. Если больше 15 минут, выполнял обмен данными.

Обмен по запросу

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

Обмен точки с точкой

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

  1. Специальный оперативный план обмена – достаточно сложно реализовать.
  2. Выгрузка/загрузка конкретных документов через XML-файл – быстрое, дешевое и сердитое решение. Выгружается файл, почтой или на флешке отправляется на другую точку, там загружается.
  3. Обмен по запросу – если наложен обмен по запросу, то пользователь просто формирует запрос на обмен с другой точкой.

Программный запуск утилит командной строки

На точках часто возникает необходимость программно запускать служебные программы. Эти программы можно создавать при первом запуске непосредственно из 1С, но возникает резонный вопрос – в какой каталог их помещать?

Вариантов решения несколько:

  1. Учитывая, что обычно на точках файловые базы данных, можно помещать программы в каталог базы, для файловой базы его можно получить программным путем.
  2. Если база файловая или каталог базы защищен от доступа, можно использовать папку «Мои документы» - ее тоже можно получить программным путем.

Нюансы ограничения доступа к программам и сайтам

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

Архитектурные решения

Служебные константы

Для работы программы требуются различные служебные константы. Особенно это касается взаимодействия с веб-сервисами. Константы добавляются достаточно часто.

Добавление каждой константы выливается в целый комплекс мероприятий:

  1. Изменить форму констант, чтобы можно было редактировать константу.
  2. Настроить права доступа на константу.
  3. Настроить миграцию константы в точки.

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

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Alex Nikolas (alexnikolas) 21.12.11 10:39
"Пока что я бы сказал, что у нас не удалось выработать идеального расписания для обмена центра с точками" - приведи свой пример расписания и в чем проблемы - детализируй грабли

"На практике мы написали скрипт на java-script, который запускался каждые 3 минуты под root на точке" - дай подсмотреть
2. Осипов Сергей (fixin) 21.12.11 11:07
(1) да грабли в том, что много холостых выгрузок. Надо бы как-то контролировать, что не делать выгрузку пока не прошла загрузка и т.п. В общем, это открытая тема.

По поводу скрипта - нате пожалуйста, текущий рабочий JS скрыпт, запускаемый на точках раз в 3 минуты:
//=== Главная программа ===
//Настройки программы
var Base1sUser = "Автообмен";
var Base1sPassword = "";
var App1sFullName = 'C:\\Program Files\\1cv81\\bin\\1cv8.exe';
var Base1sPath = GetPathOfFile(WScript.ScriptFullName);
//Время ожидания завершения работы пользователей в миллисекундах - 3 минуты
//Т.е. это время в течении которого пользователи будут предупреждаться о том, что нужно выйти из конфигурации
var WaitTime = 1000; //1 секунд 
//var WaitTime = 180000; //180 секунд = 3 минуты

//Если передан CheckConfig тогда мы только проверяем, нужно ли обновлять конфигурацию и запускаем автообмен, 
//не дожидаясь его окончания
//100 - обновлена
//200 - не обновлена
//Если ничего не передано, то запускаем дочерний скрипт с параметров CheckConfig
//При этом, если нужно обновлять конфигурацию, то обновляем ее, если не нужно то все, конец


try { 
	main();
} catch(e){ 
	Report('При исполнении программы возникла ошибка: ' + e.description); 
	WScript.Sleep(5000); 
}

//Report('Проверяем com-соединение!'); 
WScript.Sleep(5000); 
WScript.Quit(0);

function main() {
	//Проверяем, чтобы скипт не запускался дважды 
	var ScriptName = WScript.ScriptName;
	if (IsProcessExist(ScriptName)) {
		Report('Процесс '+ScriptName+' уже запущен, эта копия будет закрыта!'); 
		WScript.Quit(1);
	}

	//Проверяем переданные параметры, определяем это основной процесс или дочерний
	isCheckConfig = false;
	if (WScript.Arguments.Length > 0) 
		if (WScript.Arguments.Item(0) == "CheckConfig")
			isCheckConfig = true;
			
	//Если нужно проверять, изменилась ли конфигурация и запускать автообмен	
	if (isCheckConfig)
		CheckConfig(); //Запускаем дочерний COM-процесс для проверки конфигурации
	else
		MainProcess();
}

function CheckConfig() {
	//Если это проверка конфигурации, дочерний поток
	//Дочерний запускается, чтобы  COM-соединение убилось, иначе оно ника не убивается

	//Получаем каталог базы
	//Report(WScript.ScriptFullName);

	Base1s = Connect1s8();

	//Нужно ли обновлять конфигурацию
	var isNeedToConfigUpdate = Base1s.НужноЛиОбновлятьКонфигурацию();
	Report('Нужно обновлять конфигурацию: ' + isNeedToConfigUpdate); 

	//Далее, запускаем автообмен силами 1С
	//Функция в 1С не должна останавливать скрипт
	//Т.е. должна запуски все делать асинхронно
	Base1s.ЗапуститьАвтообмен();
	
	//Возвращаем статус
	if (isNeedToConfigUpdate)
		WScript.Quit(200); //Нужно обновлять
	else
		WScript.Quit(100);//Не нужно обновлять
}




function Connect1s8() {
	var Base1sPath = GetPathOfFile(WScript.ScriptFullName);

	//Устанавливаем быстрое COM-соединение с 1С8
	var V8 = new ActiveXObject("V81.COMConnector");
	//var V8 = new ActiveXObject("V81.Application");
	try { 
		ConnectionString = 'File="' + Base1sPath + '";Usr="' + Base1sUser + '";Pwd="' + Base1sPassword + '"';
		var Base1s = V8.Connect(ConnectionString);
	} catch(e){ 
		Report('Не удалось создать com-соединение!' + e.description); 
		WScript.Quit(1);
	} 
	return Base1s;

}


function MainProcess() {
	//Запуск дочернего процесса
	Shell = new ActiveXObject("WScript.Shell");
	PathToRun = '"' + WScript.FullName +'" "' + WScript.ScriptFullName + '" CheckConfig';
	Report("Команда для запуски дочернего процесса:" + PathToRun);
	//Запускаем дочерний процесс и ждем его завершения
	var result = Shell.Run(PathToRun,0,true); 
	
	//Конфигурацию нужно обновлять, если дочерний поток вернул 200
	isNeedToConfigUpdate = (result == 200) 
	
	
	Report("COM-соединение должно умереть, т.к. дочерний поток умер");
	
	//Если нужно обновлять конфигурацию
	if (isNeedToConfigUpdate) {
		//Несколько секунд ждем, чтобы наверняека 
		WScript.Sleep(5000); 
		
		//Выгнать пользователей
		CloseUsers1s();

		//Обновить конфигурацию
		UpdateConfig1s(App1sFullName, Base1sPath, Base1sUser, Base1sPassword);
	}
}

function CloseUsers1s() {
	//Убиваем все процессы 1С
	var Processing = new ActiveXObject("WbemScripting.SWbemLocator");
	var Service = Processing.ConnectServer(".");
	var Items  = new Enumerator(Service.ExecQuery("SELECT * FROM Win32_Process WHERE Name = '1cv8.exe'"));
	
	for (Items.moveFirst(); !Items.atEnd(); Items.moveNext()) {
		var Item = Items.item();
		Item.Terminate(0);
		Report('Kill process 1s8'); //удаляем процесс 1с8
	}
}

function UpdateConfig1s(App1sFullName, Base1sPath, Base1sUser, Base1sPassword) {
	Shell = new ActiveXObject("WScript.Shell");
	PathToRun = '"' + App1sFullName + '" config /UpdateDBCfg' + ' /N"' + Base1sUser + '" /P"' + Base1sPassword + '" /F"'+ Base1sPath + '"';
	Report("Команда для обновления конфигурации базы данных :" + PathToRun);
	var result = Shell.Run(PathToRun,2,true); //Запускаем команду обновления конфигурациии
	Report("Результат обновления " + result);
	WScript.Sleep(5000);

}


//Возвращается путь к файлу FullName, без финального слеша
function GetPathOfFile(FullName) {
	var fso = new ActiveXObject('Scripting.FileSystemObject');
	return fso.GetParentFolderName(FullName);
}



//Проверяет, существует ли процесс с заданным именем файла
function IsProcessExist(ProcessName) {
	var Processing = new ActiveXObject("WbemScripting.SWbemLocator");
	var Service = Processing.ConnectServer(".");
	//Проверяем запущенный основной процесс, без вызовов самого себя...
	var Items  = new Enumerator(Service.ExecQuery("SELECT * FROM Win32_Process WHERE (CommandLine LIKE '%" + ProcessName + "%') AND NOT (CommandLine LIKE '%CheckConfig%')"));
	
	var Count = 0;
	for (Items.moveFirst(); !Items.atEnd(); Items.moveNext()) Count++;
	Report("Количество процессов " + Count);
	return Count > 1; 
}

function Report(Msg) {
	WScript.Echo(Msg);
}
...Показать Скрыть
3. Андрей Казанцев (ander_) 21.12.11 16:03
Позновательно. Скоро видимо такое-же предстоит. Впрос по обмену "точки с точкой". Если обменялись документами ч/з xml, то при загрузке в центральную не будет конфликта? Или это речь не о том? Суть проблемы: нужно реализовать возможность чтобы одна точка могла продать товар другой точки, взяв деньги, а клиент приехав на вторую и предъявив квиток_чек мог просто забрать товар.
4. i i (ivanbor) 20.01.12 14:57
А как реализовать, если удаленный комп работает по unix?
5. Осипов Сергей (fixin) 20.01.12 15:23
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа