An Elixir implementation of gRPC.
The package can be installed as:
def deps do
[
{:grpc, "~> 0.9"}
]
end
syntax = "proto3";
package helloworld;
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greeting
message HelloReply {
string message = 1;
}
// The greeting service definition.
service Greeter {
// Greeting function
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
gRPC Support
section) or using protobuf_generate hex package. Example using protobuf_generate
lib:mix protobuf.generate --output-path=./lib --include-path=./priv/protos helloworld.proto
In the following sections you will see how to implement gRPC server logic.
defmodule Helloworld.Greeter.Server do
use GRPC.Server, service: Helloworld.Greeter.Service
@spec say_hello(Helloworld.HelloRequest.t, GRPC.Server.Stream.t) :: Helloworld.HelloReply.t
def say_hello(request, _stream) do
Helloworld.HelloReply.new(message: "Hello #{request.name}")
end
end
# Define your endpoint
defmodule Helloworld.Endpoint do
use GRPC.Endpoint
intercept GRPC.Server.Interceptors.Logger
run Helloworld.Greeter.Server
end
We will use this module in the gRPC server startup section.
Note: For other types of RPC call like streams see here.
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/v1/greeter/{name}"
};
}
rpc SayHelloFrom (HelloRequestFrom) returns (HelloReply) {
option (google.api.http) = {
post: "/v1/greeter"
body: "*"
};
}
}
In mix.exs:
def deps do
[
{:grpc, "~> 0.7"},
{:protobuf_generate, "~> 0.1.1"}
]
end
And in your terminal:
mix protobuf.generate \
--include-path=priv/proto \
--include-path=deps/googleapis \
--generate-descriptors=true \
--output-path=./lib \
--plugins=ProtobufGenerate.Plugins.GRPCWithOptions \
google/api/annotations.proto google/api/http.proto helloworld.proto
Enable http_transcode option in your Server module
defmodule Helloworld.Greeter.Server do
use GRPC.Server,
service: Helloworld.Greeter.Service,
http_transcode: true
@spec say_hello(Helloworld.HelloRequest.t, GRPC.Server.Stream.t) :: Helloworld.HelloReply.t
def say_hello(request, _stream) do
%Helloworld.HelloReply{message: "Hello #{request.name}"}
end
end
See full application code in helloworld_transcoding example.
# In the start function of your Application
defmodule HelloworldApp do
use Application
def start(_type, _args) do
children = [
# ...
{GRPC.Server.Supervisor, endpoint: Helloworld.Endpoint, port: 50051, start_server: true}
]
opts = [strategy: :one_for_one, name: YourApp]
Supervisor.start_link(children, opts)
end
end
iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051")
iex> request = Helloworld.HelloRequest.new(name: "grpc-elixir")
iex> {:ok, reply} = channel |> Helloworld.Greeter.Stub.say_hello(request)
# With interceptors
iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051", interceptors: [GRPC.Client.Interceptors.Logger])
...
Check the examples and interop directories in the project's source code for some examples.
The default adapter used by GRPC.Stub.connect/2
is GRPC.Client.Adapter.Gun
. Another option is to use GRPC.Client.Adapters.Mint
instead, like so:
GRPC.Stub.connect("localhost:50051",
# Use Mint adapter instead of default Gun
adapter: GRPC.Client.Adapters.Mint
)
The GRPC.Client.Adapters.Mint
adapter accepts custom configuration. To do so, you can configure it from your mix application via:
# File: your application's config file.
config :grpc, GRPC.Client.Adapters.Mint, custom_opts
The accepted options for configuration are the ones listed on Mint.HTTP.connect/4
GRPC.Endpoint
)Simple benchmark by using ghz
Benchmark followed by official spec
Your contributions are welcome!
Please open issues if you have questions, problems and ideas. You can create pull requests directly if you want to fix little bugs, add small features and so on. But you'd better use issues first if you want to add a big feature or change a lot of code.