07.03.2006, 15:27 | #1 |
Участник
|
Обращение к http-сервису в Аксапте
Имеется несколько http сервисов (больше 10). Время обработки запроса сервисом 3-5 сек. Аксапта обращается к этим сервисам с помощью WinInet и полученные данные сохраняет во временной таблице. Таким образом, на запрос к 10 сервисам, при последовательном обращении, уходит 30-50 сек. Хотелось бы отсылать 10 запросов сразу, а не последовательно, вот только как в Аксапте реализовать многопоточность?
Кто-нибудь может посоветовать как лучше решить такую задачу в Аксапте? Может кто-то уже решал подобные задачи в Аксапте, поделитесь опытом. |
|
07.03.2006, 16:17 | #2 |
Участник
|
можно попробовать XMLHttpRequest в асинхронном режиме и по таймеру или в цикле проверять завершился он или нет.
База знаний ERP : Axapta / Взаимодействие С Окружением |
|
|
За это сообщение автора поблагодарили: Logger (3). |
09.03.2006, 09:26 | #3 |
Участник
|
Цитата:
Сообщение от belugin
и по таймеру или в цикле проверять завершился он или нет.
По-моему такая схема будет работать если сервис один, если сервисов несколько, то: Если опрашивать сервисы в цикле, то не получается сделать запрос к следующему сервису, пока предыдущий не вернул результат. По таймеру тоже не получается, т.к. таймер только один, а как сделать в Аксапте 10 независимых друг от друга таймеров? |
|
09.03.2006, 09:31 | #4 |
Участник
|
Цитата:
Сообщение от Lucky13
Можно по подробнее с этого места:
По-моему такая схема будет работать если сервис один, если сервисов несколько, то: Если опрашивать сервисы в цикле, то не получается сделать запрос к следующему сервису, пока предыдущий не вернул результат. Цитата:
По таймеру тоже не получается, т.к. таймер только один, а как сделать в Аксапте 10 независимых друг от друга таймеров?
|
|
09.03.2006, 11:49 | #5 |
Участник
|
Кажется я понял свою ошибку: setTimeOut не выполняет функцию сразу, а выполняет через n миллисекунд, укзанных во втором параметре. Я этого не учел. Теперь все работает
|
|
05.12.2014, 10:07 | #6 |
Участник
|
|
|
07.12.2014, 16:58 | #7 |
Талантливый разгвоздяй
|
Если это в AX 2012, смотрите в сторону пакетной обработки. Разработайте периодическую операцию с поддержкой пакетной обработки и выделите там 10 задач (task), тогда при пакетной обработке эти 10 задач будут выполняться одновременно. Единственное совокупное время обработки задачи будет зависеть от самого длительно выполняющегося задания.
upd: пару ссылок по теме: http://blogs.msdn.com/b/axperf/archi...ax-part-i.aspx https://axconsultant.wordpress.com/2...h-job-ax-2012/ Последний раз редактировалось Kabardian; 07.12.2014 в 17:07. |
|
08.12.2014, 08:56 | #8 |
Участник
|
Спасибо за ответ.
У меня Ax 2009. Собственно меня не интересует параллельная обработка. Мне бы обычную однопоточную сделать. Я этим занялся впервые и хотелось бы вообще увидеть как отправлять запросы. Сейчас я вот на каком этапе X++: s = "url:/rest/2/authentication/createSession?account=ACCOUNT&login=LOGIN.dispatcher&password=PASSWORD"; code1 = winInet.internetOpen("xxx.xxx.xxx.xxx", 1, "xxx", "xxx", 0); // 1 и 0 поставил от балды code2 = winInet.internetConnect("xxx.xxx.xxx.xxx", "xxx", "xxx"); code3 = winInet.httpOpenRequest(code1, "POST", s); info (strfmt("%1 %2 %3", code1, code2, code3)); в code2 0, в code 3 тоже 0 Если правильно понимаю то при провальной работе вместо S нужно подсунуть xml файл? |
|
08.12.2014, 09:29 | #9 |
Участник
|
Может подойдет пример из Tutorial_XMLPost, там используется класс XMLHTTPRequest
|
|
08.12.2014, 09:43 | #10 |
Участник
|
У меня нет такого туториала, кстати как и класса XMLHTTPRequest. Поделитесь xpo-шником?
|
|
08.12.2014, 09:43 | #11 |
Участник
|
X++: WinInet winInet = new WinInet(...); //internetOpen вызывается в new int hURL; int hReq; int res; str ret; if (winInet.ok()) { hURL = winInet.internetConnect(servername,80); hReq = winInet.OpenRequest(hURL, url, 'POST'); res = winInet.SendRequest(hReq, hdr, data); ret = winInet.internetReadFile(hReq); } servername - адрес сервера (напр www.yandex.ru или ip) без http url - путь на сервере (если нужен) hdr - заголовок (зависит от сервера) data - это передаваемые данные, в вашем случае xml ret - ответ сервера res должен быть равен 1, ret зависит от того, что вернет сервер Еще зависит от того есть прокси сервер или нет. Если есть, то с ним тоже придется повозиться с параметрами |
|
08.12.2014, 09:47 | #12 |
Талантливый разгвоздяй
|
Если хотите использовать именно WinInet лучше на MSDN описание работы и примеры использования класса посмотреть для начала:
Using the WinINet Functions to Access the WWW Цитата:
Using the WinINet Functions to Access the WWW
Initiating a Connection to the WWW Opening a Request Adding Request Headers Sending a Request Posting Data to the Server Getting Information About a Request Downloading Resources from the WWW WinINet vs. WinHTTP. |
|
08.12.2014, 10:08 | #13 |
Участник
|
Спасибо за ответы.
Цитата:
Сообщение от Lucky13
X++: WinInet winInet = new WinInet(...); //internetOpen вызывается в new int hURL; int hReq; int res; str ret; if (winInet.ok()) { hURL = winInet.internetConnect(servername,80); hReq = winInet.OpenRequest(hURL, url, 'POST'); res = winInet.SendRequest(hReq, hdr, data); ret = winInet.internetReadFile(hReq); } у меня нет методов winInet.OpenRequest и winInet.SendRequest. У меня есть winInet.httpSendRequest но у него порядок аргументов другой и один аргумент отличается X++: boolean httpSendRequest(int _handler, BinData _file, int _size) { return _httpSendRequest.call(_handler, "Content-Type: application/x-www-form-urlencoded", 47, _file, _size); } Последний раз редактировалось smailik; 08.12.2014 в 10:12. |
|
08.12.2014, 10:29 | #14 |
Участник
|
Цитата:
Примерно вот так: X++: _httpOpenRequest = new DLLFunction(_winInet, 'HttpOpenRequestA'); _httpOpenRequest.returns(ExtTypes::DWord); _httpOpenRequest.arg(ExtTypes::DWORD); _httpOpenRequest.arg(ExtTypes::String); _httpOpenRequest.arg(ExtTypes::String); _httpOpenRequest.arg(ExtTypes::String); _httpOpenRequest.arg(ExtTypes::String); _httpOpenRequest.arg(ExtTypes::DWORD); _httpOpenRequest.arg(ExtTypes::DWORD); _httpOpenRequest.arg(ExtTypes::DWORD); _httpSendRequest = new DLLFunction(_winInet, 'HttpSendRequestA'); _httpSendRequest.returns(ExtTypes::DWord); _httpSendRequest.arg(ExtTypes::DWord); _httpSendRequest.arg(ExtTypes::String); _httpSendRequest.arg(ExtTypes::DWord); _httpSendRequest.arg(ExtTypes::String); _httpSendRequest.arg(ExtTypes::DWord); int OpenRequest(int hdl, str _url, str _verb = "POST", int flags = 0) { ; return _httpOpenRequest.call(hdl, _verb, _url, '', '', 0, flags, 0); } int SendRequest(int handle, str hdr, str data) { ; return _httpSendRequest.call(handle, hdr, strlen(hdr), data, strlen(data)); } Последний раз редактировалось Lucky13; 08.12.2014 в 10:37. |
|
|
За это сообщение автора поблагодарили: smailik (1). |
08.12.2014, 16:02 | #15 |
Участник
|
Цитата:
X++: strData = "url:/rest/2/authentication/createSession?account=ХХХ&login=ХХХ.dispatcher&password=ХХХ"; url = "http://review.maxoptra.com/"; if (winInetLocal.ok()) { hURL = winInetLocal.internetOpen("http://review.maxoptra.com/", 1, "ХХХ", "ХХХ", 0); // вот тут ответ число есть hURL = winInetLocal.internetConnect("http://review.maxoptra.com/", "ХХХ", "ХХХ"); // а вот тут ответ 0 hReq = winInetLocal.httpOpenRequest(hURL, url, 'POST'); res = winInetLocal.httpSendRequest(hReq, hdr, strData); // и тут все по нулям ret = winInetLocal.internetReadFile(hReq); // и тут 0 } |
|
09.12.2014, 00:23 | #16 |
Талантливый разгвоздяй
|
smailik, а почему именно WinInet? Этого класса даже нет в стандартной AX 2009, подозреваю у вас доработка/апгрейд класса с AX 3.0/4.0.
Вот то же самое, но используя сборки .NET и класс WebRequest: X++: static void MicrosoftWebRequestSample(Args _args) { System.Net.WebRequest webRequest; System.Net.ICredentials credentialCache; System.Net.HttpWebResponse httpWebResponse; System.IO.Stream stream; System.IO.StreamReader streamReader; str postData; System.Byte[] byteArray; System.Text.Encoding encodingUTF8; str statusDescription; str responseFromServer; ; //1. Создать запрос. webRequest = System.Net.WebRequest::Create("http://httpbin.org/post"); //этот веб-сервис отправляет в ответ данные, которые были направлены ему. webRequest.set_Method("POST"); //2. Ввести данные к отправке и ковертировать их в массив байтов postData = "url:/rest/2/authentication/createSession?account=ХХХ&login=ХХХ.dispatcher&password=ХХХ"; encodingUTF8 = System.Text.Encoding::get_UTF8(); byteArray = encodingUTF8.GetBytes(postData); //3. Изменить свойства запроса: ContentType, ContentLength. webRequest.set_ContentType("application/x-www-form-urlencoded"); webRequest.set_ContentLength(byteArray.get_Length()); //4. Если требуется авторизация, то указать учетные данные. credentialCache = System.Net.CredentialCache::get_DefaultCredentials(); //5. Получить поток с данными. stream = webRequest.GetRequestStream(); //6. Записать поток данных. stream.Write(byteArray, 0, byteArray.get_Length()); //7. Закрыть поток. stream.Close(); //8. Получить ответ. httpWebResponse = webRequest.GetResponse(); //9. Отобразить статус. statusDescription = httpWebResponse.get_StatusDescription(); info(strFmt("%1", statusDescription)); //10. Получить поток с данными. stream = httpWebResponse.GetResponseStream(); //11. Открыть поток с помощью StreamReader. streamReader = new System.IO.StreamReader(stream); //12. Прочитать содержимое. responseFromServer = streamReader.ReadToEnd(); //13. Вывести содержимое в инфолог. info(strFmt("%1", responseFromServer)); //14. Закрыть все. streamReader.Close(); stream.Close(); httpWebResponse.Close(); } Честно содрал пример у Microsoft отсюда: http://msdn.microsoft.com/en-us/libr...v=vs.110).aspx. |
|
|
За это сообщение автора поблагодарили: smailik (1). |
09.12.2014, 11:21 | #17 |
Участник
|
Возможно в 2009 по другому сделано, но функции winInet от этого не меняются. internetOpen вы, скорее всего вызвали правильно, далее internetConnect. Она должна получать handle, который вернула internetOpen, так как в new она у вас не вызывается, то как он передается в internetConnect? Далее я писал:
Цитата:
servername - адрес сервера (напр www.yandex.ru или ip) без http
X++: return _internetConnect.call(hdl, serverName, port, _login, _pass, mode, 0, 0); |
|
09.12.2014, 13:21 | #18 |
Участник
|
Цитата:
X++: hdr = "http://review.maxoptra.com/rest/2/authentication/createSession?accountID=XXX&user=XXX&password=XXX"; url = ""; strData = ""; if (winInetLocal.ok()) { //hnd = winInetLocal.internetOpen("5.9.157.231:80", 1, "XXX", "XXX", 0); // ответ не 0 hURL = winInetLocal.internetConnect("5.9.157.231:80", "XXX", "XXX"); // 0 hReq = winInetLocal.httpOpenRequest(hURL, url, 'POST'); // 0 res = winInetLocal.httpSendRequest(hReq, hdr, strData); // 0 ret = winInetLocal.internetReadFile(hReq); // 0 } порылся порылся и нашел _handle = this.internetOpen("Axapta",0,"","",0); в new. В этом примере собираюсь передать только заголовок. но пока возвращает только нули |
|
09.12.2014, 14:59 | #19 |
Участник
|
Посмотрите что в методе internetConnect. Туда должен передаваться handle, url сервера, порт, логин, пароль, режим доступа. Я чуть раньше приводил вызов. У вас только 3 параметра при вызове, а в качестве остальных что передается? Порт через двоеточие в адресе не нужен. Если конечно эта строка в методе не парсится.
|
|
09.12.2014, 15:38 | #20 |
Участник
|
X++: int internetConnect(str 60 _server, str 99 _userName, str 99 _password ) { return _internetConnect.call(_handle,_server, 80,_userName,_password,1,0,0); } X++: hURL = winInetLocal.internetConnect("review.maxoptra.com", "XXX", "XXX"); |
|