powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
16 сообщений из 16, страница 1 из 1
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39564302
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Доброго времени суток.
Решил поделиться с сообществом альтернативной технологией обмена данными между серверами Cache’ и сторонними языками программирования, поддерживающие Socket коннекты.
https://github.com/MyasnikovIA/ZSrvController

Для начала, немного о причине появления этой технологи:
Появилась необходимость получать большие объемы данных между двумя серверами Cache’. Задача казалось бы простая, и решается стандартными методами, с применением вэб технологий, но при реализации, лично я столкнулся с подводными камнями. Главной проблемой стала ошибка “Таймаута”. Данные перед отправкой очень долго подготавливались. Можно включить мозг и начать оптимизировать предварительную подготовку данных, но было лень это делать, и я пошел другим путем.
Был разработан контроллер, позволяющий прямое Socket соединение между серверами, а за одно и между любыми средствами разработки поддерживающие сокеты.

Сервер поддерживает авторизацию и следующие команды:
Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
   "ip"         -  Получить IP адрес клиента со стороны сервера
   "run: w $h"  -  Выполнить однострочную команду
   "cls"        -  Очистить буфер команд на стороне сервера
   "read"       -  Прочитать буфер команд записанные на стороне сервера
   "run"        -  Выполнить команды записанные в буфере на стороне сервера
   "runline"    -  Выполнить построчно команды записанные в буфере на стороне сервера
   "key"        -  Получить ключ сесии
   "exit"       -  Разорвать соединение
   "ping"       -  тестовый запрос (после него произойдёт разрыв соединения)
   "gl"         -  показать имя  глобал в котором хранится буфер
   "gl:^GBuff"  -  Установить имя  глобала в котором хранится буфер
   "setapp:AppName"- Указываем название приложение из которого подключились 
   Все остальные строки записываются в буфер  на стороне сервера.



Проверить работу можно применив PuTTY.exe

Если кого заинтересует этот контроллер, и появятся идеи, как улучшить код, буду рад внести изменения.


Пример подключения между серверами, и выполнения MUMPS команды (взят из документации к классу)
Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
      s obj=##class(%ZMSrv.Controller).%New()
      s obj.Host="127.0.0.1"
      s obj.Port=6006
      s obj.UserName="_SYSTEM"
      s obj.UserPass="SYS"
      s obj.NameSpace="USER"
      if obj.Connect()=1 {
         w !,obj.Send("ip")     
         w !,obj.Send("run: w $ZU(110)")       
         ; Наполняем буфер командами Cache'
         d obj.Send(" for a=1:1:100  d ")       
         d obj.Send(" .   w $JOB_"":""_a         ")      
         d obj.Send(" .   w $c(13,10) ")     
         w !,obj.Send("run") ; запустить выполнение команд в буфере
         d obj.Send("cls")   ; Очистить буфер на стороне сервера 
         w !,"SessionKey: "_obj.SessionKey
      }else{
         w !,"Error: "_obj.Error,!
      }
      d obj.DisConnect()
      q



Получить объект по ID
Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
          s obj=##class(%ZMSrv.Controller).%New()
          s obj.Host="127.0.0.1"
          s obj.Port=6006
          s obj.UserName="_SYSTEM"
          s obj.UserPass="SYS"
          s obj.NameSpace="SAMPLES"
          if obj.Connect()=1 {
            s ExternalObject=obj.GetObject("Cinema.Film","1" )  
            zw ExternalObject
          }else{
            w !,"Error: "_obj.Error,!
          }
          d obj.DisConnect()



Получить объекты из Query запроса
Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
                  s obj=##class(%ZMSrv.Controller).%New()
                  ;   s obj.Host="127.0.0.1"
                  ;   s obj.Port=6006
                  ;   s obj.UserName="_SYSTEM"
                  ;   s obj.UserPass="SYS"
                    s obj.NameSpace="SAMPLES"
                    if obj.Connect()=1 {
                      if obj.SqlQuery("","%Dictionary.ClassDefinition:Summary" )'=1  q
                      for  {
                          s resNext=obj.SqlQueryNext("")
                          q:resNext=0
                          if resNext="" {
                             w "Error: "_obj.Error,!
                             q
                          }
                          s re=obj.SqlQueryGet("")
                          zw re
                      }
                         
                    }else{
                      w !,"Error: "_obj.Error,!
                    }
                    d obj.DisConnect()
                    q
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39564378
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MyasnikovIA, а вы не смотрели в сторону асинхронного взаимодействия?
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39564554
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
eduard93,

Честно говоря нет. Даже не представляю как это сделать. Если подкините идею , буду очень признателен.
Дело в том что данная технология работает еще в одном проекте. И если есть более гибкое решение, почему бы не модернизировать.
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39564576
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного напомнило "MiniM InterConnect".

Как и ваша разработка, это скорее [ещё одна] технология удалённого выполнения кода, чем обмена большими объёмами данных. Если просто обходить глобал по $Query() и на другой стороне принимать, данные будут передаваться медленно по сравнению, например, с ECP. Обмен можно ускорить, если передавать глобал блоками (либо разобравшись, как работают %GOF/%GIF, либо используя блоки собственного формата). Приходилось делать и то, и другое, последнее, правда, пока не реализовано в виде обмена через сокеты.

Асинхронность: наверное, имелось в виду использование некоего фонового многопоточного механизма, такого как $system.WorkMgr.*, чтобы параллельно передавать сразу несколько глобалов; это, конечно, может ускорить пакетную передачу, но всё равно она завершится не раньше, чем передастся самый большой глобал.
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39564640
MyasnikovIA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Alexey Maslov,

Спасибо. я на днях попытаюсь разобраться с этими технологиями.

А вообще существует стандартный метод передачи данных предусмотренный компанией Intersystems? (конечно же кроме журналов и файлов)
Чтобы решать задачи аналогичной:
1) Подключится к уделенному серверу
2) Инициировать процесс
3) Дождаться окончания работы процесса
4) Забрать результат работы с удаленного сервера

И желательно без ограничений по времени и объеме данных на любом этапе :)
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39564910
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MyasnikovIA,

Готового "стандартного" метода не знаю. Обычно решается комбинацией самописного кода + ECP для удалённого доступа к глобалам. Мои терзания трёхлетней давности на эту тему отражены здесь .

Текущая реализация API Util.Proc сильно отличается от той, что была опубликована вместе со статьёй: ради надёжности и скорости работы её пришлось гораздо сильнее привязать к нашему базовому инструментарию (qWORD). В итоге без qWORD теперь работают лишь функции удалённого выполнения кода (Util.Proc::CCM) и запуска/контроля за удалёнными процессами (Util.Proc::RunJob, CheckJob).

Хочется это переписать, но времени пока нет. Сейчас бы делал на сокетах, и возможно добавил бы "экспресс-копирование" глобалов между произвольными серверами (блочное), не используя ECP. Да, и писал бы на стандартном M[umps].

Вспомнил байку, услышанную когда-то от пожилого сантехника. Учитель ему говорил: "Паша, делай хорошо. Х%ёво и так получится".
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39565220
kalin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MyasnikovIA,
В году этак 2000 писал с целью передачи большого объема данных из Cache в клиентское приложение. Там через socket из Cache командой write шел поток бинарных данных.
На сегодня для взаимодействия с Cache есть более продвинутые и унифицированные решения.
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39565464
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MyasnikovIAeduard93,

Честно говоря нет. Даже не представляю как это сделать. Если подкините идею , буду очень признателен.
Дело в том что данная технология работает еще в одном проекте. И если есть более гибкое решение, почему бы не модернизировать.
Пример асинхронного REST взаимодействия:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
/// Basic async REST example.
Class Utils.AsyncREST Extends %CSP.REST
{

Parameter CONTENTTYPE = "application/json";

Parameter CHARSET = "UTF-8";

Parameter UseSession As BOOLEAN = 1;

Parameter HandleCorsRequest = 1;

Parameter GLVN = "^AsyncREST";

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/StartTask" Method="GET" Call="StartTask"/>
<Route Url="/GetTask/:TaskId" Method="GET" Call="GetTask"/>
</Routes>
}

/// Get info about task
ClassMethod GetTask(TaskId As %Integer) As %Status
{
	Set PercentDone = ..TaskStatus(TaskId)
	
	If PercentDone = 100 {
		Set Result = ..GetCompletedTask(TaskId) 
	} Else {
		Set Result = {"TaskId" : (TaskId), "PercentDone":(PercentDone), "Alive":($Data(^$JOB(TaskId)))}
	}
	
	Write Result.%ToJSON()
	Quit $$$OK
}

/// Start new task and return result immediately
ClassMethod StartTask() As %Status
{
	Job ..Task()
	Write {"TaskId" : ($zchild)}.%ToJSON()
	Quit $$$OK
}

/// Actually do task
ClassMethod Task()
{
	Set Wait = 0 
	Set Increase = 1
	While Wait<=10 {
		Hang Increase
		Do ..LogTaskStatus( Wait * 10)
		Set Wait = Wait + Increase
			
	}
	
	Do ..LogTaskData("Some result")
}

/// Set current task progression
ClassMethod LogTaskStatus(PercentDone As %Integer(MINVAL=0,MAXVAL=100))
{
	Set:PercentDone>100 PercentDone = 100
	Set:PercentDone<0 PercentDone = 0
	
	Set @..#GLVN@($job) = PercentDone
	If PercentDone = 0 {
		Set @..#GLVN@($job, "Start") = $zdt($h, 3, 1, 3)
	} ElseIf PercentDone = 100 {
		Set @..#GLVN@($job, "End") = $zdt($h, 3, 1, 3)
	}
}

/// Specify data = task output
ClassMethod LogTaskData(Data)
{
	Set @..#GLVN@($job, "Data") = Data
}

/// Get current task progression
ClassMethod TaskStatus(TaskId As %Integer) [ CodeMode = expression ]
{
@..#GLVN@(TaskId)
}

/// Get info about completed task
ClassMethod GetCompletedTask(TaskId As %Integer) As %DynamicObject [ CodeMode = expression ]
{
{
	"TaskId": (TaskId), 
	"PercentDone": 100,
	"Start": (@..#GLVN@(TaskId, "Start")),
	"End": (@..#GLVN@(TaskId, "End")),
	"Data": (@..#GLVN@(TaskId, "Data")),
	"IsJobAlive": ($Data(^$JOB(TaskId)))
}
}

/// Remove complete task
ClassMethod ClearTask(TaskId As %Integer)
{
	Kill @..#GLVN@(TaskId)
}

}



Установка:
1. Загрузить код
2. Создать веб-приложение с REST брокером Utils.AsyncREST

Как работать:

Допустим веб-приложение называется /asyncREST.

Сначала запускаем новое задание по адресу http://localhost:57772/asyncREST/StartTask
В ответ нам придёт идентификатор задания:
Код: sql
1.
{"TaskId":4168}



Далее с любой периодичностью опрашиваем http://localhost:57772/asyncREST/GetTask/<TaskId> (в нашем случае http://localhost:57772/asyncREST/GetTask/12608 ).
В ответ придёт текущий статус задания:
Код: sql
1.
2.
3.
4.
5.
{
  "TaskId": "12608",
  "PercentDone": 20,
  "Alive": 1
}



Когда задение выполнится при очередном опросе придёт результат:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
{
  "TaskId": "12608",
  "PercentDone": 100,
  "Start": "2017-12-06 23:18:55.000",
  "End": "2017-12-06 23:19:05.000",
  "Data": "Some result",
  "IsJobAlive": 0
}
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39565465
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В первом ответе сервера было:
Код: sql
1.
{"TaskId":12608}
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39565467
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поправил на GitHub код так, чтобы TaskId всегда был Integer в JSON.
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39566506
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
eduard93Пример асинхронного REST взаимодействия...Эдуард,

новый Портал (v2018.1 / IRIS) будет его поддерживать?
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39566530
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey Masloveduard93Пример асинхронного REST взаимодействия...Эдуард,

новый Портал (v2018.1 / IRIS) будет его поддерживать?Лично я не вижу препятствий. Там не настолько кардинальные измения. И в этом примере не используется ничего из сколько нибудь специфичного типа WorkMgr или Event.
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39566648
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DAiMor,

я не про пример, а про сам Портал. Сейчас он преимущественно синхронный. Например, просмотр переменных процесса заканчивается обычно нередко таймаутом.
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39566674
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey MaslovDAiMor,

я не про пример, а про сам Портал. Сейчас он преимущественно синхронный. Например, просмотр переменных процесса заканчивается обычно нередко таймаутом.Очень сомневаюсь, что там что-то делали в этом плане. Фокус думаю был больше на другом функционале. Портал давно правда уже не трогали.
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39566684
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DAiMor...не используется ничего из сколько нибудь специфичного типа WorkMgr или Event...Класс Event стабилизировался уже давно.
Что касается WorkMgr, то действительно были серьёзные изменения между 2015.1 и 2017.1. Что-то новое появилось в этих классах в 2018.1?
...
Рейтинг: 0 / 0
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
    #39566757
eduard93
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Будет работать начиная с 2016.2 как есть. Адаптировать для REST без динамических объектов (2014.2) или вообще без REST на CSP не представляется сложным. С выходом InterSystems IRIS Data Platform скорее всего будет работать как есть.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]