Let's try gRPC with Go and Docker

** * This article was created on November 7, 2019 Let's try gRPC with Go and Docker --LiBz Tech Blog Is the same as **

Introduction

Hello! I'm Watanabe, an engineer. It's been a full year since I joined LiB in November. This is my fourth post on this blog.

In the previous "Story of introducing a very Rails-like serverless framework" Ruby on Jets "to the production environment" , Jets developer ** tongueroo ** and Ruby creator ** Yukihiro Matsumoto It was very encouraging to have many people share it, including **! Thank you everyone.

This time I will write about the RPC framework ** gRPC ** developed by Google.

20191106144030.jpg

What is gRPC?

It is an open source version of the RPC (Remote Procedure Call) framework called stubby used within Google.

Features of gRPC

-** High-speed, low-dose, type-guaranteed communication between different languages using Protocol Buffers ** (interface description languages like xml, json) --For server / client ** Automatic source code generation ** --Multi-language support (C ++, Java, Go, Python, Ruby, Node.js, C #, Objective-C, PHP, etc ..) --Communication protocol ** Communication by HTTP / 2 ** --Bidirectional communication using Streaming (conventional communication is 1Request-1Response)

Due to the above features, ** gRPC can solve the problems of connection and data transfer between microserviced systems, and can communicate efficiently **.

20191106164527.png

Microservices challenges solved by gRPC

--The interface needs to be unified among multiple systems

--Systems change frequently, making it difficult to ensure consistency across all systems

**-> Server / client source code can be automatically generated from Protocol Buffer (.proto file), and multiple languages can be selected **

--Documents for understanding the specifications of multiple systems (specifications, wiki, Swagger, etc ..) Update omissions, description errors

**-> Communication between services is generated from the proto file, so the proto file has the correct specifications (the source code is generated based on the proto file, so no omissions or mistakes occur) **

--Performance tends to deteriorate due to frequent API requests

**-> HTTP / 2 can handle multiple requests and responses with one TCP connection **

--In HTTP / 1, only one resource can be acquired with one connection (the number of connections is limited even if multiple TCPs are pasted at the same time on the browser side).

**-> Because of HTTP / 2 communication, you can continue to use the connection at the time of the first connection without discarding the connection **

20191106164702.png

gRPC challenges

Of course, there are not only advantages but also disadvantages. The fact that the communication standard is HTTP / 2 means that ** browsers and load balancers that do not support it cannot receive requests **.

For browsers, reverse proxies such as grpc-gateway and grpc-web There is no problem if you use a library that does Inter-service communication is the HTTP2 protocol, and only browser-server communication is the HTTP1 protocol, so some people may feel uncomfortable with the mixture.

Checking the operation of the gRPC server is also a little troublesome. You can check the operation like the conventional API with curl, but you can not use curl with gRPC. (Recently, you can check the operation of gRPC like curl gRPCurl and gRPC UI which is a GUI client for gRPC. hinastory / items / 131cb603af34e3235ccf) There seems to be a tool)

20190711145732.png

Let's try gRPC

Introduction to gRPC starting with Go Try gRPC with Golang

20191106164848.png

1. Preparation

Install the above three.

gRPC

$ go get -u google.golang.org/grpc

protoc

It depends on the OS. Please install from here.

protoc-gen-go

$ go get -u github.com/golang/protobuf/protoc-gen-go

Dockerfile

Since we will use Docker this time, we will also prepare Dockerfile and docker-compose.yml.

FROM golang:1.13.1  
  
RUN apt-get update && apt-get install -y unzip  
  
# Install protobuf  
# @see https://github.com/yoshi42662/go-grpc/blob/master/server/Dockerfile  
RUN mkdir -p /tmp/protoc && \  
  curl -L https://github.com/protocolbuffers/protobuf/releases/download/v3.10.0/protoc-3.10.0-linux-x86_64.zip > /tmp/protoc/protoc.zip && \  
  cd /tmp/protoc && \  
  unzip protoc.zip && \  
  cp /tmp/protoc/bin/protoc /usr/local/bin && \  
  chmod go+rx /usr/local/bin/protoc && \  
  cd /tmp && \  
  rm -r /tmp/protoc  
  
WORKDIR /study-grpc  
COPY . /study-grpc  
  
RUN go get -u google.golang.org/grpc  
RUN go get -u github.com/golang/protobuf/protoc-gen-go

docker-compose.yml

For the time being, it's good if the container is running, so I set it to command: bash

docker-compose.yml


version: '3.7'  
  
services:  
  study-grpc:  
    build: .  
    container_name: "study-grpc"  
	ports:  
      - 1234:1234  
    volumes:  
      - .:/study-grpc  
	command: bash
	tty: true

2. Create proto file

Define the interface in the proto file and generate the code. I have created pb / cat.proto.

syntax = "proto3";  
  
service Cat {  
    rpc GetMyCat (GetMyCatMessage) returns (MyCatResponse) {}  
}  
  
message GetMyCatMessage {  
    string target_cat = 1;  
}  
  
message MyCatResponse {  
    string name = 1;  
    string kind = 2;  
}

Note that if you forget to write syntax =" proto3 ", it will be interpreted as proto2. gRPC generally uses proto3. The difference between proto2 and proto3 is here The article was easy to understand.

The number part of string name = 1 is the tag number. The tag number is used to distinguish the fields. It is said that once the number is assigned, it is better not to change it, so if there is a change, a new number will be assigned.

Then go inside the container and compile the proto file to generate the source code.

#Container startup
$ docker-compose up

#Go inside the container
$ docker exec -it study-grpc bash

#protoc command execution
$ protoc --go_out=plugins=grpc:. ./pb/cat.proto

It is OK if pb / cat.pb.go is generated.

3. Processing on the server side

Create server.go.

package main  
  
import (  
	"context"  
	"errors"
	"google.golang.org/grpc"
	"log"
	"net"
	cat "study-grpc/pb"  
)  
  
type myCatService struct{}  
  
func (s *myCatService) GetMyCat(ctx context.Context, message *cat.GetMyCatMessage) (*cat.MyCatResponse, error) {  
	switch message.TargetCat {  
	case "tama":  
		return &cat.MyCatResponse{  
			Name: "tama",  
			Kind: "Maine Coon",  
		}, nil  
	case "mike":  
		return &cat.MyCatResponse{  
			Name: "mike",  
			Kind: "Norwegian Forest Cat",  
		}, nil  
	default:  
		return nil, errors.New("Not Found YourCat..")  
	}  
}  
  
func main() {  
	port, err := net.Listen("tcp", ":1234")  
	if err != nil {  
		log.Println(err.Error())  
		return  
	}
	s := grpc.NewServer()  
	cat.RegisterCatServer(s, &myCatService{})  
	s.Serve(port)  
}

4. Client side (request) processing

Create client.go.

package main  
  
import (  
	"context"  
	"fmt"
	"google.golang.org/grpc"
	"log"
	cat "study-grpc/pb"  
)  
  
func main() {  
	conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure())  
	if err != nil {  
		log.Fatal("connection error:", err)  
	}  
	defer conn.Close()  
  
	client := cat.NewCatClient(conn)  
	message := &cat.GetMyCatMessage{TargetCat: "mike"}  
	res, err := client.GetMyCat(context.Background(), message)  
	if err != nil {  
		log.Fatal(err)  
	}  
	fmt.Printf("result:%s\n", res)  
}

5. Build and run

Let's build and execute the created server.go and client.go.

#Go inside the container
$ docker exec -it study-grpc bash

# server.build go&Run
$ go build server.go
$ ./server

# client.build go&Run
$ go build client.go
$ ./client

#If it is troublesome to build, go run is ok
$ go run server.go
$ go run client.go

Execution result

result:name:"mike" kind:"Norwegian Forest Cat"

Finally

What did you think?

Just hearing the name makes me think "gRPC? ProtocolBuffer? It seems difficult," but I think it was easier than I had imagined when I actually moved my hand.

It has a track record of being adopted not only by Google but also by a number of major companies, and the number of cases in Japanese companies is steadily increasing.

20191106171413.png

There are many challenges to microservices, but gRPC, which solves the communication part, is one of the options, and I definitely want to remember it.

The code used this time is summarized in this repository.

Recommended Posts

Let's try gRPC with Go and Docker
Hello World with gRPC / go in Docker environment
GRPC starting with Go server and Dart client
Try implementing perfume with Go
Try Selenium Grid with Docker
Try building JupyterHub with Docker
Easy Slackbot with Docker and Errbot
Authentication process with gRPC and Firebase Authentication
HTTPS with Django and Let's Encrypt
Communicate between Elixir and Python with gRPC
Try using Dropbox API v2 with Go
Let's scrape a dynamic site with Docker
Try using S3 object upload and download with AWS SDK for Go v2
Python with Go
Try running Google Chrome with Python and Selenium
Go (Echo) Go Modules × Build development environment with Docker
Try to communicate with EV3 and PC! (MQTT)
Compare xml parsing speeds with Python and Go
[Python3] [Ubuntu16] [Docker] Try face recognition with OpenFace
Let's control EV3 motors and sensors with Python
Build PyPy and Python execution environment with Docker
Let's try analysis! Chapter 8: Analysis environment for Windows created with Python and Eclipse (PyDev)
Let's transpose the matrix with numpy and multiply the matrices.
Try making a simple website with responder and sqlite3
Install selenium on Mac and try it with python
Try to operate DB with Python and visualize with d3
Let's make a simple game with Python 3 and iPhone
How to share folders with Docker and Windows with tensorflow
Now, let's try face recognition with Chainer (prediction phase)
Let's make a Mac app with Tkinter and py2app
Easy face recognition try with Jetson Nano and webcam
Now, let's try face recognition with Chainer (learning phase)
[Linux] Create a self-signed certificate with Docker and apache
Tftp server with Docker
goland and Docker settings
GRPC starting with Python
Try gRPC in Python
Use python with docker
Try SNN with BindsNET
Proxy server with Docker
Hello, World with Docker
Try regression with TensorFlow
With and without WSGI
[Machine learning] Start Spark with iPython Notebook and try MLlib
Try hitting the Twitter API quickly and easily with Python
Try Amazon Simple Workflow Service (SWF) with Python and boto3
Let's create a PRML diagram with Python, Numpy and matplotlib.
Try to link iTunes and Hue collection case with MQTT
Try to bring up a subwindow with PyQt5 and Python
Try MD simulation with ANN potential using aenet and ASE
[Let's play with Python] Image processing to monochrome and dots
Package python runtime and pypi library with chef / omnibus and Docker
Build GPU environment with GCP and kaggle official image (docker)
Let's move word2vec with Chainer and see the learning progress