Rust-Grpc rs: grpc-rs — The gRPC library for Rust built on C Core library and futures

gRPC-rs

gRPC-rs is a Rust wrapper of gRPC Core. gRPC is a high performance, open source universal RPC framework that puts mobile and HTTP/2 first.

Crates.io docs.rs Build Status Build Status

Status

This project is still under development. The following features with the check marks are supported:

  • Basic asynchronous unary/steaming call
  • SSL
  • Generic call
  • Connection level compression
  • Interoperability test
  • QPS benchmark
  • Custom metadata
  • Health check
  • Reflection
  • Authentication
  • Load balance, client side is fully supported, server side load report is not implemented yet.

Prerequisites

  • CMake >= 3.8.0
  • Rust >= 1.19.0
  • binutils >= 2.22
  • LLVM and Clang >= 3.9 if you need to generate bindings at compile time.
  • By default, the secure feature is provided by boringssl, which requires Go (>=1.7) to build. You can also use openssl instead by enabling openssl feature.

For Linux and MacOS, you also need to install gcc (or clang) too.

Bindings are pre-generated for x86_64 Linux. For other platforms, bindings are generated at compile time.

For Windows, you also need to install following software:

  • Active State Perl
  • yasm
  • Visual Studio 2015+

Build

$ ./scripts/reset-submodule.cmd # if you just cloned the repository
$ cargo build

Error linking OpenSSL

If you're getting linker errors when building your project using gRPC-rs, head down to the openssl feature section for a possible fix.

Usage

To generate the sources from proto files:

Option 1 - Manual Generation

  1. Install the protobuf compiler:
$ cargo install protobuf-codegen
  1. Install the gRPC compiler:
$ cargo install grpcio-compiler
  1. Generate the sources:
$ protoc --rust_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_rust_plugin` example.proto

Option 2 - Programmatic Generation

Programmatic generation can be used to generate Rust modules from proto files via your build.rs by using protoc-grpcio.

For more information and examples see README.

To include this project as a dependency:

[dependencies]
grpcio = "0.4"

Feature secure

secure feature enables support for TLS encryption and some authentication mechanism. When you do not need it, for example when working in intranet, you can disable it by using the following configuration:

[dependencies]
grpcio = { version = "0.4", default-features = false, features = ["protobuf-codec"] }

Feature openssl

gRPC-rs comes vendored with gRPC Core, which by default uses BoringSSL instead of OpenSSL. This may cause linking issues due to symbol clashes and/or missing symbols when another one of your dependencies uses OpenSSL. To resolve this, you can tell gRPC-rs to use OpenSSL too by specifying "openssl" in your Cargo.toml's features list for gprcio, which requires openssl (>=1.0.2). E.g.:

[dependencies]
grpcio = { version = "0.4.4", features = ["openssl"] }

Performance

See benchmark to find out how to run a benchmark by yourself.

Cross Compile

See cross_compile

Contributing

Make sure to format and test the code before sending a PR.

If the content in grpc-sys/grpc is updated, you may need to regenerate bindings:

$ ./scripts/generate-bindings.sh

Comments

  • Fixed date in changelog
    Fixed date in changelog

    Mar 31, 2020

    Just fixing small typo

    Reply
  • grpcio::Env can leak threads -- it detaches them instead of joining them
    grpcio::Env can leak threads -- it detaches them instead of joining them

    Apr 1, 2020

    The grpcio::env impl of Drop requests that all the completion queues shutdown, but does not actually join the threads.

    For many applications this works fine, often a webserver does not require a graceful shutdown strategy.

    However, in my usecase I want to validate that even if the server goes down and comes back repeatedly, the users are able to recover their data from the database.

        let users = ... mock user set
    
        for phase_count in 0..NUM_PHASES {
            log::info!(logger, "Phase {}/{}", phase_count + 1, NUM_PHASES);
    
            // First make grpcio env
            let grpcio_env = mobile_acct_api::make_env();
    
            ... make server, make client,
            ... make requests for each mock user,
            ... validate results
        }
    

    Although grpcio_env is scoped to the loop body, the implementation of Drop does not join the threads. When the test ends, it crashes consistently, because my server contains an SGX enclave, and there is a static object in the intel library SimEnclaveMgr which is torn down before these threads get cleaned up. Then they try to tear down their enclaves and SIGSEGV occurs.

    I believe that with the current API, I cannot guarantee that my grpcio threads are torn down before that object is. The only way that I can do that is if there is some API on grpcio::Environment that actually joins the threads.

    In the grpc-rs rust tests that validate grpcio::Environment, you yourselves have written code that explicitly joins the join handles, instead of leaving them detached. I would like to be able to do that in my tests at the end of my loop body.

    I would like to expose this functionality as a new public function. This commit creates a new function shutdown_and_join, which issues the shutdown command, and then joins the join handles. It also makes the rust unit test in grpc-rs use that API. I would use this at the end of my loop body in my code example.

    This is not a breaking change, since we don't change the implementation of Drop or any other current public api.

    Reply
  • Fetch google.rpc.Status proto if present
    Fetch google.rpc.Status proto if present

    Apr 4, 2020

    This allows us to get metadata from the server around why a failure happened.

    We've been using this patch in an older version of the grpcio crate (https://github.com/pantsbuild/grpc-rs/commit/4dfafe9355dc996d7d0702e7386a6fedcd9734c0) for a while now to enable handling "both rpc status errors as well as message-inline errors" (see https://github.com/pantsbuild/pants/pull/6589).

    Reply
  • Support sending initial metadata and trailing metadata
    Support sending initial metadata and trailing metadata

    Apr 29, 2020

    Currently, only sending initial metadata from client side and receiving initial metadata from server side are supported. The missing parts are:

    • [ ] Sending initial metadata from server side
    • [ ] Receiving initial metadata from client side
    • [ ] Sending/Receiving trailing metadata
    Enhancement Help Wanted 
    Reply
  • How do you get started w/this project?
    How do you get started w/this project?

    May 24, 2020

    Hi,

    How do I get started with this project? I have a pre-existing project that I'm trying to integrate gRPC into it, but I'm not sure how I'm suppose to get started with this repo. Do I migrate over my other project into this project or am I suppose to place this project inside my current project?

    Just looking for a little guidance as to what I'm suppose to do after I've built my proto files.

    My particular use-case is to build a rust gRPC client that can talk to an already pre-established service in the cloud. So I just want to be able to get a client setup which can connect to a gRPC server in the cloud.

    Any guidance would be helpful. Thanks in advance.

    Help Wanted Question 
    Reply
  • Enhance sinks to make them batchable
    Enhance sinks to make them batchable

    Jun 17, 2020

    close #415

    Optimize send_all using sink in grpc-rs. By buffering the message to be sent to determine whether there is still message in the stream, and add the buffer_hint flag to indicate follow-up messages.

    After a simple test, this does improve the QPS by 50%.

    Before
    ======== test_client_stream_send_split
    QPS: 13626.411713542033
    ======== test_client_stream_send_all
    QPS: 13458.8795676736
    ======== test_server_stream_send_all
    QPS: 21513.004479575207
    
    After
    ======== test_client_stream_send_split
    QPS: 13632.78241828707
    ======== test_client_stream_send_all
    QPS: 20634.743684214573
    ======== test_server_stream_send_all
    QPS: 21282.527286920154
    
    // tcpdump capture file size (only send_all test)
    Before:22M
    After:2.6M
    

    Related test code: https://github.com/hunterlxt/grpc-rs/blob/xt/bench-sink-over-master/tests-and-examples/examples/hello_world/client.rs

    Enhancement 
    Reply
  • grpc-sys 0.4.2 fails to build - but 0.4.1 builds fine
    grpc-sys 0.4.2 fails to build - but 0.4.1 builds fine

    Jan 15, 2019

    Describe the bug

    0.4.2 fails to build for us with CentOS 7.

    To Reproduce

    On CentOS 7 run cargo build against a crate which depends on either grpc-sys 0.4.2, or grpc-sys 0.4.1

    With grpc-sys 0.4.2, the following is seen:

    error: failed to run custom build command for `grpcio-sys v0.4.2`
    process didn't exit successfully: `/target/debug/build/grpcio-sys-840781b2e44e9c86/build-script-build` (exit code: 101)
    --- stdout
    cargo:rerun-if-changed=grpc_wrap.cc
    cargo:rerun-if-changed=grpc
    cargo:rerun-if-env-changed=GRPCIO_SYS_USE_PKG_CONFIG
    cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS
    running: "cmake" "/opt/rust/registry/src/github.com-1ecc6299db9ec823/grpcio-sys-0.4.2/grpc" "-DGO_EXECUTABLE=fake-go-nonexist" "-DgRPC_INSTALL=false" "-DgRPC_BUILD_CSHARP_EXT=false" "-DgRPC_BUILD_CODEGEN=false" "-DCMAKE_INSTALL_PREFIX=.../target/debug/build/grpcio-sys-f45f9c164b4a8726/out" "-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_C_COMPILER=/usr/local/bin/cc" "-DCMAKE_CXX_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_CXX_COMPILER=/usr/bin/c++" "-DCMAKE_BUILD_TYPE=Debug"
    -- The C compiler identification is GNU 4.8.5
    -- The CXX compiler identification is GNU 4.8.5
    -- Check for working C compiler: /usr/local/bin/cc
    -- Check for working C compiler: /usr/local/bin/cc -- works
    -- Detecting C compiler ABI info
    -- Detecting C compiler ABI info - done
    -- Check for working CXX compiler: /usr/bin/c++
    -- Check for working CXX compiler: /usr/bin/c++ -- works
    -- Detecting CXX compiler ABI info
    -- Detecting CXX compiler ABI info - done
    -- Looking for sys/types.h
    -- Looking for sys/types.h - found
    -- Looking for stdint.h
    -- Looking for stdint.h - found
    -- Looking for stddef.h
    -- Looking for stddef.h - found
    -- Check size of off64_t
    -- Check size of off64_t - done
    -- Looking for fseeko
    -- Looking for fseeko - found
    -- Looking for unistd.h
    -- Looking for unistd.h - found
    -- Renaming
    --     /opt/rust/registry/src/github.com-1ecc6299db9ec823/grpcio-sys-0.4.2/grpc/third_party/zlib/zconf.h
    -- to 'zconf.h.included' because this file is included with zlib
    -- but CMake generates it automatically in the build directory.
    -- Looking for res_servicename in resolv
    -- Looking for res_servicename in resolv - not found
    -- Looking for gethostbyname in nsl
    -- Looking for gethostbyname in nsl - found
    -- Looking for gethostbyname in socket
    -- Looking for gethostbyname in socket - not found
    -- Looking for clock_gettime in rt
    -- Looking for clock_gettime in rt - found
    -- Looking for include file sys/socket.h
    -- Looking for include file sys/socket.h - found
    -- Looking for include file arpa/inet.h
    -- Looking for include file arpa/inet.h - found
    -- Looking for include file arpa/nameser_compat.h
    -- Looking for include file arpa/nameser_compat.h - found
    -- Looking for include file arpa/nameser.h
    -- Looking for include file arpa/nameser.h - found
    -- Looking for include file assert.h
    -- Looking for include file assert.h - found
    -- Looking for include file errno.h
    -- Looking for include file errno.h - found
    -- Looking for include file fcntl.h
    -- Looking for include file fcntl.h - found
    -- Looking for include file inttypes.h
    -- Looking for include file inttypes.h - found
    -- Looking for include file limits.h
    -- Looking for include file limits.h - found
    -- Looking for include file malloc.h
    -- Looking for include file malloc.h - found
    -- Looking for include file memory.h
    -- Looking for include file memory.h - found
    -- Looking for include file netdb.h
    -- Looking for include file netdb.h - found
    -- Looking for include file netinet/in.h
    -- Looking for include file netinet/in.h - found
    -- Looking for include file netinet/tcp.h
    -- Looking for include file netinet/tcp.h - found
    -- Looking for include file net/if.h
    -- Looking for include file net/if.h - found
    -- Looking for include file signal.h
    -- Looking for include file signal.h - found
    -- Looking for include file socket.h
    -- Looking for include file socket.h - not found
    -- Looking for include file stdbool.h
    -- Looking for include file stdbool.h - found
    -- Looking for include file stdlib.h
    -- Looking for include file stdlib.h - found
    -- Looking for include file strings.h
    -- Looking for include file strings.h - found
    -- Looking for include file string.h
    -- Looking for include file string.h - found
    -- Looking for include file stropts.h
    -- Looking for include file stropts.h - not found
    -- Looking for include file sys/ioctl.h
    -- Looking for include file sys/ioctl.h - found
    -- Looking for include file sys/param.h
    -- Looking for include file sys/param.h - found
    -- Looking for include file sys/select.h
    -- Looking for include file sys/select.h - found
    -- Looking for include file sys/stat.h
    -- Looking for include file sys/stat.h - found
    -- Looking for include file sys/time.h
    -- Looking for include file sys/time.h - found
    -- Looking for include file sys/uio.h
    -- Looking for include file sys/uio.h - found
    -- Looking for include file time.h
    -- Looking for include file time.h - found
    -- Looking for include file dlfcn.h
    -- Looking for include file dlfcn.h - found
    -- Looking for include file unistd.h
    -- Looking for include file unistd.h - found
    -- Looking for include files winsock2.h, windows.h
    -- Looking for include files winsock2.h, windows.h - not found
    -- Looking for 3 include files winsock2.h, ..., windows.h
    -- Looking for 3 include files winsock2.h, ..., windows.h - not found
    -- Looking for include files winsock.h, windows.h
    -- Looking for include files winsock.h, windows.h - not found
    -- Looking for include file windows.h
    -- Looking for include file windows.h - not found
    -- Performing Test HAVE_SOCKLEN_T
    -- Performing Test HAVE_SOCKLEN_T - Success
    -- Performing Test HAVE_TYPE_SOCKET
    -- Performing Test HAVE_TYPE_SOCKET - Failed
    -- Performing Test HAVE_BOOL_T
    -- Performing Test HAVE_BOOL_T - Success
    -- Performing Test HAVE_SSIZE_T
    -- Performing Test HAVE_SSIZE_T - Success
    -- Performing Test HAVE_LONGLONG
    -- Performing Test HAVE_LONGLONG - Success
    -- Performing Test HAVE_SIG_ATOMIC_T
    -- Performing Test HAVE_SIG_ATOMIC_T - Success
    -- Performing Test HAVE_STRUCT_ADDRINFO
    -- Performing Test HAVE_STRUCT_ADDRINFO - Success
    -- Performing Test HAVE_STRUCT_IN6_ADDR
    -- Performing Test HAVE_STRUCT_IN6_ADDR - Success
    -- Performing Test HAVE_STRUCT_SOCKADDR_IN6
    -- Performing Test HAVE_STRUCT_SOCKADDR_IN6 - Success
    -- Performing Test HAVE_STRUCT_SOCKADDR_STORAGE
    -- Performing Test HAVE_STRUCT_SOCKADDR_STORAGE - Success
    -- Performing Test HAVE_STRUCT_TIMEVAL
    -- Performing Test HAVE_STRUCT_TIMEVAL - Success
    -- Looking for AF_INET6
    -- Looking for AF_INET6 - found
    -- Looking for O_NONBLOCK
    -- Looking for O_NONBLOCK - found
    -- Looking for FIONBIO
    -- Looking for FIONBIO - found
    -- Looking for SIOCGIFADDR
    -- Looking for SIOCGIFADDR - found
    -- Looking for MSG_NOSIGNAL
    -- Looking for MSG_NOSIGNAL - found
    -- Looking for PF_INET6
    -- Looking for PF_INET6 - found
    -- Looking for SO_NONBLOCK
    -- Looking for SO_NONBLOCK - not found
    -- Looking for CLOCK_MONOTONIC
    -- Looking for CLOCK_MONOTONIC - found
    -- Performing Test HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
    -- Performing Test HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID - Success
    -- Performing Test HAVE_LL
    -- Performing Test HAVE_LL - Success
    -- Looking for bitncmp
    -- Looking for bitncmp - not found
    -- Looking for closesocket
    -- Looking for closesocket - not found
    -- Looking for CloseSocket
    -- Looking for CloseSocket - not found
    -- Looking for connect
    -- Looking for connect - found
    -- Looking for fcntl
    -- Looking for fcntl - found
    -- Looking for freeaddrinfo
    -- Looking for freeaddrinfo - found
    -- Looking for getaddrinfo
    -- Looking for getaddrinfo - found
    -- Looking for getenv
    -- Looking for getenv - found
    -- Looking for gethostbyaddr
    -- Looking for gethostbyaddr - found
    -- Looking for gethostbyname
    -- Looking for gethostbyname - found
    -- Looking for gethostname
    -- Looking for gethostname - found
    -- Looking for getnameinfo
    -- Looking for getnameinfo - found
    -- Looking for getservbyport_r
    -- Looking for getservbyport_r - found
    -- Looking for gettimeofday
    -- Looking for gettimeofday - found
    -- Looking for if_indextoname
    -- Looking for if_indextoname - found
    -- Looking for inet_net_pton
    -- Looking for inet_net_pton - not found
    -- Looking for inet_ntop
    -- Looking for inet_ntop - found
    -- Looking for inet_pton
    -- Looking for inet_pton - found
    -- Looking for ioctl
    -- Looking for ioctl - found
    -- Looking for ioctlsocket
    -- Looking for ioctlsocket - not found
    -- Looking for IoctlSocket
    -- Looking for IoctlSocket - not found
    -- Looking for recv
    -- Looking for recv - found
    -- Looking for recvfrom
    -- Looking for recvfrom - found
    -- Looking for send
    -- Looking for send - found
    -- Looking for setsockopt
    -- Looking for setsockopt - found
    -- Looking for socket
    -- Looking for socket - found
    -- Looking for strcasecmp
    -- Looking for strcasecmp - found
    -- Looking for strcmpi
    -- Looking for strcmpi - not found
    -- Looking for strdup
    -- Looking for strdup - found
    -- Looking for stricmp
    -- Looking for stricmp - not found
    -- Looking for strncasecmp
    -- Looking for strncasecmp - found
    -- Looking for strncmpi
    -- Looking for strncmpi - not found
    -- Looking for strnicmp
    -- Looking for strnicmp - not found
    -- Looking for writev
    -- Looking for writev - found
    -- Found Perl: /usr/bin/perl (found version "5.16.3") 
    -- The ASM compiler identification is GNU
    -- Found assembler: /usr/local/bin/cc
    -- Configuring done
    -- Generating done
    -- Build files have been written to: .../target/debug/build/grpcio-sys-f45f9c164b4a8726/out/build
    
    --- stderr
    CMake Warning at cmake/protobuf.cmake:48 (message):
      gRPC_PROTOBUF_PROVIDER is "module" but PROTOBUF_ROOT_DIR is wrong
    Call Stack (most recent call first):
      CMakeLists.txt:140 (include)
    
    
    CMake Warning at cmake/gflags.cmake:26 (message):
      gRPC_GFLAGS_PROVIDER is "module" but GFLAGS_ROOT_DIR is wrong
    Call Stack (most recent call first):
      CMakeLists.txt:142 (include)
    
    
    CMake Warning at cmake/benchmark.cmake:26 (message):
      gRPC_BENCHMARK_PROVIDER is "module" but BENCHMARK_ROOT_DIR is wrong
    Call Stack (most recent call first):
      CMakeLists.txt:143 (include)
    
    
    CMake Error at CMakeLists.txt:738 (target_compile_options):
      Error evaluating generator expression:
    
        $<COMPILE_LANGUAGE:CXX>
    
      Expression did not evaluate to a known generator expression
    
    
    CMake Error at CMakeLists.txt:6171 (target_compile_options):
      Error evaluating generator expression:
    
        $<COMPILE_LANGUAGE:CXX>
    
      Expression did not evaluate to a known generator expression
    ....
    thread 'main' panicked at '
    command did not execute successfully, got: exit code: 1
    
    build script failed, must exit now', /opt/rust/registry/src/github.com-1ecc6299db9ec823/cmake-0.1.35/src/lib.rs:778:5
    note: Run with `RUST_BACKTRACE=1` for a backtrace.
    
    warning: build failed, waiting for other jobs to finish...
    error: failed to verify package tarball
    
    Caused by:
      build failed
    

    Expected behavior

    grpc-sys to build successfully.

    System information

    • CPU architecture: x86-64
    • Distribution and kernel version: CentOS 7 under Docker on Core OS.
    • SELinux on?:
    • Any other system details we should know?:

    Additional context Add any other context about the problem here.

    Build 
    Reply
  • grpc-sys: add submodule, now static link
    grpc-sys: add submodule, now static link

    Apr 25, 2017

    Fix #2

                                                                                                                                                                                                           
    Reply
  • Zero copy for send
    Zero copy for send

    Oct 9, 2018

    TODOs

    • [X] Fix benchmark compilation
    • [x] Fix link error (multiple symbol definitions)
    • [x] Fix size_t 6 in Rust becomes size_t in C 140184721559552 via FFI (140184721559552+6 is 2^47)
    • [x] Sync master changes
    • [x] Improve GrpcSlice
    • [x] Improve GrpcByteBuffer
    • [x] (New!) Support bytes in prost

    Now (updated at: 23, April 2019)

    Since @nrc has introduced prost support (instead of rust-protobuf) which is natively using "bytes", we no longer have that one copy for send which is stated to be necessary below. Yay!

    Before:

    • User code deserialize (particularly, the protobuf library), producing a list of &[u8], we copied the data into a Vec<u8>, this is done internally in the protobuf library (copy 0)
    • We create a grpc_slice (a ref-counted single string) by copying the Vec<u8> mentioned above (copy 1)
    • We create a grpc_byte_buffer (a ref-counted list of strings) from only one grpc_slice
    • Send

    Total copy: 2

    After:

    • User code deserialize (particularly, the protobuf library), producing a list of &[u8], we copied each produced &[u8] and collect them into a grpc_byte_buffer (copy 0)
    • Send

    Total copy: 1

    The reason why still one copy:

    • Rust manages its own allocated memory'a lifetime
    • C-side uses a ref-count mechanism to manage the lifetime of objects
    • We either need to longer the Rust objects' lifetime or copy once
    • Tried to longer Rust objects' lifetime in #225
      • Result: grpc supports buffer-hint which requires a much longer lifetime, it's too hard to manage the lifetime in such case
      • This is why I closed #225
    Enhancement 
    Reply
  • Linking fails against libssl on OS X
    Linking fails against libssl on OS X

    Jun 12, 2019

    Describe the bug I found this originally on another project, but I can reproduce the same thing against the grpc-rs repo. The final step of cargo build fails with a linker error:

    [...]
      = note: ld: warning: directory not found for option '-L/Users/habnabit/Projects/20181023-activity-aggregator/grpc-rs/target/debug/build/grpcio-sys-88e0b97a2cd094d1/out/build/third_party/boringssl/ssl'
              ld: warning: directory not found for option '-L/Users/habnabit/Projects/20181023-activity-aggregator/grpc-rs/target/debug/build/grpcio-sys-88e0b97a2cd094d1/out/build/third_party/boringssl/crypto'
              ld: library not found for -lssl
              clang: error: linker command failed with exit code 1 (use -v to see invocation)
    

    Full output here: https://gist.github.com/habnabit/1b9a0cf0d0454db3ee98e7bb46f40624

    To Reproduce On a clean grpc-rs checkout:

    $ git checkout v0.4.4
    $ git submodule update --init --recursive
    $ OPENSSL_ROOT_DIR=/usr/local/opt/openssl cargo build --features openssl --examples
    

    Expected behavior Presumably this build should succeed. I don't think I have a broken openssl.

    System information macOS 10.14.5; homebrew openssl.

    $ cargo version
    cargo 1.35.0 (6f3e9c367 2019-04-04)
    $ rustc --version
    rustc 1.35.0 (3c235d560 2019-05-20)
    $ ls -ld /usr/local/opt/openssl
    lrwxr-xr-x  1 habnabit  admin  24 May 31 20:26 /usr/local/opt/openssl -> ../Cellar/openssl/1.0.2r
    
    Reply
  • travis: add notification hook
    travis: add notification hook

    Jun 8, 2017

                                                                                                                                                                                                           
    Reply
  • Zero copy for receive
    Zero copy for receive

    Aug 25, 2018

    This is not ready to merge yet, but I'm opening this PR so we can discuss changes related to #134 .

    Enhancement 
    Reply