hotch-potch, Note to self

いろいろ作業記録

チュートリアル チャレンジ・gRPC on Elixir

1.はじめに

最近興味を持っているgRPCをElixirでも試してみました。

所々ハマリどころがあったので、備忘録としてまとめます。

試行環境

ハード Raspberry Pi 3 B+
OS Ubuntu Server 20.04 LTS

2.下準備

(1)protocol bufferのインストール

gRPCの*.protoファイルを解釈するのに必要なツールをインストールします。

$ sudo apt-get install libprotobuf-dev libprotoc-dev protobuf-compiler -y
$ protoc --version
libprotoc 3.6.1
$

(2)protobuf-elixirのインストール

こちらの内容に従ってインストールします。

GitHub - tony612/protobuf-elixir: A pure Elixir implementation of Google Protobuf

$ git clone https://github.com/tony612/protobuf-elixir.git
$ cd protobuf-elixir
$ mix escript.install hex protobuf

elixirで生成した実行ファイルは~/.mix/escriptsにインストールされます。このディレクトリにパスを通します。

$ nano ~/.bashrc
bashrc
(・・・省略・・・)
# for escript
export PATH="$PATH:$HOME/.mix/escripts"
$ . ~/.bashrc
$ echo $PATH
/home/ubuntu/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/ubuntu/.mix/escripts
$ protoc-gen-elixir --version
0.7.1
使い方

カレントディレクトリのprotoファイルを解釈して、./libディレクトリに出力します。

$ protoc --elixir_out=./lib helloworld.proto

3.gRPC Elixirのサンプルを実行

こちらの内容に従ってチュートリアルを進めます。

GitHub - elixir-grpc/grpc: An Elixir implementation of gRPC

ライブラリの依存関係の処理の途中で聴かれるShall I install rebar3? (if running non-interactively, use "mix local.rebar --force") [Yn]は、"y"を回答します。

$ git clone https://github.com/elixir-grpc/grpc.git
$ cd ./grpc/examples/helloworld/
$ mix do deps.get, compile
* Getting protobuf (https://github.com/tony612/protobuf-elixir.git)
remote: Enumerating objects: 2002, done.
remote: Total 2002 (delta 0), reused 0 (delta 0), pack-reused 2002
Receiving objects: 100% (2002/2002), 428.11 KiB | 598.00 KiB/s, done.
Resolving deltas: 100% (1240/1240), done.
Resolving Hex dependencies...
Dependency resolution completed:
Unchanged:
  cowboy 2.7.0
  dialyxir 0.5.1
  grpc_cowlib 2.8.1
  grpc_gun 2.0.0
  ranch 1.7.1
* Getting cowlib (Hex package)
* Getting dialyxir (Hex package)
* Getting cowboy (Hex package)
* Getting gun (Hex package)
* Getting ranch (Hex package)
==> protobuf
Compiling 21 files (.ex)
Generated protobuf app
==> helloworld
Could not find "rebar3", which is needed to build dependency :ranch
I can install a local copy which is just used by Mix
Shall I install rebar3? (if running non-interactively, use "mix local.rebar --force") [Yn]
* creating /home/pi/.mix/rebar
(・・・省略・・・)
==> helloworld
Compiling 4 files (.ex)
Generated helloworld app

コンソールをもう一つ開いて、サーバ・クライアントのやりとりを試します。

コンソール1:サーバ

実行したあと、クライアントから要求があると、それに合わせてメッセージを出力します。

$ pwd
...../grpc/examples/helloworld
$ mix grpc.server
09:58:22.257 [warn]  cowlib should be >= 2.9.0, it's 2.8.1 now. See grpc's README for details
09:58:22.360 [info]  Running Helloworld.Endpoint with Cowboy using http://0.0.0.0:50051
09:58:48.344 [info]  Handled by Helloworld.Greeter.Server.say_hello
09:58:48.350 [info]  Response :ok in 5ms
10:05:26.091 [info]  Handled by Helloworld.Greeter.Server.say_hello
10:05:26.091 [info]  Response :ok in 11µs

コンソール2:クライアント

その1・iexから操作する例です。
$ pwd
...../grpc/examples/helloworld
$ iex -S mix
Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]

09:58:29.651 [warn]  cowlib should be >= 2.9.0, it's 2.8.1 now. See grpc's README for details
Interactive Elixir (1.9.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, channel} = GRPC.Stub.connect("localhost:50051")
{:ok,
 %GRPC.Channel{
   accepted_compressors: [],
   adapter: GRPC.Adapter.Gun,
   adapter_payload: %{conn_pid: #PID<0.228.0>},
   codec: GRPC.Codec.Proto,
   compressor: nil,
   cred: nil,
   headers: [],
   host: "localhost", 
   interceptors: [],
   port: 50051,
   scheme: "http"
 }}

iex(2)> request = Helloworld.HelloRequest.new(name: "grpc-elixir")
%Helloworld.HelloRequest{name: "grpc-elixir"}

iex(3)> {:ok, reply} = channel |> Helloworld.Greeter.Stub.say_hello(request)
{:ok, %Helloworld.HelloReply{message: "Hello grpc-elixir"}}

iex(4)> {:ok, channel} = GRPC.Stub.connect("localhost:50051", interceptors: [GRPC.Logger.Client])
{:ok,
 %GRPC.Channel{
   accepted_compressors: [],
   adapter: GRPC.Adapter.Gun,
   adapter_payload: %{conn_pid: #PID<0.234.0>},
   codec: GRPC.Codec.Proto,
   compressor: nil,
   cred: nil,
   headers: [],
   host: "localhost", 
   interceptors: [{GRPC.Logger.Client, :info}],
   port: 50051,
   scheme: "http"
 }}

iexのプロンプトを抜けるときは、[Ctrl-\]を押すか、コマンドラインからiex> System.haltを入力します。

その2・コマンドラインからクライアントスクリプトを実行する例です。
$ pwd
...../grpc/examples/helloworld
$ mix run priv/client.exs
10:05:25.904 [warn]  cowlib should be >= 2.9.0, it's 2.8.1 now. See grpc's README for details
10:05:26.046 [info]  Call say_hello of helloworld.Greeter
10:05:26.157 [info]  Got :ok in 77ms
%Helloworld.HelloReply{message: "Hello grpc-elixir"}

補足:実行時にcould not find application file: xmerl.appが発生

Elixirをaptパッケージで入れると、一部不足するパッケージが出てくるので、必要に応じてパッケージを追加する必要があります。

could not find application file: xmerl.appの場合は、下記のパッケージを追加します。

$ sudo apt-get install erlang-xmerl

4.参考