2011-12-15 2 views
5

Сервер, который будет работать вечно и обрабатывает запросы, нуждается в асинхронной части кода, которая будет выполнять некоторые запросы к базе данных и обновляться только тогда, когда в нее будут внесены новые изменения. Сервер должен запускаться вечно, и эта функция для выполнения функции db снова и снова должна выполняться асинхронно, так что сервер не будет препятствовать из-за обновления один раз в каждые «x» минуты.Асинхронная обработка в C++

Как лучше всего это можно обрабатывать асинхронно в C++? Как я могу настроить эту функцию самостоятельно для запуска на демонах, чтобы она вообще не блокировала сервер?

+0

Как насчет многопоточной программы? –

+6

Вы проверили Boost ASIO? Существуют синхронные и асинхронные IO, таймеры и т. Д. http://www.boost.org/doc/libs/release/libs/asio/ – Joel

+0

Использовать многопоточный подход. Могу ли я установить этот поток для демона, как это делается в python? Потому что остальная часть программы действительно не нуждается в потоках, как ее над CORBA. @Joel, приходящий в ASIO, пожалуйста, просветите меня. Это хороший вариант (у меня очень мало знаний об asio), но, похоже, блокирующий вызов io_service.run(). Я хочу асинхронно запускать функцию для dbqueries периодически независимо от того, что делает сервер. Они в значительной степени отделены, за исключением того, что они собираются использовать переменную. Пока сервер продолжает работать, другая функция должна выполняться асинхронно. – King

ответ

5

я настоятельно рекомендую использовать Boost's ASIO библиотеку

Вы должны были бы класс, чтобы принимать новые запросы, а другой периодически проверять наличие обновлений. Оба могут выполнять свою работу асинхронно и использовать один и тот же boost :: asio :: io_service для планирования работы.

Установка будет

  • сеть асинхронного boost::asio::ip::tcp::acceptor прослушивания для новых запросов.
  • A boost::asio::deadline_time выполнить асинхронное ожидание проверить наличие обновлений для базы данных.

Псевдо-код для того, что я понимаю, что вы описываете ниже:

#include <iostream> 
#include <boost/asio.hpp> 
#include <boost/bind.hpp> 
#include <boost/shared_ptr.hpp> 
#include <string> 

class DatabaseUpdateChecker{ 
    public: 
    DatabaseUpdateChecker(boost::asio::io_service& io, const int& sleepTimeSeconds) 
    :timer_(io,boost::posix_time::seconds(sleepTimeSeconds)),sleepSeconds_(sleepTimeSeconds){ 
     this->timer_.async_wait(boost::bind(&DatabaseUpdateChecker::doDBUpdateCheck,this,boost::asio::placeholders::error)); 
    }; 

    protected: 
    void doDBUpdateCheck(const boost::system::error_code& error){ 
     if(!error){ 
      std::cout << " Checking Database for updates" << std::endl; 
      //Reschdule ourself 
      this->timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(this->sleepSeconds_)); 
      this->timer_.async_wait(boost::bind(&DatabaseUpdateChecker::doDBUpdateCheck,this,boost::asio::placeholders::error)); 
     } 
    }; 
    private: 
    boost::asio::deadline_timer timer_; 
    int sleepSeconds_; 
}; 

typedef boost::shared_ptr<boost::asio::ip::tcp::socket> TcpSocketPtr; 

class NetworkRequest{ 
    public: 
    NetworkRequest(boost::asio::io_service& io, const int& port) 
    :acceptor_(io,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),port)){ 
     this->start_accept(); 
    }; 
    protected: 
    void start_accept(){ 
     TcpSocketPtr socketPtr(new boost::asio::ip::tcp::socket(acceptor_.get_io_service())); 
     std::cout << "About to accept new connection" << std::endl; 
     acceptor_.async_accept(*socketPtr,boost::bind(&NetworkRequest::handle_accept,this,socketPtr,boost::asio::placeholders::error)); 
    }; 
    void handle_accept(TcpSocketPtr socketPtr,const boost::system::error_code& error){ 
     std::cout << "Accepted new network connection" << std::endl; 
     if(!error){ 
      std::string response("This is a response\n"); 
      boost::asio::async_write(*socketPtr,boost::asio::buffer(response), 
       boost::bind(&NetworkRequest::handle_write,this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred)); 
     } 
     //Start listeing for a new connection 
     this->start_accept(); 
    } 
    void handle_write(const boost::system::error_code& error,size_t size){ 
     if(!error){ 
      std::cout << "Wrote out " << size << " bytes to the network connection" << std::endl; 
     } 

    } 
    private: 
    boost::asio::ip::tcp::acceptor acceptor_; 
}; 

int main(int argc, char *argv[]) { 
    static const int DB_TIMER_SECONDS=5; 
    static const int LISTENING_TCP_PORT=4444; 

    std::cout << "About to start" << std::endl; 
    boost::asio::io_service io; 

    DatabaseUpdateChecker dbChecker(io,DB_TIMER_SECONDS); 
    NetworkRequest networkRequestAcceptor(io,LISTENING_TCP_PORT); 

    io.run(); 

    std::cout << "This won't be printed" << std::endl; 
    return 0; 
} 

Компиляция выше, и работает он покажет, что база данных Update Checker будет проверять наличие обновлений каждые 5 секунд во время прослушивания для соединений на TCP-порт 4444. Чтобы увидеть, как код принимает новое соединение, вы можете использовать telnet/netcat/ваш любимый инструмент сетевого клиента ....

telnet 127.0.0.1 4444 
Trying 127.0.0.1... 
Connected to localhost. 
Escape character is '^]'. 
This is a response 
Connection closed by foreign host. 

Если вы обнаружили, что обработка обновлений и/или запросов занимает значительное количество времени, то я хотел бы посмотреть в резьбе приложения и запуская каждую задачу в своем собственном потоке. io_service запланирует, какую работу он должен выполнить, а не завершить, пока не будет больше работы. Хитрость заключается в том, чтобы занятия, выполняющие работу, перенесли на себя, когда они будут выполнены.

Конечно, вы должны учитывать комментарии других участников по вашему вопросу. Я не знаю, как интерфейс CORBA может усложнить это, но я бы подумал, что boost :: asio как асинхронная библиотека C++ будет хорошим решением и достаточно гибким для того, что вы описываете.

+0

Я закончил тем, что использовал boost asio.Infact крайний таймер, как вы использовали. потребовалось некоторое время, чтобы оценить это. Все пошло позади CORBA. Так что это не имеет значения. асинхронная часть программы работает в сторону, пока серверные запросы обрабатываются. Благодаря ! Ты один из тех, кто вчера меня убедил! Работает очарование! boost :: asio обладает мощной способностью обрабатывать тонны запросов, с которыми я был очень скептичен. – King

1

Похоже, что это означает, что, хотя система непрерывно обрабатывает сетевые запросы, она асинхронно связывается с БД.

Это означает, что когда ему нужно поговорить с БД, он отправляет запрос, но не ждет ответа.

Когда он получает ответ от БД, он обрабатывает его.

Асинхронная часть может быть реализована посредством отдельного потока, который ведет переговоры с БД, и когда он получает ответ, он помещает даже в очередь сервера для обработки.

Или сервер может прослушивать множество сокетов для данных, а один из них может быть подключением к базе данных, где он получает ответы от БД.

+0

Сервер не отправляет запросы. Скорее я кэширую таблицу, так как это очень ограниченные данные. Функция, которую я хочу сделать асинхронной, делает кеширование. Итак, пока кеширование происходит асинхронно, сервер продолжается. – King

1

Таким образом, в основном (если я вас правильно понимаю) вам необходимо периодически опробовать базу данных, чтобы узнать, не изменилось ли оно. И когда он изменился, вам нужно уведомить обработчик запросов на основе CORBA, что произошли изменения.

Что бы я сделал, это добавить новый тип запроса на ваш сервер CORBA. Запрос будет «Обновление базы данных». Затем вы можете написать небольшую, совершенно другую программу, единственной задачей которой является опрос базы данных и отправка запроса CORBA при обновлении базы данных.

Таким образом, вы можете сбросить сообщение обновления базы данных в основной поток запросов для сервера CORBA.

Нет нитей, никаких асинхронных ничего. Всего два процесса, каждый из которых делает свое дело.

+0

Частое опроса базы данных и переход между ними будут блокировать и немного тратить время. Каждые миллисекунды драгоценны в реальном времени. Хотя я реализовал это асинхронно. Чтобы обновить, я собираюсь опросить db, чтобы увидеть, действительно ли есть какие-либо изменения. – King

+0

@ Dumb: Тогда я не понимаю, о чем вы спрашивали. Как вы выясните, изменилась ли таблица базы данных, не часто ли опросив ее? – Omnifarious

+0

Конечно, мы должны опросить db !. Вы на месте. Но я хотел знать, могу ли я поставить все за асинхронную оболочку. Запустив его на отдельный процесс, который снова будет взаимодействовать друг с другом по сравнению с CORBA, мне будет немного отставать во времени. – King

Смежные вопросы