2011-12-15 43 views
5

Máy chủ sẽ chạy mãi và xử lý các yêu cầu cần một phần mã không đồng bộ trong đó sẽ thực hiện một số truy vấn cơ sở dữ liệu và chỉ cập nhật khi có bất kỳ thay đổi mới nào. Máy chủ phải chạy vĩnh viễn và chức năng này để thực hiện một hàm db một lần nữa và một lần nữa phải chạy không đồng bộ, do đó không có cản trở máy chủ vì cập nhật một lần trong mỗi 'x' phút.Xử lý không đồng bộ trong C++

Cách tốt nhất có thể xử lý không đồng bộ trong C++? Làm thế nào tôi có thể thiết lập chức năng đó một mình để chạy trên một daemon để nó không chặn máy chủ ở tất cả?

+0

Làm thế nào về một chương trình đa luồng? –

+6

Bạn đã xem Boost ASIO chưa? Có IO đồng bộ và không đồng bộ, bộ hẹn giờ và hơn thế nữa. http://www.boost.org/doc/libs/release/libs/asio/ – Joel

+0

Để sử dụng cách tiếp cận theo luồng. Tôi có thể thiết lập thread đó thành daemon như cách nó được thực hiện trong python không? Bởi vì phần còn lại của chương trình thực sự không cần các chủ đề như của nó trên CORBA. @Jelel đến ASIO, hãy khai sáng cho tôi. Nó trông giống như một lựa chọn tốt (tôi có rất ít kiến ​​thức về asio) nhưng có vẻ như một cuộc gọi chặn đến io_service.run(). Tôi muốn chạy không đồng bộ chức năng cho các truy vấn dbqueries định kỳ bất kể máy chủ làm gì. Họ là khá nhiều tách ra, ngoại trừ họ sẽ chia sẻ một biến. Trong khi máy chủ tiếp tục chạy, hàm kia phải chạy không đồng bộ. – King

Trả lời

5

tôi muốn khuyên bạn sử dụng Boost's ASIO thư viện

Bạn sẽ cần một lớp học để chấp nhận các yêu cầu mới và một để kiểm tra định kỳ để cập nhật. Cả hai có thể làm công việc của họ một cách không đồng bộ và sử dụng cùng một boost :: asio :: io_service để lên lịch công việc.

Quá trình cài đặt sẽ

  • Một không đồng bộ mạng boost::asio::ip::tcp::acceptor nghe cho các yêu cầu mới.
  • A boost::asio::deadline_time làm một sự chờ đợi không đồng bộ để kiểm tra các bản cập nhật cho cơ sở dữ liệu.

Pseudo mã cho những gì tôi hiểu bạn đang mô tả là dưới đây:

#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; 
} 

Biên dịch ở trên và chạy nó sẽ cho thấy rằng cơ sở dữ liệu Update Checker sẽ kiểm tra cập nhật mỗi 5 giây khi nghe cho các kết nối trên Cổng TCP 4444. Để xem mã chấp nhận kết nối mới, bạn có thể sử dụng công cụ mạng khách/mạng yêu thích của 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. 

Nếu bạn thấy rằng việc xử lý cập nhật và/hoặc yêu cầu mất một khoảng thời gian đáng kể thì tôi sẽ xem từng công việc trong chuỗi của riêng nó. io_service sẽ lên kế hoạch công việc cần làm và không hoàn thành cho đến khi không còn hoạt động nữa. Bí quyết là để các lớp học làm công việc lên lịch lại khi chúng được thực hiện.

Tất nhiên bạn phải tính đến nhận xét của người khác về câu hỏi của bạn. Tôi không biết làm thế nào một giao diện CORBA có thể phức tạp này nhưng tôi sẽ nghĩ rằng tăng :: asio như một thư viện C++ không đồng bộ sẽ là một quyết định tốt và đủ linh hoạt cho những gì bạn mô tả.

+0

Tôi đã kết thúc bằng cách sử dụng boost asio.Theo dõi bộ đếm thời gian như bạn đã sử dụng. mất một thời gian để đánh giá cao nó. Mọi thứ đã đi sau CORBA. Vì vậy, nó không quan trọng. phần không đồng bộ của chương trình hoạt động theo cách của nó sang một bên trong khi máy chủ xử lý các yêu cầu. Cảm ơn ! Bạn là một trong những người đã thuyết phục tôi ngày hôm qua! Làm việc một say mê! boost :: asio có khả năng xử lý tấn yêu cầu mạnh mẽ mà tôi rất hoài nghi. – King

1

Có vẻ như điều đó có nghĩa là trong khi hệ thống xử lý các yêu cầu mạng liên tục, nó liên lạc không đồng bộ với DB.

Điều đó có nghĩa là khi cần nói chuyện với DB, nó sẽ gửi một truy vấn nhưng không chờ phản hồi.

Khi nhận được phản hồi từ DB, quy trình xử lý nó.

Phần không đồng bộ có thể được triển khai bằng cách có một chuỗi riêng biệt trao đổi với DB và khi nó được phản hồi, nó sẽ đăng ngay cả trong hàng đợi máy chủ để xử lý.

Hoặc máy chủ có thể đang nghe trên nhiều ổ cắm dữ liệu và một trong số đó có thể là kết nối cơ sở dữ liệu trong đó máy chủ nhận phản hồi từ DB.

+0

Máy chủ không gửi truy vấn. Thay vào đó tôi nhớ cache bảng vì nó là dữ liệu rất hạn chế. Các chức năng mà tôi muốn làm cho nó không đồng bộ không bộ đệm ẩn. Vì vậy, trong khi bộ nhớ đệm xảy ra không đồng bộ, máy chủ vẫn tiếp tục. – King

1

Vì vậy, về cơ bản (nếu tôi hiểu bạn chính xác), bạn cần thăm dò ý kiến ​​cơ sở dữ liệu định kỳ để xem liệu nó có thay đổi không. Và khi nó đã thay đổi, bạn cần thông báo cho một bộ xử lý yêu cầu dựa trên Corba rằng đã có thay đổi.

Điều tôi sẽ làm là thêm loại yêu cầu mới vào máy chủ CORBA của bạn. Yêu cầu sẽ là "Cơ sở dữ liệu đã được cập nhật". Sau đó, bạn có thể viết một chương trình nhỏ, hoàn toàn khác, chỉ có công việc là thăm dò cơ sở dữ liệu và gửi yêu cầu CORBA khi cơ sở dữ liệu đã được cập nhật.

Bằng cách đó, bạn có thể gấp thông điệp cập nhật cơ sở dữ liệu vào luồng yêu cầu chính cho máy chủ CORBA.

Không có chủ đề nào, không có gì bất đồng bộ. Chỉ cần hai quá trình mỗi làm việc của riêng mình.

+0

Việc bỏ phiếu cho một cơ sở dữ liệu thường xuyên và chuyển giữa các cơ sở dữ liệu khác sẽ bị chặn và một chút lãng phí thời gian. Mỗi giây thứ hai là quý giá trong thời gian thực. Mặc dù tôi đã thực hiện điều này một cách không đồng bộ. Để cập nhật, tôi sẽ thăm dò ý kiến ​​của db để xem liệu có thực sự thay đổi nào không. – King

+0

@ Dumb: Vậy tôi không hiểu bạn đang hỏi gì. Làm thế nào để bạn tìm ra nếu bảng cơ sở dữ liệu đã thay đổi mà không bỏ phiếu thường xuyên? – Omnifarious

+0

ofcourse đúng là chúng ta phải thăm dò ý kiến ​​của db! Bạn đang ở trên. Nhưng tôi muốn biết nếu tôi có thể đặt tất cả mọi thứ đằng sau một wrapper không đồng bộ. Chạy nó trên một tiến trình riêng biệt mà một lần nữa sẽ tương tác với nhau qua CORBA cho tôi chút chậm trễ trong thời gian đó. – King

Các vấn đề liên quan