0

Reference: https://www.boost.org/doc/libs/1_80_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp

My websocket client application was built based on the above example. Now I experience a bottleneck where one websocket connection subscribes too many channels from server and the server has a limit on how many messages a single connection can receive. In order to fix the issues, the solution is to load balance multiple channels across a few websocket connections. The platform I am using is Linux.

Question> Does the boost::beast framework offer a way so that I can easily add support for multiple websocket connections without locks(i.e. still use the asynchronous operations shown in above example). It is best if there is an example to illustrate the basic idea.

class WebSocketConnection {
  ...
  void on_read(beast::error_code ec, std::size_t) {
      if (ec)
        return fail(ec, "read");

      // trigger MainClass::message_callback
      msg_callback(std::move(buffered_message_from_server));

      // continue to read further messages from server
    }
    ...
}

class MainClass {
  void message_callback(std::string msg) {

    }
  ...
  WebSocketConnection websocket_;
};

Updated:

One solution I could figure out is follows but I am not sure whether this is applicable.

class WebSocketConnection {
  ...
  void on_read(beast::error_code ec, std::size_t) {
      if (ec)
        return fail(ec, "read");

      // trigger MainClass::message_callback
      msg_callback(std::move(buffered_message_from_server));

      // continue to read further messages from server
    }
    ...
}

class MainClass {
  void message_callback(std::string msg) {

    }
  ...
  std::vector<WebSocketConnection> websockets_;
};

Basically, I define a vector of WebSocketConnection within MyClass. Each instance of WebSocketConnection will be registered a same callback function(i.e. MainClass::message_callback). Also each instance of WebSocketConnection will be passed the same net::io_context and net::strandnet::io_context::executor_type, so that all message_callback from the pool of websocket will be a sequential event.

Question> Can I do this setup without introducing race condition?

Thank you

q0987
  • 34,938
  • 69
  • 242
  • 387
  • 1
    I don't understand what you're looking for. You can write whatever you want, perhaps you should just try and post concrete questions. What you describe is not a general-purpose need, so it won't exist out-of-the-box. But it doesn't sound too hard. The advanced examples might give you inspiration, like e.g. https://www.boost.org/doc/libs/1_80_0/libs/beast/example/http/client/crawl/http_crawl.cpp – sehe Nov 09 '22 at 20:49
  • 1
    More inspiration https://stackoverflow.com/a/49330236/85371 and https://stackoverflow.com/a/69908177/85371. Oh and one that actually does something related to trading https://stackoverflow.com/a/73861075/85371 (which I suspect is what you're doing as well) – sehe Nov 09 '22 at 20:54
  • @sehe, I have updated my question based on your comments. – q0987 Nov 09 '22 at 21:28
  • 1
    "I am not sure whether this is applicable" - I'm not sure why it would not be. If you have multiple IO threads you can use a strand executor to make sure no two handlers on the strand overlap in execution. – sehe Nov 09 '22 at 21:42
  • @sehe, different from above referred examples, I don't want to introduce threads(std::thread) unnecessarily if I could just rely on the websocket async operations. My application is a single-thread application and I like to keep it this way if I could. The issue is not the CPU cannot keep up instead the server limits how many messages each connections can receive per second. – q0987 Nov 09 '22 at 21:45
  • @sehe, So the ideal case is that One MainClass handles all websocket connections without introducing any extra threads. – q0987 Nov 09 '22 at 21:49
  • 1
    Great, then it can be trivially thread safe. – sehe Nov 09 '22 at 21:52

0 Answers0