Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ boost ASIO和线程之间的消息传递_C++_Multithreading_Sockets_Boost - Fatal编程技术网

C++ boost ASIO和线程之间的消息传递

C++ boost ASIO和线程之间的消息传递,c++,multithreading,sockets,boost,C++,Multithreading,Sockets,Boost,我正在设计一个websocket服务器,它接收消息并将其保存到嵌入式数据库中。用于阅读我正在使用的消息。要将消息保存到嵌入式数据库,我会看到前面有几个选项: 当我通过同一线程收到消息时,立即同步保存消息 在单独的线程上异步保存消息 我很确定第二个答案就是我想要的。但是,我不知道如何将消息从套接字线程传递到IO线程。我看到以下选项: 每个线程使用一个io服务,并使用在线程之间进行通信。在这里,我不得不担心锁争用。我应该吗 使用Linux域套接字在线程之间传递消息。据我所知,没有锁争用。在这里,我可

我正在设计一个websocket服务器,它接收消息并将其保存到嵌入式数据库中。用于阅读我正在使用的消息。要将消息保存到嵌入式数据库,我会看到前面有几个选项:

  • 当我通过同一线程收到消息时,立即同步保存消息
  • 在单独的线程上异步保存消息
  • 我很确定第二个答案就是我想要的。但是,我不知道如何将消息从套接字线程传递到IO线程。我看到以下选项:

  • 每个线程使用一个io服务,并使用在线程之间进行通信。在这里,我不得不担心锁争用。我应该吗
  • 使用Linux域套接字在线程之间传递消息。据我所知,没有锁争用。在这里,我可以使用BOOST\u ASIO\u DISABLE\u THREADS宏来提高性能
  • 此外,我相信有多个IO线程将有助于以循环方式接收消息以保存到嵌入式数据库

    哪种体系结构最具性能?我提到的体系结构还有其他替代方案吗

    需要注意的几点:

    • 消息的长度正好为8个字节
    • 无法使用外部数据库。数据库必须嵌入到正在运行的数据库中 过程
    • 我正在考虑将其用作嵌入式系统 数据库

    您可能只需要一个
    io\u服务
    ——您可以创建额外的线程,通过提供
    boost::asio::io\u service::run
    作为线程函数来处理
    io\u服务
    中发生的事件。对于通过网络套接字从客户端接收8字节的消息来说,这应该具有很好的扩展性

    对于在数据库中存储消息,它取决于数据库和接口。如果它是多线程的,那么您也可以从接收消息的线程向DB发送每条消息。否则,我可能会设置一个
    boost::lockfree::queue
    ,其中一个读卡器线程提取项目并将其发送到数据库,
    io_服务
    线程在它们到达时将新消息附加到队列中

    这是最有效的方法吗?我不知道。这绝对是简单的,并给你一个基线,你可以概况,如果它不够快,你的情况。但我建议不要一开始就设计更复杂的东西:你根本不知道你是否需要它,除非你对你的系统了解很多,否则实际上不可能说复杂的方法是否比简单的方法表现得更好。

    void Consumer(无锁::队列&消息队列){
    
    void Consumer( lockfree::queue<uint64_t> &message_queue ) {
        // Connect to database...
        while (!Finished) {
            message_queue.consume_all( add_to_database ); // add_to_database is a Functor that takes a message
            cond_var.wait_for( ... ); // Use a timed wait to avoid missing a signal.  It's OK to consume_all() even if there's nothing in the queue.
        }
    }
    
    void Producer( lockfree::queue<uint64_t> &message_queue ) {
        while (!Finished) {
            uint64_t m = receive_from_network( );
            message_queue.push( m );
            cond_var.notify_all( );
        }
    }
    
    //连接到数据库。。。 当(!完成){ message_queue.consume_all(add_to_database);//add_to_database是接受消息的函子 cond_var.wait_for(…);//使用定时等待以避免丢失信号。即使队列中没有任何内容,也可以使用_all()。 } } 无效生产者(无锁::队列和消息队列){ 当(!完成){ uint64_t m=从_网络()接收_; 消息队列推送(m); cond_var.notify_all(); } }
    我认为您不想使用unix套接字,它总是需要系统调用并通过内核传递数据。这通常更适合作为进程间机制而不是线程间机制

    除非您的数据库API要求所有调用都来自同一个线程(我对此表示怀疑),否则您不必为它使用单独的
    boost::asio::io_服务。我将在现有的
    io_服务
    实例上创建一个实例,并使用member函数(而不是
    io_服务::post()
    )来执行任何阻塞数据库任务。以这种方式使用
    可以保证最多有一个线程可能被阻止访问数据库,从而使
    io_服务
    实例中的所有其他线程都可用于服务非数据库任务

    为什么这比使用单独的
    io\u服务
    实例要好?一个优点是,拥有一个带有一组线程的单个实例稍微更易于编码和维护。另一个次要的优点是,如果可以,使用
    strand::dispatch()
    将在当前线程中执行(即如果
    strand
    中没有任务正在运行),这可能会避免上下文切换


    对于最终的优化,我同意使用一个特殊的队列,其排队操作不能进行系统调用,这可能是最快的。但是,考虑到生产者有网络i/o,消费者有磁盘i/o,我看不出队列的实现将如何成为您的瓶颈。

    假设在您的情况下使用cxx11的限制不是太难,我会尝试使用来对嵌入式DB进行异步调用

    在基准测试/评测之后,我发现facebook folly的实现速度最快,至少有50%的优势。如果我使用,那么套接字线程几乎没有开销,IO线程仍然很忙。系统调用的数量也比其他队列实现少得多

    boost中包含cond变量的SPSC队列速度较慢。我不知道这是为什么。这可能与愚蠢队列使用的自适应旋转有关


    此外,消息传递(本例中为UDP域套接字)的速度慢了几个数量级,尤其是对于较大的消息。这可能与复制数据两次有关。

    我会使用BooSt.ASIO与设备等通信,但是如果你需要线程间通信,我不会认为这是正确的选择。也许您可以使用boost.lockfree中提供的无锁缓冲区?spsc_队列为我做了很多次。我也认为这是最快的方式,在performan