Update RPC server to use asynchronous IO. #214

pull jordanlewis wants to merge 2 commits into bitcoin:master from jordanlewis:rpc-asio changing 1 files +385 −103
  1. jordanlewis commented at 6:56 pm on May 9, 2011: contributor

    This patch set updates bitcoin’s RPC server to use boost::asio’s async_read, _write, etc instead of their non-asynchronous versions.

    The server still exists as a single separate thread, but the async calls should greatly improve performance under high load. The next step in robustifying the RPC server is to create a pool of threads for the RPC server, each of which handle a number of asynchronously reading and writing connections.

  2. jrmithdobbs commented at 5:11 am on May 27, 2011: contributor
    This works great for me as is and is a good first step to fixing this.
  3. shanew commented at 7:02 pm on May 29, 2011: contributor
    Can you rebase? This doesn’t apply to current tree.
  4. Update RPC server to use asynchronous IO
    Properly does ASIO for both SSL and non-SSL cases if SSL is enabled, and
    also if SSL is disabled.
    
    Next steps: attempt to non-block on the actual RPC call.
                make the whole thing a thread pool
    9424ab37de
  5. Remove debug printfs bb04a7750c
  6. jordanlewis commented at 2:57 am on May 30, 2011: contributor
    Rebased to current tree.
  7. shanew commented at 6:12 pm on June 7, 2011: contributor

    Using this patch on a heavily loaded bitcoind, I am getting quite a few: reservekeyfromkeypool(): read failed from send transactions.

    I backed out the patch and so far so good but time will tell. Are you aware of any wallet locking issues with this async code?

  8. dlancer commented at 3:20 am on June 10, 2011: none
    Can you rebase with latest version? With transaction fee 0.0005 ? Why this important pull still not merged with upstream?
  9. jgarzik commented at 9:10 am on June 14, 2011: contributor
    Any updated test results, from heavily loaded bitcoind’s?
  10. doublec commented at 4:28 am on June 17, 2011: none
    I’m running this patch on a loaded server. It works fine, but I’ve seen one problem. If I do “bitcoind listtransactions” I get a correct list of transactions. If I do “bitcoind listtransactions "” 1000" I get: error: couldn’t parse reply from server
  11. jgarzik commented at 4:40 am on June 17, 2011: contributor
    Any chance you can look at wireshark output, or some other way of dumping the network traffic, and see what’s going on? Sounds like output was truncated somewhere.
  12. doublec commented at 4:45 am on June 17, 2011: none
    Yep, I’ll do that in a day or so and report back.
  13. jrmithdobbs commented at 12:58 pm on June 17, 2011: contributor

    I don’t have the dumps I made handy but I’ve seen this issue as well. It only seems to happen on large RPC calls like listtransactions. I actually ran across it testing out sipa’s showwallet branch for privkey import/export and didn’t make the correlation until seeing your comments.

    Reverting this makes it stop happening. So there’s definitely an issue here and this shouldn’t be pulled until resolved.

    The dumps I did showed it just cutting off in the middle sometimes or sometimes leaving out chunks of the response that made the json not validate.

  14. jordanlewis commented at 3:39 pm on June 17, 2011: contributor
    Thanks for the testing guys. I’ll look into this issue.
  15. jordanlewis closed this on Jun 17, 2011

  16. jordanlewis reopened this on Jun 17, 2011

  17. jrmithdobbs commented at 3:25 pm on June 18, 2011: contributor
    Some more info. It also happens on RPC requests receiving a lot of data. Eg, sipa’s importwallet. The “alot” seems to be around the 1k boundary or so from my very brief testing.
  18. jine commented at 10:44 pm on June 25, 2011: none
    I’m willing to pay to get this fixed and working in production use. Also looking for a keep-alive solution which would reuse connections to bitcoind.
  19. in src/rpc.cpp: in bb04a7750c
    2037+                        shared_from_this(), asio::placeholders::error,
    2038+                        asio::placeholders::bytes_transferred));
    2039+    }
    2040+    void respond(std::string str)
    2041+    {
    2042+        boost::asio::async_write(socket, boost::asio::buffer(str),
    


    ius commented at 6:56 pm on June 28, 2011:
    str goes out of scope when the method returns
  20. ius commented at 6:59 pm on June 28, 2011: contributor

    See comment above. A possible fix: http://pastie.org/private/d04wwgdsk881yl70k1g

    I’m not familiar with boost though, so there might very well be a better solution.

  21. JoelKatz commented at 1:17 am on July 3, 2011: contributor

    If your plan is to optimize the RPC code, you’re kind of barking up the wrong tree. The socket I/O is only about 3% of the load coming from the RPC code. If you just want it to handle more than one connection at a time and keepalives, just dispatching the RPC to a thread (and fixing the protocol handler to close the socket when it’s the right time) does it.

    The breakdown is, roughly: 30% Do the actual operation (various based on the operation, of course) 20% Parse JSON request 20% Generate JSON reply 15% Parse HTTP 4% Check user/pass/IP 3% Socket I/O 2% Make JSON reply 1% Send HTTP reply

    This is still the right thing to do. However, there are much simpler and less invasive ways to accomplish the same thing. Now, if you had done this for the net code, that would actually make a huge difference.

  22. jgarzik commented at 1:32 am on July 3, 2011: contributor

    @JoelKatz: you missed the point. This is not an optimization, but a big step towards correcting a major design flaw. The current RPC code executes HTTP requests in order, in a FIFO queue.

    You can find examples of this logic in “My First TCP Server” style code examples, but never in any production server. A synchronous, FIFO approach stalls all clients except the “current” one. If the current client is, itself, stalled or slow or misbehaving, then all other clients suffer.

    Asynchronous I/O + HTTP/1.1 keep alives are desperately needed to solve obvious problems seen in the field by heavy RPC users.

  23. JoelKatz commented at 3:08 am on July 3, 2011: contributor
    As I said, that issue is more easily solved by simply dispatching the RPC to a thread and making the trivial fixes to the keepalive logic. There aren’t enough RPC connections, and the operation order is always accept/read/write, so you don’t get any benefit from asynchronous I/O. In contrast, in the ’net’ code, you have many connections and unpredictable operation order. That code would significantly benefit from async I/O.
  24. jgarzik commented at 3:10 am on July 3, 2011: contributor
    One thread per RPC connection is unscalable in many modern workloads. That is also potentially DoS’able, if you’re not careful.
  25. JoelKatz commented at 3:35 am on July 3, 2011: contributor

    I don’t think many people, if any, expose their bitcoin RPC connections to the world. So I don’t think the DoS issue is particularly important. I guess you could argue that they don’t because they can’t, and if they could, they might. But I think most people run a bitcoin client on each machine that needs to issue RPC queries and should bind their RPC listening sockets to ’localhost’ only.

    As for RPC not being scalable in modern workloads, I would argue that modern workloads include proper support for keepalives and don’t require large numbers of connections.

    If there’s a realistic case where asio for RPC provides any benefit over thread-per-connection with proper keepalive support, I don’t know what it is. Again, I still think this patch is “the right thing to do”, but I don’t think there will be any actual benefit in any realistic use case. (Again, over dipatching the RPC calls to threads and fixing the broken HTTP keepalive implementation. You have to at least do that.)

  26. jgarzik commented at 3:46 am on July 15, 2011: contributor
    Any rebase / update for current tree?
  27. alexwaters commented at 8:06 am on September 30, 2011: contributor

    The pull has become unmergeable (without conflicts), and will be closed in 15 days from this message if action is not taken.

    To prevent closure, kindly rebase the pull to merge cleanly with the current codebase. If a time extension is needed, please respond to this comment or contact QA@BitcoinTesting.org.

  28. jordanlewis commented at 1:41 pm on September 30, 2011: contributor
    Sorry guys, I don’t have the time to maintain this pull indefinitely. Anyone please feel free to rebase and maintain yourself. I think it’s an important patch.
  29. jordanlewis closed this on Sep 30, 2011

  30. jordanlewis reopened this on Sep 30, 2011

  31. alexwaters commented at 5:39 am on October 20, 2011: contributor
    Closed pending rebase / additional commentary. The rebase label has been applied.
  32. alexwaters closed this on Oct 20, 2011

  33. dexX7 referenced this in commit d91588f87b on Dec 1, 2014
  34. sipa referenced this in commit 9d09322b41 on Mar 27, 2015
  35. TheBlueMatt referenced this in commit 582b2934e6 on Oct 20, 2015
  36. deadalnix referenced this in commit 0bada0e2a9 on Jan 19, 2017
  37. deadalnix referenced this in commit e89e3cd882 on Feb 12, 2017
  38. lateminer referenced this in commit 7edeacb64e on Dec 9, 2017
  39. attilaaf referenced this in commit 009c89f7f4 on Jan 13, 2020
  40. Losangelosgenetics referenced this in commit 84abe866d2 on Mar 12, 2020
  41. rajarshimaitra referenced this in commit 75c2ebc9b0 on Aug 5, 2021
  42. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-08 22:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me