Гость
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe) / 16 сообщений из 16, страница 1 из 1
05.12.2017, 12:28
    #39564302
MyasnikovIA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
Доброго времени суток.
Решил поделиться с сообществом альтернативной технологией обмена данными между серверами 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
05.12.2017, 13:44
    #39564378
eduard93
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
MyasnikovIA, а вы не смотрели в сторону асинхронного взаимодействия?
...
Рейтинг: 0 / 0
05.12.2017, 16:34
    #39564554
MyasnikovIA
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
eduard93,

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

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

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

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

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

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

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

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

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

Вспомнил байку, услышанную когда-то от пожилого сантехника. Учитель ему говорил: "Паша, делай хорошо. Х%ёво и так получится".
...
Рейтинг: 0 / 0
06.12.2017, 16:07
    #39565220
kalin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
MyasnikovIA,
В году этак 2000 писал с целью передачи большого объема данных из Cache в клиентское приложение. Там через socket из Cache командой write шел поток бинарных данных.
На сегодня для взаимодействия с Cache есть более продвинутые и унифицированные решения.
...
Рейтинг: 0 / 0
06.12.2017, 23:25
    #39565464
eduard93
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
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
06.12.2017, 23:26
    #39565465
eduard93
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
В первом ответе сервера было:
Код: sql
1.
{"TaskId":12608}
...
Рейтинг: 0 / 0
06.12.2017, 23:28
    #39565467
eduard93
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
Поправил на GitHub код так, чтобы TaskId всегда был Integer в JSON.
...
Рейтинг: 0 / 0
08.12.2017, 12:09
    #39566506
Alexey Maslov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Организация обмена данными между серверами Cache' через Socket коннект (PuTTY.exe)
eduard93Пример асинхронного REST взаимодействия...Эдуард,

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

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

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

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


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