[Interest] QtHttpServer Asynchronous Request Processing

Ievgenii Meshcheriakov ievgenii.meshcheriakov at qt.io
Tue Jan 10 16:08:58 CET 2023


Hi,

I've tried to reproduce this on Windows and Linux and I cannot. In both cases
the requests are executed in parallel. One thing that comes to mind is that a 
shared thread pool is used to execute request, so if it has only one thread 
then requests will be run sequentially. But this will not explain why the 
program with two handlers runs reuqests in parallel.

Regards,
Ievgenii

середа, 4 січня 2023 р. 17:31:28 CET  написано:
> Hi all,
> 
> I played around with the new QHttpServer module in Qt6.4.1 and Qt6.5 and
> ran into some questions regarding how to implement an asynchronous request
> processing. I would like to implement a webservice that can handle several
> requests in parallel, since each request may take significant processing
> time to generate the corresponding response.
> 
> Some examples in the following using QHttpServer:
> 
>     QHttpServer server;
>     server.route("/", []() {
>     return QtConcurrent::run([]() {
>                 std::cout <<
> QTime::currentTime().toString().toLatin1().constData() << " start" <<
> std::endl;
>                 QThread::currentThread()->msleep(5000); //simulate some
> processing time
>                 std::cout <<
> QTime::currentTime().toString().toLatin1().constData() << " stop" <<
> std::endl;
>                 return QHttpServerResponse(QString("1"));
>                 });
>         });
>     server.listen(QHostAddress::Any, 80)
> 
> When I run this example on a Windows machine and generate requests from two
> different browser windows to "http://127.0.0.1", the registered view
> handler lambda is processed in sequence and not (as expected) in parallel
> (i.e. I get start/stop/start/stop). This is the same behavior with Qt6.4.1
> as with Qt6.5.
> 
> However, I could observe a different behavior, if I register a second rule:
> 
>     QHttpServer server;
>     server.route("/", []() {
>         return QtConcurrent::run([]() {
>                 std::cout <<
> QTime::currentTime().toString().toLatin1().constData() << " start" <<
> std::endl;
>                 QThread::currentThread()->msleep(5000); //simulate some
> processing time
>                 std::cout <<
> QTime::currentTime().toString().toLatin1().constData() << " stop" <<
> std::endl;
>                 return QHttpServerResponse(QString("1"));
>                 });
>         });
>     server.route("/", [](QString id) {
>             return QtConcurrent::run([id]() {
>                 std::cout <<
> QTime::currentTime().toString().toLatin1().constData() << " start" <<
> std::endl;
>                 QThread::currentThread()->msleep(5000); //simulate some
> processing time
>                 std::cout <<
> QTime::currentTime().toString().toLatin1().constData() << " stop" <<
> std::endl;
>                 return QHttpServerResponse(QString("2: %1").arg(id));
>                 });
>             });
>     server.listen(QHostAddress::Any, 80)
> 
> Surprisingly, if I now enter in the first browser window "http://127.0.0.1"
> while in the second browser window "http://127.0.0.1/test", both view
> handlers are processed in parallel, i.e. I get start/start/stop/stop. So,
> different view handlers can be run in parallel, if their (different) rules
> are fired at the same time. Thus, in general an asynchronous request
> processing is obviously possible, but unfortunately with the current API
> and implementation only for different targets / rules.
> 
> Since I need to handle arbitrarily formed URL requests (that does not fit
> into the current route-API of QHttpServer), I tried similar experiments
> using QAbstractHttpServer and overriding the handleRequest() function. Here
> again, I could not find a way for an asynchronous request processing, i.e.
> early return of handleRequest() function after triggering asynchronous
> background jobs for each request, and then later sending the calculated
> response. Every handleRequest() is called only after the response to the
> last request was sent.
> 
> Furthermore, the handleRequest() interface looks like it expects to send
> the response within this function (blocking call). The interface even
> changed from Qt6.4.1 to Qt6.5, and in Qt6.5 with the non-copyable
> QHttpServerResponder parameter it is even harder to keep this struct for a
> later response (only by std::moving).
> 
> So, my question is, if QHttpServer is intended to support asynchronous
> request processing (for arbitrary URL requests) sometime in the future? Or
> am I missing the correct way to do this with the current API?
> 
> Thanks in advance
> Daniel
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL:
> <http://lists.qt-project.org/pipermail/interest/attachments/20230104/3b7c05
> 8d/attachment.htm>


More information about the Interest mailing list