Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

ikkyu
ikkyu

Posted on

     

Using gRPC and gRPC-Web with a Golang

Set Up

The final directory structure will look like this.

 go  |_prj     |_gRPC_prjweb_tmp          |-api.proto          |-client          |  |_client.go          |-docker-compose.yaml          |-go.mod          |-go.sum          |-html          |  |-dist          |  |  |_main.js          |  |-index.html          |  |_index.js          |-Makefile          |-pb          |  |-api_grpc_web_pb.js          |  |-api.pb.go          |  |-api_pb.js          |  |-node_modeles          |  |-package.json          |  |_package-lock.json          |-proxy          |  |-conf          |  |  |_envoy.yaml          |  |_Dockerfile          |_server             |_server.go
Enter fullscreen modeExit fullscreen mode

And network structure will look like this.

gRPC_web(4444)<-->envoy(8080)<-->gRPC_server(8000)
Enter fullscreen modeExit fullscreen mode

First, build the environment.

go mod init web_tmpgo get google.golang.org/protobuf github.com/sirupsen/logrus golang.org/x/net/context google.golang.org/grpc google.golang.org/grpc/codes google.golang.org/grpc/status
Enter fullscreen modeExit fullscreen mode

gRPC

Create a proto file.
[api.proto]

syntax = "proto3";service Greeter {  rpc Hello (HelloRequest) returns (HelloReply) {}}message HelloRequest {  string name = 1;}message HelloReply {  string message = 1;}
Enter fullscreen modeExit fullscreen mode

Create a pb directory, and generate Protocol Buffers code from api.proto file.

mkdir pbprotoc --go_out=plugins=grpc:pb api.proto
Enter fullscreen modeExit fullscreen mode

Create a server directory and a client directory.

mkdir servermkdir client
Enter fullscreen modeExit fullscreen mode

Then we'll write the server and client code.
[sever/server.go]

package mainimport (    "fmt"    pb "web_tmp/pb"    "net"    "github.com/sirupsen/logrus"    "gINFO[0000] Greeting: Hello lupinolang.org/x/net/context"    "google.golang.org/grpc")func main() {    listener, err := net.Listen("tcp", ":8000")    if err != nil {            panic(err)    }    server := grpc.NewServer()    greeterService := &GreeterService{}    pb.RegisterGreeterServer(server, greeterService)    logrus.Info(fmt.Sprintf("start server: %#v", listener.Addr().String()))    server.Serve(listener)}type GreeterService struct {}func (s *GreeterService) Hello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {        return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil}
Enter fullscreen modeExit fullscreen mode

[client/client.go]

package mainimport (    "context"    pb "web_tmp/pb"    "github.com/sirupsen/logrus"    "google.golang.org/grpc")func main() {    conn, err := grpc.Dial("localhost:8000", grpc.WithInsecure())    if err != nil {            panic(err)    }    defer conn.Close()    c := pb.NewGreeterClient(conn)    name := &pb.HelloRequest{Name: "lupin"}     r, err := c.Hello(context.TODO(), name)    if err != nil {        logrus.Error(err)    }    logrus.Info("Greeting: ", r.GetMessage())}
Enter fullscreen modeExit fullscreen mode

Create a makefile.
[Makefile]

.PHONY: server clientserver:        go run ./server/server.goclient:         go run ./client/client.go
Enter fullscreen modeExit fullscreen mode

Start the server.

make server
Enter fullscreen modeExit fullscreen mode

Run the client code.

make client
Enter fullscreen modeExit fullscreen mode

We can see the gRPC server returning "Hello lupin".

INFO[0000] Greeting: Hello lupin
Enter fullscreen modeExit fullscreen mode

gRPC-web

Next, we'll write the code for gRPC-web communication.

protoc --js_out=import_style=commonjs:pb --grpc-web_out=import_style=commonjs,mode=grpcwebtext:pb api.proto
Enter fullscreen modeExit fullscreen mode

The api_grpc_web_pb created here under pb directory will be imported into the js file to be created later. Also, install the modules grpc-web and google-protobuf as they are required for webpack.

cd pbnpm install grpc-webnpm install google-protobuf
Enter fullscreen modeExit fullscreen mode

Create an html directory and create a js file.

mkdir html
Enter fullscreen modeExit fullscreen mode

[html/index.js]

import proto from '../pb/api_grpc_web_pb';var client = new proto.GreeterClient('http://localhost:8080');var request = new proto.HelloRequest();request.setName("lupin");client.hello(request, {}, function(err, response) {    if (err) {        console.log(err.code);        console.log(err.message);    } else {        console.log(response.getMessage());    }});
Enter fullscreen modeExit fullscreen mode

Proxy

Create a proxy directory and a conf directory under it for prepareing envpy proxy. Write the envoy.yaml file under the conf directory you created.

[proxy/conf/envoy.yaml]

admin:  access_log_path: /tmp/admin_access.log  address:    socket_address: { address: 127.0.0.1, port_value: 9901 }static_resources:  listeners:  - name: listener_0    address:      socket_address: { address: 127.0.0.1, port_value: 8080 }    filter_chains:    - filters:      - name: envoy.filters.network.http_connection_manager        typed_config:          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager          codec_type: auto          stat_prefix: ingress_http          access_log:            - name: envoy.access_loggers.file              typed_config:                "@type": type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog                path: "/dev/stdout"          route_config:            name: local_route            virtual_hosts:            - name: local_service              domains: ["*"]              routes:              - match: { prefix: "/" }                route:                  cluster: greeter_service                  max_grpc_timeout: 0s              cors:                allow_origin_string_match:                  - prefix: "*"                allow_methods: GET, PUT, DELETE, POST, OPTIONS                allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout                max_age: "1728000"                expose_headers: custom-header-1,grpc-status,grpc-message          http_filters:          - name: envoy.filters.http.grpc_web          - name: envoy.filters.http.cors          - name: envoy.filters.http.router  clusters:  - name: greeter_service    connect_timeout: 0.25s    type: logical_dns    http2_protocol_options: {}    lb_policy: round_robin    dns_lookup_family: V4_ONLY    upstream_connection_options:      tcp_keepalive:        keepalive_time: 300    load_assignment:      cluster_name: cluster_0      endpoints:        - lb_endpoints:            - endpoint:                address:                  socket_address:                    address: 172.17.0.1                    port_value: 8000
Enter fullscreen modeExit fullscreen mode

Administration interface of envoy is 9901 port, and envoy proxy is 8080 port. Envoy passes the received communication to the server on port 8000. The docker address may vary depending on your environment, so check it.

ip a | grep docker
Enter fullscreen modeExit fullscreen mode

Create the Docker file.
[proxy/Dockerfile]

FROM envoyproxy/envoy:v1.15.0COPY ./conf/envoy.yaml /etc/envoy/envoy.yamlCMD /usr/local/bin/envoy -c /etc/envoy/envoy.yaml
Enter fullscreen modeExit fullscreen mode

Start up the container in a proxy directory.

docker build -t envoy/hello_lupin .docker run -d --rm -p 8080:8080 -p 9901:9901 -v ~/go/prj/gRPC_prj/web_tmp/proxy/conf:/etc/envoy --name Greeter envoy/hello_lupin
Enter fullscreen modeExit fullscreen mode

Or create docker-compose.yaml in web_tmp directory.
[docker-compose.yaml]

version: '3'services:  envoy:    build:      context: ./proxy    image: hello_lupin    container_name: Greeter    ports:      - 8080:8080
Enter fullscreen modeExit fullscreen mode

Then,

docker-compose up
Enter fullscreen modeExit fullscreen mode

By the way, if you want to stop the container

docker stop Greeter
Enter fullscreen modeExit fullscreen mode

Add the webpack command and the command to build the server to the make file and run it.
[Makefile]

.PHONY: server client make_webclientserver:        go run ./server/server.goclient:         go run ./client/client.goweb_client:        cd ./html && webpack ./index.js && static -p 4444
Enter fullscreen modeExit fullscreen mode

Then,

make web_client
Enter fullscreen modeExit fullscreen mode

Access 4444 port on localhost with a browser and check the Developer Tools console.

Image description

Top comments(3)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
lorenzotinfena profile image
Lorenzo Tinfena
Pythonian, machine-learner, data structures lover. I worked with Python and C#, a little PHP, C, Java, Swift and C++

Seems to early for grpc on browser... I made an app, initially the idea was create a site with grpc, but I ended up with an app, only for the grpc native

CollapseExpand
 
umbeb profile image
Umberto Benelli
  • Joined

Hi@ikk_hck ,
it's a very interesting article!
I tried to follow this tutorial but I had a problem at the end of this steps.
When I run the following command:

make web_client

I received this error:
ERROR in ../pb/node_modules/google-protobuf/google-protobuf.js
Module not found: Error: Can't resolve './../../../html/buffer' in '/home/ubuntu/gitprojects/grpc-test/tutorialprj/pb/node_modules/google-protobuf'
@ ../pb/node_modules/google-protobuf/google-protobuf.js 1:0-33
@ ../pb/api_pb.js
@ ../pb/api_grpc_web_pb.js
@ ./index.js

It's due to "webpack ./index.js" command.

Do you know how I could fix this error?
Thank you very much!

CollapseExpand
 
umbeb profile image
Umberto Benelli
  • Joined

Solved!! According to my architecture there was an error on the url in the index.js.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Cyber Security
  • Location
    Japan
  • Joined

Trending onDEV CommunityHot

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp