多个boost :: asio ssl客户端在同一系统上运行

时间:2015-02-18 06:54:41

标签: c++ ssl boost multiprocessing boost-asio

我有一个简单的Boost ASIO SSL客户端,可以调用web api。客户端稍微修改了Boost SSL文档示例。

//http.h
class Http {
public:
    static void WebApiCall(...);
}

//http.cpp
void Http::WebApiCall(...) {
    try {
        // .......
        boost::asio::io_service io_service;
        tcp::resolver resolver(io_service);
        tcp::resolver::query query(serverip, serverport);
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        boost::asio::ssl::context ctx(io_service, boost::asio::ssl::context::tlsv1); // ERROR # 1
        // ....
        // Setting SSL Context Properties Here
        // ....
        boost::shared_ptr<boost::asio::ssl::stream<tcp::socket> >  ssocket(new boost::asio::ssl::stream<tcp::socket>(io_service, ctx));
        boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
        ssocket->lowest_layer().connect(endpoint);
        boost::system::error_code er;
        ssocket->handshake(boost::asio::ssl::stream_base::client,er);

        boost::asio::streambuf request;
        std::ostream request_stream(&request);
        // ....
        // Set Headers & Body of HTTP Request here
        // ....
        size_t written = 0;
        written = boost::asio::write(*ssocket, request); // ERROR # 2

        // .....
        // Read server response
        boost::asio::streambuf response;
        boost::system::error_code error;
        int read_bytes = 0;
        std::string TempBuf = "";
        std::ostringstream responseStringstream; 
        std::stringstream  response_stream;
        while ( boost::asio::read(*ssocket,response,boost::asio::transfer_at_least(1), error)) {
                read_bytes  = read_bytes + response.size();
                responseStringstream << &response;
            }
        }

        // Do some stuff with server response....
        // ....
    } catch ( const boost::system::system_error &error ) {
        // Print the exception ..
    }
}
// client.cpp
Http::WebApiCall(<api_to_call>)

您可以看到一个简单的HTTP客户端,其中包含一个静态函数,该函数使用ASIO实现实际启用SSL的HTTP客户端。

使用案例:

在一台计算机上运行此客户端的1000个进程。所有进程都在大约相同的时间内定期(例如每隔一分钟)向一个资源发出POST请求。机器是Ubuntu,我似乎没有内存不足(我有大约6 GB免费)

这个客户端工作得很完美,但在一种情况下,我必须在我的服务器上模拟一些负载,我已经在一台机器上启动了这个客户端的1000个进程,所有这些都使用相同的公共证书向相同的服务器调用相同的API,除了每个客户端有自己的OAuth令牌¹。在这种情况下,我有两种类型的例外:

错误:

  • 错误#2:写入时出现一些客户端(NOT ALL)错误(写入:短读取)。从不同的论坛和Boost来源看来,服务器似乎正在发送SSL_Shutdown,导致ASIO抛出此错误,根据我的发现,这是正常行为。我的问题是,为什么服务器此时发送SSL_Shutdown?这是否必须对从同一台机器调用相同资源的多个进程执行任何操作?从ASIO docs ASIO SSL不是线程安全的,但在这种情况下,我只运行一个线程但不同的进程(我相信这是完全安全的),除了上面的代码本身是线程安全的。潜在的openssl表现不正常吗?

  • 错误#1:有时在创建Boost ASIO SSL Context时会出现异常,只需说“context:ssl error”。同样的想法,为什么它表现得像这样?这是否与多个流程有关,在这种情况下是否开放混合?

我的客户端在过去的一年里运行完美,每台机器只需一个进程,之前我从未见过这些错误。任何想法都表示赞赏。


¹(刚才提到OAuth,但我认为这与它没有任何关系)

1 个答案:

答案 0 :(得分:1)

  •   

    问:写入时出现一些客户端(NOT ALL)错误(写入:短读取)。从不同的论坛和Boost来源看来,服务器似乎正在发送SSL_Shutdown,导致ASIO抛出此错误,根据我的发现,这是正常行为。

    最有可能的原因是您正在推动系统超出资源限制。例如。客户端或服务器可能用完文件句柄。例如。在我的Linux机器上,默认情况下,打开文件的数量限制为1024ulimit -a输出:

    core file size          (blocks, -c) 0
    data seg size           (kbytes, -d) unlimited
    scheduling priority             (-e) 0
    file size               (blocks, -f) unlimited
    pending signals                 (-i) 256878
    max locked memory       (kbytes, -l) unlimited
    max memory size         (kbytes, -m) unlimited
    open files                      (-n) 1024
    pipe size            (512 bytes, -p) 8
    POSIX message queues     (bytes, -q) 819200
    real-time priority              (-r) 95
    stack size              (kbytes, -s) 8192
    cpu time               (seconds, -t) unlimited
    max user processes              (-u) 256878
    virtual memory          (kbytes, -v) unlimited
    file locks                      (-x) unlimited
    
  •   

    问:我的问题是,为什么服务器此时正在发送SSL_Shutdown?

    最有可能是因为上述原因。

  •   

    问:这是否必须对从同一台计算机调用相同资源的多个进程执行任何操作?

    没有

  •   

    问:来自ASIO docs ASIO SSL不是线程安全的,但在这种情况下,我只运行一个线程但不同的进程(我相信这是绝对安全的),除了上面的代码本身就是线程安全。潜在的openssl表现不稳定吗?

    此处不存在线程安全或底层SSL库。

  •   

    问:有时在创建Boost ASIO SSL上下文时会遇到异常,只需说&#34; context:ssl error&#34;。同样的想法,为什么它表现得像这样?这是否与多个流程有关,在这种情况下是否会混淆?

    它不太可能,但 可能 每个ssl::context实例都会产生开销。您可以尝试静态地/循环地分配它。

    也就是说,如果SSL上下文只是运行到(相同的)资源限制,那么初始化的可能性更大,因为它可能会打开一些系统配置文件和/或检查是否存在众所周知的路径(例如CApath等)