Kenneth Posted May 17, 2020 Share Posted May 17, 2020 Всем привет! Возник такой вопрос, могу ли я использовать UNIGUI как RestFul Api? В ServerModule есть возможность принимать запросы ПОСТ, ГЕТ с параметрами и в принципе технически, я так понял, можно принять запрос с параметрами, обратиться к базе и обратно вернуть JSON ответ. Я все это уже сделал и в принципе все неплохо работает, но возник вопрос! В документации настоятельно не рекомендуют создавать подключение к базе данных в ServerModule, так как это один глобальный ресурс нашего приложения и при многопоточной работе могут возникнуть конфликты, особенно при редактировании данных. Есть конечно вариант занести в критическую зону, но не думаю что это решение для 100 и более подключений. Поэтому, если я один обращаюсь к этому вэб-сервису, то проблем нет, а если сразу будет 100 подключений? Как это решается, ведь не просто так были созданы процедуры обработки http запросов в ServerModule? Или это сделано только для чтения и для особых случаев, но не для организации вэб сервиса? Если все таки можно, то подскажите куда двигаться? Надеюсь понятно изложил мысль? Link to comment Share on other sites More sharing options...
x11 Posted May 17, 2020 Share Posted May 17, 2020 Вопрос другой - а зачем? Зачем, если UniGUI для этого не предназначен? Погугли на тему: Delphi rest api http://docwiki.embarcadero.com/RADStudio/Rio/en/Tutorial:_Using_the_REST_Client_Library_to_Access_REST-based_Web_Services Link to comment Share on other sites More sharing options...
Kenneth Posted May 17, 2020 Author Share Posted May 17, 2020 Так в том то и вопрос, предназначена ли она для этого. Говорю же, увидел поддержку веб сервисов. А так думаю неплохо было бы в самом унигуи иметь такой сервис и уже ничего стороннего не подключать. Сейчас нашел delphimvcframework. Разбираюсь. А кто чем пользуется? Я так понимаю при каждом запросе должен создаваться отдельный поток с подключением, чтобы не мешать друг другу, чего в ServerModule можно добитсья создавая динамически отдельное соединение, но насколько это оправдано в рамках экономии памяти, не раздует ли сервер при множестве запросов? Ну еще можно с пулом соединения поиграться. В общем у кого какой опыт, поделитесь, направьте пожалуйста. Link to comment Share on other sites More sharing options...
x11 Posted May 17, 2020 Share Posted May 17, 2020 6 minutes ago, Kenneth said: Я так понимаю при каждом запросе должен создаваться отдельный поток с подключением, чтобы не мешать друг другу, чего в ServerModule можно добитсья создавая динамически отдельное соединение так MainModule для этого предназначен - один MainModule на каждое клиентское подключение Link to comment Share on other sites More sharing options...
Kenneth Posted May 17, 2020 Author Share Posted May 17, 2020 http запрос не доходит до MainModule, если знаете как его до туда донести, подскажите. В СерверМодуле есть две прекрасные функции UniGUIServerModuleHTTPCommand и UniGUIServerModuleHTTPDocument, в которых я и принимаю мои запросы, но как до MainModule их донести? Link to comment Share on other sites More sharing options...
Tokay Posted May 17, 2020 Share Posted May 17, 2020 А в чем проблема? в MainModule описываешь нужную(ые) методы и дергаешь их из сервермодуля Link to comment Share on other sites More sharing options...
x11 Posted May 17, 2020 Share Posted May 17, 2020 Для начала надо понять: какому именно экземпляру MainModule нужно переадресовать запрос. Link to comment Share on other sites More sharing options...
stas Posted May 17, 2020 Share Posted May 17, 2020 Можно , обрабатываете события servermodule , датамодуль с бд создаёте в рантайме Будет медленнее, чем обычный рест Работать будет Link to comment Share on other sites More sharing options...
stas Posted May 17, 2020 Share Posted May 17, 2020 31 minutes ago, Kenneth said: http запрос не доходит до MainModule, если знаете как его до туда донести, подскажите. В СерверМодуле есть две прекрасные функции UniGUIServerModuleHTTPCommand и UniGUIServerModuleHTTPDocument, в которых я и принимаю мои запросы, но как до MainModule их донести? Передаёте id сессии в запросе, тогда дойдет, но к сервису это не имеет никакого отношения Link to comment Share on other sites More sharing options...
Tokay Posted May 17, 2020 Share Posted May 17, 2020 Можно пробовать по ID'шникам сессий, как я тут писал: http://forums.unigui.com/index.php?/topic/14257-uniservermodulegetsession-new-powerfull-feature/ ID'шники приходят в сервермодуль в куках, если что: Cookie := ARequestInfo.Cookies.Cookie['UNI_GUI_SESSION_ID', ''] Link to comment Share on other sites More sharing options...
Kenneth Posted May 17, 2020 Author Share Posted May 17, 2020 Ого сколько мнений! Спасибо за советы! Что то все ушли в сторону МаинМодуля, но по-моему как то это не верно! Задача то по сути следующая: 1. получать http запросы извне; 2. произвести некие действия с базой; 3. вернуть результат. Вот в принципе и все что надо. МаинМодуль это больше про сессии, которые как бы здесь не особо меня интересуют. Основное опасение, не будут ли мешать запросы друг-другу, так как СерверМодуль один и коннект один. Тут по-моему есть два варианта: 1. создавать динамически коннект, делать свои дела и уничтожать 2. или создать один коннект с пулом и динамически создавать запросы и уничтожать. 3. или еще ваш вариант.... Будет ли это работать так как надо при больших нагрузках? Как себя поведет СерверМодуль если одновременно прилетит один и тот же запрос с 10 адресов? Он выполнит их паралельно или же поставит в очередь или же зависнет? Хотелось бы все таки услышать мнение самих разработчиков или все же смотреть в сторону других решений? Link to comment Share on other sites More sharing options...
stas Posted May 17, 2020 Share Posted May 17, 2020 4 hours ago, stas said: Можно , обрабатываете события servermodule , датамодуль с бд создаёте в рантайме Будет медленнее, чем обычный рест Работать будет Вы мой ответ читали ? Link to comment Share on other sites More sharing options...
Kenneth Posted May 17, 2020 Author Share Posted May 17, 2020 @stas да согласен, что нужно создавать в рантайме, но не МаинМодуль, достаточно думаю коннект или запросы Link to comment Share on other sites More sharing options...
stas Posted May 17, 2020 Share Posted May 17, 2020 Я хоть слово сказал, что Вы должны создавать UniMainModule ? Обычный Tdatamodule с базой данных Link to comment Share on other sites More sharing options...
Kenneth Posted May 17, 2020 Author Share Posted May 17, 2020 @stas прошу прощения, я почему то не так прочитал. даже во второй раз. Да все верно вы написали. А если использовать один коннект с пулом и создавать запросы не будет легче? Link to comment Share on other sites More sharing options...
stas Posted May 17, 2020 Share Posted May 17, 2020 Я думал об этом, но не пришел к определенному выводу, в результате Вы должны создать аналог UniMainModule но без формы. Оно вам надо? З.Ы. Пробуйте так, в случае неудачи Вы легко перенесете код на чистый рест (но на indy) Link to comment Share on other sites More sharing options...
Kenneth Posted May 17, 2020 Author Share Posted May 17, 2020 Да буду делать тесты, прежде думал спросить, может кто то сталкивался, чтобы не изобретать велосипед. Link to comment Share on other sites More sharing options...
x11 Posted May 18, 2020 Share Posted May 18, 2020 16 hours ago, Kenneth said: Сейчас нашел delphimvcframework. Разбираюсь. https://github.com/danieleteti/delphimvcframework/tree/master/samples Link to comment Share on other sites More sharing options...
x11 Posted May 18, 2020 Share Posted May 18, 2020 Если ты всё же решишь использовать UniGUI, как rest api service, то обрати внимание на свойство soWipeShadowSessions, которое живет в ServerModule.Options. http://www.unigui.com/doc/online_help/api/uniGUIServer_TUniServerOption.html Link to comment Share on other sites More sharing options...
Kenneth Posted May 19, 2020 Author Share Posted May 19, 2020 Небольшой отчет о проделанной работе, к чему привели тесты. Не буду описывать что и как я перепробовал, имею ввиду все варианты, а начну сразу с рабочего варианта, то что действительно дало результаты. Создаю в FDManager соединение с пулом, соединения с базой и сами запросы создаю в рантайме, и после уничтажаю их. Что использовал: Firebird 3.0 + FireDac. На серверМодуль кидаю FDManager, в onCreate настраиваю подключение с пулом и делаю актив=тру. Все как доках. И все! Дальше принимаю запрос и делаю следующее: if ARequestInfo.URI = '/test/ins' then //запрос на вставку записи begin Con:=TFDConnection.Create(self); con.ConnectionDefName:='FB_Con_srv'; con.Connected:=true; with TFDCommand.Create(self) do begin Connection:=con; CommandText.Add('insert into tbtest(name) values('''+ARequestInfo.Params.Values['n']+''');'); try Execute; AResponseInfo.ContentText:='ok'; AResponseInfo.ResponseNo:=200; finally free; con.Free; end; end; Handled:=true; end else if ARequestInfo.URI = '/test/get' then //запрос на селект begin Con:=TFDConnection.Create(self); con.ConnectionDefName:='FB_Con_srv'; con.Connected:=true; with TFDQuery.Create(self) do begin Connection:=con; SQL.Add('select count(*) as cnt from tbtest;'); try Active:=true; AResponseInfo.ContentText:='{"cnt":'+FieldByName('CNT').AsString+'}'; Close; finally Free; con.Free; end; end; Тестил через Stress TestTool. В тесте сначала вставляю запись в табилцу, потом следующей сессией выбираю кол-во записей. 250 Сессий отрабатывает на ура, но почему если делать больше, то вылетает с ошибкой. ServerLimits.MaxSession:=1000; Что еще нужно подкрутить? Link to comment Share on other sites More sharing options...
stas Posted May 19, 2020 Share Posted May 19, 2020 1) Handled в else if ARequestInfo.URI = '/test/get' then 2) Что именно Вы тестировали ? Насколько я вижу Вы тестировали создание пустой формы и приложение благополучно умерло. Stresstool тут неприменимо, от слова совсем. Вам необходимо использовать стандартные тесты рест методов. И на вход подавать полный урл Link to comment Share on other sites More sharing options...
Kenneth Posted May 19, 2020 Author Share Posted May 19, 2020 @stas 2 hours ago, stas said: 1) Handled в код не до конца скопировал, две последние строчки оставил: AResponseInfo.ResponseNo:=200; Handled:=true; end; Там все нормально. Теперь на счет тестирования. Согласен напрямую не протестируешь. Поэтому я запустил свой тестовый проект, создал другое приложение, в котором на форме бросил две кнопочки, одна отправляет запрос на мой сервис для вставки записи, другая на селект. Через StressTool запускаю запись сценария, запускается второе приложение, которое обращается к моему целевому, нажимаю последовательно эти две кнопочки, завершаю запись и после прогоняю этот сценарий. При удачном тесте все записи 250 запсей вставляются, что говорит о работе теста. Так что не думаю что СтрессТул неприменим. Вопрос остается, почему не получается увеличить кол-во сессий больше 250? Link to comment Share on other sites More sharing options...
stas Posted May 19, 2020 Share Posted May 19, 2020 Вы что хотите протестировать, клиент или сервер ? Если сервер, то неприменим, если клиент, то вопрос совершенно другой ветки. Link to comment Share on other sites More sharing options...
Kenneth Posted May 19, 2020 Author Share Posted May 19, 2020 Сервер конечно! А чего не понятного, я же все подробно описал, что я через клиента гружу сервер, в этом и заключается тест. Основная нагрузка на сервер идет, т.к. он за минуту обрабатывает 250 сессий в которых работает с базой! Я писал что напрямую через СтрессТул не получиться тестить, поэтому я создал клиента, которого грузит СтрессТул, а тот в свою очередь сервер. Надеюсь понятна мысль? StressTool -> Client -> Web Server. Link to comment Share on other sites More sharing options...
Kenneth Posted May 19, 2020 Author Share Posted May 19, 2020 Все вопрос снят. Пока писал ответ, меня осенило Параметр ServerLimits.MaxSession:=1000, был выставлен на целевом сервере, который я тестил, а в промежуточном клиенте стояло 250! Вот он то выводил исключение. Всем спасибо за советы! Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now