September 9, 2019

building a gRPC application (part 7)

This is part 7 on a simple gRPC tutorial. In this post, we will package each microservice in a container, and perform a local test using Docker compose.

In general, we don’t want to run such services by opening individual terminal windows. The advantages of gRPC become more relevant if we package services in a containerization framework like Docker or Kubernetes, allowing us to isolate a consistent runtime.

Create a Dockerfile for our Ruby code:

FROM ruby:2.5

RUN gem install bundler

COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock

RUN bundle install

COPY .pryrc .pryrc
COPY bin bin
COPY lib lib

ENTRYPOINT [ "bundle", "exec" ]

and for basic testing, create a docker-compose.yaml file to launch the client and server environments:

version: '3'
services:
  ruby_client:
    image: 'jprime/guided-demo:ruby'
    build:
      context: src/ruby
    command: pry
  ruby_friendly_server:
    image: 'jprime/guided-demo:ruby'
    build:
      context: src/ruby
    command: bin/friendly

We can run the build and launch the services with one command: docker-compose up -d

Now, connect to the test container:

docker attach guided-demo_ruby_client
pry(main)> friendly.acknowledge alice
=> <UserAcknowledgement: user: <UserInformation: username: "steve">, message: "Hello alice!">
pry(main)> friendly.acknowledge steve
=> <UserAcknowledgement: user: <UserInformation: username: "steve">, message: "Hello steve!">

Things get more interesting when we add different service implementations. For instance, create a “nasty” implementation:

require './lib/user_services_pb'

module Demo
  class Nasty < UserActivity::Service
    def acknowledge(user_information, _extra)
      UserAcknowledgement.new(
        user: user_information,
        message: "Who are you looking at, #{user_information.username}?"
      )
    end
  end
end

and a script to run it:

#!/usr/bin/env ruby

require 'grpc'
require './lib/demo/nasty'

server = GRPC::RpcServer.new
server.add_http2_port('0.0.0.0:50051', :this_port_is_insecure)
server.handle(Demo::Nasty)
server.run_till_terminated

Basically everything is the same execpt the class defining the business logic. Add the nasty service to the docker-compose:

version: '3'
services:
  ruby_client:
    image: 'jprime/guided-demo:ruby'
    build:
      context: src/ruby
    command: pry
    links:
      - ruby_friendly_server:friendly.svc
      - ruby_nasty_server:nasty.svc
  ruby_friendly_server:
    image: 'jprime/guided-demo:ruby'
    build:
      context: src/ruby
    command: bin/friendly
  ruby_nasty_server:
    image: 'jprime/guided-demo:ruby'
    build:
      context: src/ruby
    command: bin/nasty

and a quick client to the .pryrc

nasty = UserActivity::Stub.new('nasty.svc:50051', :this_channel_is_insecure)

And you can test as before.

Content by © Jared Davis 2019
Theme by © Emir Ribic 2017

Powered by Hugo & Kiss.