Asynchronous REST API calls using QNetworkAccessManager.



  • Hello Developers,

    I would like to create an app that should capable to handle multiple rest api call within short time. Minimum 1000 calls per minute. I had experience in making REST Api calls but I need some suggestions and ideas to create an app like above mentioned.

    Thank you.


  • Lifetime Qt Champion

    Hi,

    You have to give more details about your architecture.

    Are you planning to send 17 calls per second to one service ? To multiple services ? What kind of machine are you going to use ? What network infrastructure ?



  • Thank for your reply,

    Multiple API calls not exact 17calls per second. And in some times the call rate may gets diff from too low 0 calls(idle) per minute to 1000 call per minute.

    Api calls to multiple services not a single one.

    Normal desktop machines having minimum 2gib of ram, OS type - Ubuntu, Network speed diff from 4Mbps - 10Mbps. Network interface may be wired or wireless.


  • Lifetime Qt Champion

    QNetworkAccessManager handles up to six calls in parallel, then queues the following and executes them as soon as possible.

    What will you do with the answer of these APIs ?



  • Sorry for the late reply,

    Doing some sort of operations like calculations, loading response data into required models show to user, doing some analytics based on the analytics result requesting for next api call like that.

    Thanks in advance.


  • Lifetime Qt Champion

    You are going to have to benchmark things. One of the things you don't seem to take into account is the network latency as well as time it could take for the service you call to answer.



  • Hello developers, I have tried something with QNetworkAccessManager & QThreads.

    I had some problem with Qthreads my QThread::finished function have not been called even after i got my response.

    Implementation here:

    RESTClientController -> Assign jobs to Threads

    #include "RESTClientController.h"
    #include <QThread>
    
    RESTClientController::RESTClientController(QObject *parent) : QObject(parent)
    {
    }
    
    void RESTClientController::executeRESTRequests(RESTClient *client)
    {
        QThread *thread = new QThread();
        client->moveToThread(thread);
    
        connect(thread, &QThread::finished, this, &RESTClientController::onThreadFinished);
        connect(thread, &QThread::started, client, &RESTClient::startSync);
        connect(thread, &QThread::finished, thread, &QThread::deleteLater);
        thread->start();
    }
    
    void RESTClientController::onThreadFinished()
    {
        qDebug() << "THread done its job !!!!!";
    }
    
    

    Class RESTClient -> Used to make Network request through Common AccessManager

    #include "RESTClient.h"
    #include <QEventLoop>
    
    RESTClient::RESTClient(NetworkRequest *reqRes, QObject *parent) :
        QObject(parent),
        m_request(reqRes)
    {
        m_networkManager = new QNetworkAccessManager();
    
        connect(m_networkManager, &QNetworkAccessManager::finished, m_request, &NetworkRequest::onFinished);
    }
    
    void RESTClient::startSync()
    {
        m_networkManager->get(m_request->constructRequest());
    }
    

    Class NetworkRequest -> Container having QNetworkRequest & QNetworkReply

    #include "NetworkRequest.h"
    #include <QDebug>
    #include <QJsonDocument>
    
    NetworkRequest::NetworkRequest(QObject *parent) : QObject(parent)
    {
        initMembers();
    }
    
    void NetworkRequest::initMembers()
    {
        m_request.setHeader(QNetworkRequest::ContentTypeHeader,
                          "application/x-www-form-urlencoded");
    }
    
    void NetworkRequest::setUrl(const QString hostName)
    {
        m_url = hostName;
        m_request.setUrl(QUrl(m_url));
    }
    
    void NetworkRequest::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
    {
        m_request.setHeader(header, value);
    }
    
    
    void NetworkRequest::onFinished(QNetworkReply *reply)
    {
        int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        QByteArray data = reply->readAll();
        handleReply(status, data);
    }
    
    void NetworkRequest::handleReply(int status, QByteArray data)
    {
        QJsonDocument jsonDocument;
        QJsonParseError parsingResult;
    
        if (status >= 200 && status < 300) {
            // success
            jsonDocument = QJsonDocument::fromJson(data, &parsingResult);
            qDebug() << QString("Status: %1 !!! success").arg(QString::number(status));
        } else if (status >= 300 && status < 400) {
            qDebug() << QString("Status: %1 !!! Redirected").arg(QString::number(status));
        } else if (status >= 400 && status < 500) {
            qDebug() << QString("Status: %1 !!! Client error").arg(QString::number(status));
        } else if (status >= 500 && status < 600) {
            qDebug() << QString("Status: %1 !!! Server error").arg(QString::number(status));
        } else {
            qDebug() << QString("Status: %1 !!! Unknown error").arg(QString::number(status));
        }
    }
    

    Main or Some Backend class -> Trigger requests

    RESTClientController *m_restController;
    NetworkRequest *request = new NetworkRequest();
    RESTClient *restClient = new RESTClient(request);
    m_restController->executeRESTRequests(restClient);
    

    Above is my implementation as of now im jus creating QTHread instances. In future i had an idea to go with QThreadPool. But now I can't able to catch my finished signal from QThread. So that i can able to clear my instances.

    Thanks in advance


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.