From 124acba6dbb10c1d5b9f7b1566d2df1dc1042027 Mon Sep 17 00:00:00 2001 From: James Dong Date: Thu, 27 Aug 2020 17:22:40 +0000 Subject: [PATCH] Add a sample of Golang gRPC client/server programs --- demos/golang/grpc_pingpong/.gitignore | 6 ++ demos/golang/grpc_pingpong/README.md | 20 +++++++ demos/golang/grpc_pingpong/go.mod | 9 +++ demos/golang/grpc_pingpong/ping.go | 31 ++++++++++ .../grpc_pingpong/pingpong/pingpong.proto | 13 +++++ demos/golang/grpc_pingpong/pong.go | 38 +++++++++++++ .../golang/grpc_pingpong/prepare_ping_pong.sh | 56 +++++++++++++++++++ .../grpc_pingpong/run_ping_on_occlum.sh | 35 ++++++++++++ .../grpc_pingpong/run_pong_on_occlum.sh | 35 ++++++++++++ demos/golang/{ => web_server}/.gitignore | 0 demos/golang/{ => web_server}/README.md | 0 .../{ => web_server}/run_golang_on_occlum.sh | 0 demos/golang/{ => web_server}/web_server.go | 0 13 files changed, 243 insertions(+) create mode 100644 demos/golang/grpc_pingpong/.gitignore create mode 100644 demos/golang/grpc_pingpong/README.md create mode 100644 demos/golang/grpc_pingpong/go.mod create mode 100644 demos/golang/grpc_pingpong/ping.go create mode 100644 demos/golang/grpc_pingpong/pingpong/pingpong.proto create mode 100644 demos/golang/grpc_pingpong/pong.go create mode 100755 demos/golang/grpc_pingpong/prepare_ping_pong.sh create mode 100755 demos/golang/grpc_pingpong/run_ping_on_occlum.sh create mode 100755 demos/golang/grpc_pingpong/run_pong_on_occlum.sh rename demos/golang/{ => web_server}/.gitignore (100%) rename demos/golang/{ => web_server}/README.md (100%) rename demos/golang/{ => web_server}/run_golang_on_occlum.sh (100%) rename demos/golang/{ => web_server}/web_server.go (100%) diff --git a/demos/golang/grpc_pingpong/.gitignore b/demos/golang/grpc_pingpong/.gitignore new file mode 100644 index 00000000..1c514102 --- /dev/null +++ b/demos/golang/grpc_pingpong/.gitignore @@ -0,0 +1,6 @@ +occlum_ping +occlum_pong +occlum_ping_instance/ +occlum_pong_instance/ +go.sum +github.com/ diff --git a/demos/golang/grpc_pingpong/README.md b/demos/golang/grpc_pingpong/README.md new file mode 100644 index 00000000..b9101562 --- /dev/null +++ b/demos/golang/grpc_pingpong/README.md @@ -0,0 +1,20 @@ +# Use Golang and gRPC with Occlum + +This project demonstrates how Occlum enables [Golang](https://golang.org) programs with [gRPC](google.golang.org/grpc) calls running in SGX enclaves. The client program invokes a gRPC call with a ping message, and receives a pong message sent by the server program. + +Step 1: Build the Golang gRPC application using the Occlum Golang toolchain via +``` +./prepare_ping_pong.sh +``` + +Step 2: Run the gRPC server demo on Occlum via +``` +./run_pong_on_occlum.sh +``` +The gRPC server should now start to listen on port 8888 and serve incoming requests. + +Step 3: Run the gRPC client demo on Occlum via +``` +./run_ping_on_occlum.sh +``` +After the reply message is received, the latency incurred during a gRPC call will be printed out. diff --git a/demos/golang/grpc_pingpong/go.mod b/demos/golang/grpc_pingpong/go.mod new file mode 100644 index 00000000..13f0f118 --- /dev/null +++ b/demos/golang/grpc_pingpong/go.mod @@ -0,0 +1,9 @@ +module grpc_pingpong + +go 1.13 + +require ( + github.com/golang/protobuf v1.4.1 + google.golang.org/grpc v1.33.0-dev + google.golang.org/protobuf v1.25.0 +) diff --git a/demos/golang/grpc_pingpong/ping.go b/demos/golang/grpc_pingpong/ping.go new file mode 100644 index 00000000..8979b925 --- /dev/null +++ b/demos/golang/grpc_pingpong/ping.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + "time" + + "golang.org/x/net/context" + "google.golang.org/grpc" + + "grpc_pingpong/github.com/occlum/demos/grpc_pingpong/pingpong" +) + +func main() { + conn, err := grpc.Dial("localhost:8888", grpc.WithInsecure()) + if err != nil { + fmt.Printf("Failed to connect: %s\n", err) + } + defer conn.Close() + + previousTime := time.Now() + fmt.Printf("Ping: at %s\n", previousTime.Format("2006-01-02T15:04:05.999999999Z07:00")) + client := pingpong.NewPingPongServiceClient(conn) + response, err := client.PingPong(context.Background(), &pingpong.PingPongMesg{Ping: "Hello"}) + if err != nil { + fmt.Printf("Error when calling PingPongHandler: %s\n", err) + } + fmt.Printf("Pong from server: %s (at %s)\n", response.Pong, response.Timestamp) + currentTime := time.Now() + fmt.Printf("End-to-End latency is: %f Seconds\n", currentTime.Sub(previousTime).Seconds()) +} + diff --git a/demos/golang/grpc_pingpong/pingpong/pingpong.proto b/demos/golang/grpc_pingpong/pingpong/pingpong.proto new file mode 100644 index 00000000..27a2461b --- /dev/null +++ b/demos/golang/grpc_pingpong/pingpong/pingpong.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package pingpong; +option go_package = "github.com/occlum/demos/grpc_pingpong/pingpong"; + +message PingPongMesg { + string ping = 1; + string pong = 2; + string timestamp = 3; +} + +service PingPongService { + rpc PingPong(PingPongMesg) returns (PingPongMesg) {} +} diff --git a/demos/golang/grpc_pingpong/pong.go b/demos/golang/grpc_pingpong/pong.go new file mode 100644 index 00000000..f5d09109 --- /dev/null +++ b/demos/golang/grpc_pingpong/pong.go @@ -0,0 +1,38 @@ +package main + +import ( + "context" + "fmt" + "net" + "time" + + "google.golang.org/grpc" + + "grpc_pingpong/github.com/occlum/demos/grpc_pingpong/pingpong" +) + +func PingPong(ctx context.Context, in *pingpong.PingPongMesg) (*pingpong.PingPongMesg, error) { + currentTime := time.Now() + fmt.Printf("Receiving Ping: %s (at %s)\n", in.Ping, currentTime.Format("2006-01-02T15:04:05.999999999Z07:00")) + return &pingpong.PingPongMesg{Ping: in.Ping, + Pong: fmt.Sprintf("Greetings from Pong! Ping Echoed: %s", in.Ping), + Timestamp: currentTime.Format("2006-01-02T15:04:05.999999999Z07:00")}, nil + } + +func main() { + fmt.Println("grpc_pingpong server is waiting for service requests ...") + + conn, err := net.Listen("tcp", "localhost:8888") + if err != nil { + fmt.Printf("Failed to listen: %v\n", err) + } + + grpcServer := grpc.NewServer() + + pingpong.RegisterPingPongServiceService(grpcServer, &pingpong.PingPongServiceService{PingPong: PingPong}) + + if err := grpcServer.Serve(conn); err != nil { + fmt.Printf("Failed to serve: %s\n", err) + } +} + diff --git a/demos/golang/grpc_pingpong/prepare_ping_pong.sh b/demos/golang/grpc_pingpong/prepare_ping_pong.sh new file mode 100755 index 00000000..f80ea817 --- /dev/null +++ b/demos/golang/grpc_pingpong/prepare_ping_pong.sh @@ -0,0 +1,56 @@ +#!/bin/bash +set -e + +BLUE='\033[1;34m' +NC='\033[0m' + +# sanity check +FILE_SET=" +occlum_ping +occlum_pong +go.sum" +for CURR_FILE in $FILE_SET +do + if [ -f "$CURR_FILE" ]; then + rm $CURR_FILE + fi +done + +DIR_SET=" +github.com +occlum_ping_instance +occlum_pong_instance" +for CURR_DIR in $DIR_SET +do + if [ -d "$CURR_DIR" ]; then + rm -fr $CURR_DIR + fi +done + +# enable Go modules for package management +export GO111MODULE=on + +# update PATH so that the protoc compiler can find the plugin: +export PATH="$PATH:$(go env GOPATH)/bin" + +# assume that protoc is installed +if ! type "protoc" > /dev/null 2>&1; then + echo "Please install protoc" + exit 1 +fi + +# install protoc-gen-go and protoc-gen-go-grpc plugin +if ! type "protoc-gen-go" > /dev/null 2>&1; then + go get google.golang.org/protobuf/cmd/protoc-gen-go +fi +if ! type "protoc-gen-go-grpc" > /dev/null 2>&1; then + go get google.golang.org/grpc/cmd/protoc-gen-go-grpc +fi + +# compiling pingpong gRPC .proto file +export GOPRIVATE=github.com/occlum/demos/\* +protoc --proto_path=pingpong --go-grpc_out=. --go_out=. pingpong/pingpong.proto + +# prepare occlum images +occlum-go build -o occlum_pong pong.go +occlum-go build -o occlum_ping ping.go diff --git a/demos/golang/grpc_pingpong/run_ping_on_occlum.sh b/demos/golang/grpc_pingpong/run_ping_on_occlum.sh new file mode 100755 index 00000000..ef9c72e5 --- /dev/null +++ b/demos/golang/grpc_pingpong/run_ping_on_occlum.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e + +BLUE='\033[1;34m' +NC='\033[0m' + +occlum_ping="./occlum_ping" + +if [ ! -f $occlum_ping ];then + echo "Error: cannot stat file '$occlum_ping'" + echo "Please see README and build it using prepare_ping_pong.sh" + exit 1 +fi + +# Init Occlum Workspace +rm -rf occlum_ping_instance && mkdir occlum_ping_instance +cd occlum_ping_instance +occlum init +new_json="$(jq '.resource_limits.user_space_size = "2560MB" | + .resource_limits.kernel_space_heap_size="320MB" | + .resource_limits.kernel_space_stack_size="10MB" | + .process.default_stack_size = "40MB" | + .process.default_heap_size = "320MB" | + .process.default_mmap_size = "960MB" ' Occlum.json)" && \ +echo "${new_json}" > Occlum.json + +# 2. Copy program into Occlum Workspace and build +cp ../occlum_ping image/bin +mkdir image/etc/ +cp /etc/hosts image/etc/ +occlum build + +# 3. Run the hello world sample +echo -e "${BLUE}occlum run /bin/occlum_ping${NC}" +time occlum run /bin/occlum_ping diff --git a/demos/golang/grpc_pingpong/run_pong_on_occlum.sh b/demos/golang/grpc_pingpong/run_pong_on_occlum.sh new file mode 100755 index 00000000..cc6c91d4 --- /dev/null +++ b/demos/golang/grpc_pingpong/run_pong_on_occlum.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -e + +BLUE='\033[1;34m' +NC='\033[0m' + +occlum_pong="./occlum_pong" + +if [ ! -f $occlum_pong ];then + echo "Error: cannot stat file '$occlum_pong'" + echo "Please see README and build it using prepare_pong_pong.sh" + exit 1 +fi + +# Init Occlum Workspace +rm -rf occlum_pong_instance && mkdir occlum_pong_instance +cd occlum_pong_instance +occlum init +new_json="$(jq '.resource_limits.user_space_size = "2560MB" | + .resource_limits.kernel_space_heap_size="320MB" | + .resource_limits.kernel_space_stack_size="10MB" | + .process.default_stack_size = "40MB" | + .process.default_heap_size = "320MB" | + .process.default_mmap_size = "960MB" ' Occlum.json)" && \ +echo "${new_json}" > Occlum.json + +# 2. Copy program into Occlum Workspace and build +cp ../occlum_pong image/bin +mkdir image/etc/ +cp /etc/hosts image/etc/ +occlum build + +# 3. Run the hello world sample +echo -e "${BLUE}occlum run /bin/occlum_pong${NC}" +time occlum run /bin/occlum_pong diff --git a/demos/golang/.gitignore b/demos/golang/web_server/.gitignore similarity index 100% rename from demos/golang/.gitignore rename to demos/golang/web_server/.gitignore diff --git a/demos/golang/README.md b/demos/golang/web_server/README.md similarity index 100% rename from demos/golang/README.md rename to demos/golang/web_server/README.md diff --git a/demos/golang/run_golang_on_occlum.sh b/demos/golang/web_server/run_golang_on_occlum.sh similarity index 100% rename from demos/golang/run_golang_on_occlum.sh rename to demos/golang/web_server/run_golang_on_occlum.sh diff --git a/demos/golang/web_server.go b/demos/golang/web_server/web_server.go similarity index 100% rename from demos/golang/web_server.go rename to demos/golang/web_server/web_server.go