All Projects → Tradias → asio-grpc

Tradias / asio-grpc

Licence: Apache-2.0 license
Asynchronous gRPC with Asio/unified executors

Programming Languages

C++
36643 projects - #6 most used programming language
CMake
9771 projects

Projects that are alternatives of or similar to asio-grpc

Cxxhttp
Asynchronous, Header-only C++ HTTP-over-(TCP|UNIX Socket|STDIO) Library
Stars: ✭ 24 (-76%)
Mutual labels:  asynchronous, asio
zab
C++20 liburing backed coroutine executor and event loop framework.
Stars: ✭ 54 (-46%)
Mutual labels:  asynchronous, cpp20
Purerpc
Asynchronous pure Python gRPC client and server implementation supporting asyncio, uvloop, curio and trio
Stars: ✭ 125 (+25%)
Mutual labels:  asynchronous, grpc
SierraChartZorroPlugin
A Zorro broker API plugin for Sierra Chart, written in Win32 C++.
Stars: ✭ 22 (-78%)
Mutual labels:  asynchronous, asio
Asio samples
Examples (code samples) describing the construction of active objects on the top of Boost.Asio. A code-based guide for client/server creation with usage of active object pattern by means of Boost C++ Libraries.
Stars: ✭ 191 (+91%)
Mutual labels:  asynchronous, asio
agrpc
Async GRPC with C++20 coroutine support
Stars: ✭ 53 (-47%)
Mutual labels:  grpc, cpp20
ip scan
Scan a list of IPs quickly using multithreading
Stars: ✭ 13 (-87%)
Mutual labels:  asynchronous
fetch-http-client
A http client wrapper for fetch api with middleware support.
Stars: ✭ 42 (-58%)
Mutual labels:  asynchronous
buckshot
A fast and capable Minecraft name sniper.
Stars: ✭ 21 (-79%)
Mutual labels:  asynchronous
asynctools
Various asynchronous tools for Nim language
Stars: ✭ 88 (-12%)
Mutual labels:  asynchronous
grpc-chat
Simple Chat Server/Client implemented with gRPC
Stars: ✭ 107 (+7%)
Mutual labels:  grpc
bazel-cache
Minimal cloud oriented Bazel gRPC cache
Stars: ✭ 33 (-67%)
Mutual labels:  grpc
go-tensorflow
Tools and libraries for using Tensorflow (and Tensorflow Serving) in go
Stars: ✭ 25 (-75%)
Mutual labels:  grpc
fm.consulinterop
a lib for build micro-service
Stars: ✭ 33 (-67%)
Mutual labels:  grpc
zepto
⚡️Lightweight web framework written in go
Stars: ✭ 115 (+15%)
Mutual labels:  grpc
node-grpc-ssl
Basic example gRPC protocol with NodeJS + SSL + Docker
Stars: ✭ 40 (-60%)
Mutual labels:  grpc
agentgo
Hi! Agentgo is a tool for making remote command executions from server to client with golang, protocol buffers (protobuf) and grpc.
Stars: ✭ 15 (-85%)
Mutual labels:  grpc
sdsl-lite
Succinct Data Structure Library 3.0
Stars: ✭ 55 (-45%)
Mutual labels:  cpp20
cheap-watch
If it works, why use something else? // Mirror of https://git.chor.date/Conduitry/cheap-watch
Stars: ✭ 64 (-36%)
Mutual labels:  asynchronous
MR.AspNetCore.Jobs
A background processing library for Asp.Net Core.
Stars: ✭ 59 (-41%)
Mutual labels:  asynchronous

asio-grpc

Reliability Rating Reliability Rating vcpkg hunter

An Executor, Networking TS and std::execution interface to grpc::CompletionQueue for writing asynchronous gRPC clients and servers using C++20 coroutines, Boost.Coroutines, Asio's stackless coroutines, callbacks, sender/receiver and more.

Features

Example

  • Server side 'hello world':

std::unique_ptr<grpc::Server> server;

grpc::ServerBuilder builder;
agrpc::GrpcContext grpc_context{builder.AddCompletionQueue()};
builder.AddListeningPort(host, grpc::InsecureServerCredentials());
helloworld::Greeter::AsyncService service;
builder.RegisterService(&service);
server = builder.BuildAndStart();

boost::asio::co_spawn(
    grpc_context,
    [&]() -> boost::asio::awaitable<void>
    {
        grpc::ServerContext server_context;
        helloworld::HelloRequest request;
        grpc::ServerAsyncResponseWriter<helloworld::HelloReply> writer{&server_context};
        co_await agrpc::request(&helloworld::Greeter::AsyncService::RequestSayHello, service, server_context,
                                request, writer);
        helloworld::HelloReply response;
        response.set_message("Hello " + request.name());
        co_await agrpc::finish(writer, response, grpc::Status::OK);
    },
    boost::asio::detached);

grpc_context.run();

snippet source | anchor

More examples for things like streaming RPCs, double-buffered file transfer with io_uring, libunifex-based coroutines and sharing a thread with an io_context can be found in the example directory.

Requirements

Tested by CI:

  • gRPC 1.44.0, 1.16.1 (older versions might work as well)
  • Boost 1.79.0 (min. 1.74.0)
  • Standalone Asio 1.17.0 (min. 1.17.0)
  • libunifex 2022-02-09
  • MSVC 19.31 (Visual Studio 17 2022)
  • GCC 8.4.0, 9.3.0, 10.3.0, 11.1.0
  • Clang 10.0.0, 11.0.0, 12.0.0
  • AppleClang 13.0.0.13000029
  • C++17 and C++20

For MSVC compilers and asio-grpc before v1.6.0 the following compile definitions need to be set:

BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT
BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT
BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT
BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT
BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT
BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT

When using standalone Asio then omit the BOOST_ prefix.

Usage

The library can be added to a CMake project using either add_subdirectory or find_package. Once set up, include the individual headers from the agrpc/ directory or the combined header:

#include <agrpc/asioGrpc.hpp>
As a subdirectory

Clone the repository into a subdirectory of your CMake project. Then add it and link it to your target.

Using Boost.Asio:

find_package(gRPC)
find_package(Boost)
add_subdirectory(/path/to/repository/root)
target_link_libraries(your_app PUBLIC gRPC::grpc++ asio-grpc::asio-grpc Boost::headers)

Or using standalone Asio:

find_package(gRPC)
find_package(asio)
add_subdirectory(/path/to/repository/root)
target_link_libraries(your_app PUBLIC gRPC::grpc++ asio-grpc::asio-grpc-standalone-asio asio::asio)

Or using libunifex:

find_package(gRPC)
find_package(unifex)
add_subdirectory(/path/to/repository/root)
target_link_libraries(your_app PUBLIC gRPC::grpc++ asio-grpc::asio-grpc-unifex unifex::unifex)

As a CMake package

Clone the repository and install it.

cmake -B build -DCMAKE_INSTALL_PREFIX=/desired/installation/directory .
cmake --build build --target install

Locate it and link it to your target.

Using Boost.Asio:

# Make sure CMAKE_PREFIX_PATH contains /desired/installation/directory
find_package(asio-grpc)
target_link_libraries(your_app PUBLIC asio-grpc::asio-grpc)

Or using standalone Asio:

# Make sure CMAKE_PREFIX_PATH contains /desired/installation/directory
find_package(asio-grpc)
target_link_libraries(your_app PUBLIC asio-grpc::asio-grpc-standalone-asio)

Or using libunifex:

# Make sure CMAKE_PREFIX_PATH contains /desired/installation/directory
find_package(asio-grpc)
target_link_libraries(your_app PUBLIC asio-grpc::asio-grpc-unifex)

Using vcpkg

Add asio-grpc to the dependencies inside your vcpkg.json:

{
    "name": "your_app",
    "version": "0.1.0",
    "dependencies": [
        "asio-grpc",
        // To use the Boost.Asio backend add
        // "boost-asio",
        // To use the standalone Asio backend add
        // "asio",
        // To use the libunifex backend add
        // "libunifex"
    ]
}

Locate asio-grpc and link it to your target in your CMakeLists.txt:

find_package(asio-grpc)
# Using the Boost.Asio backend
target_link_libraries(your_app PUBLIC asio-grpc::asio-grpc)
# Or use the standalone Asio backend
#target_link_libraries(your_app PUBLIC asio-grpc::asio-grpc-standalone-asio)
# Or use the libunifex backend
#target_link_libraries(your_app PUBLIC asio-grpc::asio-grpc-unifex)

Available features

boost-container - Use Boost.Container instead of <memory_resource>

See selecting-library-features to learn how to select features with vcpkg.

Using Hunter

See asio-grpc's documentation on the Hunter website: https://hunter.readthedocs.io/en/latest/packages/pkg/asio-grpc.html.

CMake Options

ASIO_GRPC_USE_BOOST_CONTAINER - Use Boost.Container instead of <memory_resource>.

ASIO_GRPC_DISABLE_AUTOLINK - Set before using find_package(asio-grpc) to prevent asio-grpcConfig.cmake from finding and setting up interface link libraries.

Performance

asio-grpc is part of grpc_bench. Head over there to compare its performance against other libraries and languages.

Results from the helloworld unary RPC
Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz, Linux, Boost 1.78, gRPC 1.45.0, asio-grpc v1.5.0, jemalloc 5.2.1

Results

1 CPU server

name req/s avg. latency 90 % in 95 % in 99 % in avg. cpu avg. memory
rust_tonic_mt 47057 21.08 ms 9.45 ms 10.30 ms 538.94 ms 101.99% 23.03 MiB
rust_thruster_mt 42084 23.61 ms 10.40 ms 11.27 ms 619.37 ms 99.59% 18.96 MiB
cpp_asio_grpc_unifex 41392 24.01 ms 25.49 ms 25.97 ms 27.21 ms 101.87% 23.19 MiB
rust_grpcio 41036 24.19 ms 25.77 ms 26.45 ms 27.56 ms 102.04% 37.3 MiB
cpp_grpc_mt 39971 24.88 ms 26.37 ms 26.79 ms 28.24 ms 101.49% 17.95 MiB
cpp_asio_grpc_callback 39669 25.08 ms 26.67 ms 27.22 ms 29.26 ms 101.27% 23.44 MiB
cpp_asio_grpc_cpp20_coroutine 34918 28.52 ms 31.02 ms 31.55 ms 32.89 ms 100.9% 19.61 MiB
cpp_grpc_callback 12061 78.32 ms 104.41 ms 113.88 ms 165.21 ms 100.16% 123.0 MiB
go_grpc 7391 128.34 ms 220.03 ms 299.23 ms 432.17 ms 98.03% 29.62 MiB

2 CPU server

name req/s avg. latency 90 % in 95 % in 99 % in avg. cpu avg. memory
cpp_grpc_mt 85780 10.04 ms 18.31 ms 22.16 ms 30.52 ms 200.78% 48.37 MiB
cpp_asio_grpc_unifex 84826 10.07 ms 18.46 ms 22.92 ms 33.97 ms 200.05% 43.57 MiB
cpp_asio_grpc_callback 83421 10.40 ms 19.34 ms 23.41 ms 34.31 ms 202.11% 47.62 MiB
cpp_asio_grpc_cpp20_coroutine 76205 11.77 ms 22.43 ms 26.47 ms 37.30 ms 202.9% 46.58 MiB
rust_tonic_mt 75512 12.42 ms 33.21 ms 51.89 ms 79.70 ms 201.96% 19.17 MiB
cpp_grpc_callback 73730 11.99 ms 21.13 ms 27.39 ms 41.39 ms 206.76% 153.53 MiB
rust_thruster_mt 67854 13.91 ms 37.24 ms 59.66 ms 85.51 ms 201.0% 14.41 MiB
rust_grpcio 67496 14.22 ms 21.79 ms 23.92 ms 27.76 ms 200.15% 37.24 MiB
go_grpc 16291 53.61 ms 99.19 ms 112.99 ms 175.49 ms 151.25% 29.14 MiB

Documentation

API reference

The main workhorses of this library are the agrpc::GrpcContext and its executor_type - agrpc::GrpcExecutor.

The agrpc::GrpcContext implements asio::execution_context and can be used as an argument to Asio functions that expect an ExecutionContext like asio::spawn.

Likewise, the agrpc::GrpcExecutor satisfies the Executor and Networking TS and Scheduler requirements and can therefore be used in places where Asio/libunifex expects an Executor or Scheduler.

The API for RPCs is modeled closely after the asynchronous, tag-based API of gRPC. As an example, the equivalent for grpc::ClientAsyncReader<helloworld::HelloReply>.Read(helloworld::HelloReply*, void*) would be agrpc::read(grpc::ClientAsyncReader<helloworld::HelloReply>&, helloworld::HelloReply&, CompletionToken).

Instead of the void* tag in the gRPC API the functions in this library expect a CompletionToken. Asio comes with several CompletionTokens already: C++20 coroutine, stackless coroutine, callback and Boost.Coroutine. There is also a special token created by agrpc::use_sender(scheduler) that causes RPC functions to return a TypedSender.

If you are interested in learning more about the implementation details of this library then check out this blog article.

Getting started

Getting started

Start by creating a agrpc::GrpcContext.

For servers and clients:

grpc::ServerBuilder builder;
agrpc::GrpcContext grpc_context{builder.AddCompletionQueue()};

snippet source | anchor

For clients only:

agrpc::GrpcContext grpc_context{std::make_unique<grpc::CompletionQueue>()};

snippet source | anchor

Add some work to the grpc_context and run it. Make sure to shutdown the server before destructing the grpc_context. Also destruct the grpc_context before destructing the server. A grpc_context can only be run on one thread at a time.

grpc_context.run();
server->Shutdown();
}  // grpc_context is destructed here before the server

snippet source | anchor

It might also be helpful to create a work guard before running the agrpc::GrpcContext to prevent grpc_context.run() from returning early.

std::optional guard{asio::require(grpc_context.get_executor(), asio::execution::outstanding_work_t::tracked)};

snippet source | anchor

Where to go from here?

Check out the examples and the API documentation.

What users are saying

Asio-grpc abstracts away the implementation details of asynchronous grpc handling: crafting working code is easier, faster, less prone to errors and considerably more fun. At 3YOURMIND we reliably use asio-grpc in production since its very first release, allowing our developers to effortlessly implement low-latency/high-throughput asynchronous data transfer in time critical applications.

@3YOURMIND

Our project is a real-time distributed motion capture system that uses your framework to stream data back and forward between multiple machines. Previously I have tried to build a bidirectional streaming framework from scratch using only gRPC. However, it's not maintainable and error-prone due to a large amount of service and streaming code. As a developer whose experienced both raw grpc and asio-grpc, I can tell that your framework is a real a game-changer for writing grpc code in C++. It has made my life much easier. I really appreciate the effort you have put into this project and your superior skills in designing c++ template code.

@khanhha

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].