simple_rpc

Build Status

RPC Server and Client for Crystal. Implements msgpack-rpc protocol. Designed to be reliable and stable (catch every possible protocol/socket errors). It also quite fast: benchmark performs at 160Krps for single server process and single clients process (in pool mode).

Installation

Add this to your application's shard.yml:

dependencies:
  simple_rpc:
    github: kostya/simple_rpc

Usage

Server example

To create RPC server from your class/struct, just include SimpleRpc::Proto, it adds MyRpc::Server class and also expose all public methods to the external rpc calls. Each method should define type for each argument and also return type. Types of arguments should supports MessagePack::Serializable (by default it supported by most common language types, including Unions). Instance of MyRpc created for each rpc call, so you should not use instance variables for between-request interaction.

require "simple_rpc"

struct MyRpc
  include SimpleRpc::Proto

  def sum(x1 : Int32, x2 : Float64) : Float64
    x1 + x2
  end

  record Greeting, rand : Float64, msg : String { include MessagePack::Serializable }

  def greeting(name : String) : Greeting
    Greeting.new(rand, "Hello from Crystal #{name}")
  end
end

puts "Server listen on 9000 port"
MyRpc::Server.new("127.0.0.1", 9000).run

Client example

Client simple method to use is: .request!(return_type, method_name, *args). This call can raise SimpleRpc::Errors. If you not care about return type use can use MessagePack::Any (in example below, you also can use Greeting record instead if you share that declaration). If you dont want to raise on errors you can use similar method request and process result manually.

require "simple_rpc"

client = SimpleRpc::Client.new("127.0.0.1", 9000)

p client.request!(Float64, :sum, 3, 5.5)
# => 8.5
p client.request!(MessagePack::Any, :greeting, "Vasya")
# => {"rand" => 0.7839463879734746, "msg" => "Hello from Crystal Vasya"}

MsgpackRPC is multi-language RPC, so you can call it, for example, from Ruby

# gem install msgpack-rpc
require 'msgpack/rpc'

client = MessagePack::RPC::Client.new('127.0.0.1', 9000)
p client.call(:sum, 3, 5.5)
# => 8.5
p client.call(:greeting, "Vasya")
# => {"rand"=>0.47593728045415334, "msg"=>"Hello from Crystal Vasya"}

Client modes

SimpleRpc::Client can work in multiple modes, you can choose it by argument mode:

Example of client, which can handle 50 concurrent requests, and can be used in multifiber environment:

client = SimpleRpc::Client.new("127.0.0.1", 9000, mode: :pool, pool_size: 50, pool_timeout: 1.0)