
Now in the world of microservice, came across the usage of gRPC instead of REST way to get the advantage of RPC framework simplicity and fast interaction across the network. gRPC is an open-source RPC framework maintained and developed by Google.
So let's start exploring it. We need to define “.proto” file and use the generator function which generated the Interface to be used in the client and the server.
Here, for example, I will be developing two services 1. ItemService and 2. ListService and last but not least the client 3. Website. In total 4 steps and you are done.
- The starting point is always a proto file. Here we will define a simple function to get_items and get_lists.
item.proto
# ./protos/item.protosyntax = "proto3";service ItemService {rpc GetItems(Item) returns(Item) {}}message Item {
string title = 1;
}
list.proto
# ./protos/list.protosyntax = "proto3";service ListService {rpc GetLists(List) returns(List) {}}message List {
string title = 1;
}
2. Generate service and proto buff files using the generator.
grpc_tools_ruby_protoc -I ./protos --ruby_out=lib --grpc_out=lib ./protos/list.protogrpc_tools_ruby_protoc -I ./protos --ruby_out=lib --grpc_out=lib ./protos/item.proto
Now respective services file will get generated. Thanks to google.
3. Creating server:
a. ItemServer:
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)require 'grpc'
require 'item_services_pb'include ItemServiceclass ItemServer < ItemService::Servicedef get_items(item_req, _unused_call)
Item.new(title: "wassup")
endenddef main
s = GRPC::RpcServer.new
s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure)
s.handle(ItemServer)
s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT'])
endmain
b. ListServer:
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)require 'grpc'
require 'list_services_pb'include ListServiceclass ListServer < ListService::Servicedef get_lists(list_req, _unused_call)
List.new(title: "wassup")
endenddef main
s = GRPC::RpcServer.new
s.add_http2_port('0.0.0.0:50052', :this_port_is_insecure)
s.handle(ListServer)
s.run_till_terminated_or_interrupted([1, 'int', 'SIGQUIT'])
endmain
I hope it is self-explanatory. We are creating a server instance GRPC:: RpcServer.new and that particular instance handle that particular service calls from clients.
Now that the server is created for both the service. What is left is creating a client to actually make use of the function call on the server.
4. Creating Client:
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)require 'grpc'
require 'item_services_pb'
require 'list_services_pb'def main
begin
list_stub = ListService::Stub.new('localhost:50052', :this_channel_is_insecure)
list = list_stub.get_lists( List.new(title: "list_title") )
p "List: #{ list.title}"item_stub = ItemService::Stub.new('localhost:50051', :this_channel_is_insecure)
item = item_stub.get_items( Item.new(title: "item_title") )
p "Item: #{ item.title }"
rescue Exception => e
p e
end
endmain
Even this is clear, we are creating an instance of each service and calling its function. Though we are not doing any great use of it. This is just a demonstration of the server and client interaction.
Now let's try it out. Open three terminals and start below:
Terminal 1:
ruby item_server.rb
Terminal 2:
ruby list_server.rb
Terminal 3:
ruby website.rb
Output:
List: wassup
Item: wassup
Here it goes. The topic of this blog is covered. It still a vague article considering not mentioning anything about grpc or why grpc. I would make another article for this. But for now, this is a PoC code for trying out a grpc. Git hub code for the same is in here. Hope this is helpful.